diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-02-12 16:42:50 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-02-12 16:42:50 +0000 |
commit | 628a746cf0d380ba8fc0fff2926c899e323768a7 (patch) | |
tree | afd8e3fe07ce89f9dad65a2b2548ad9e34c6deaf | |
parent | a4550442b947d2c2b346bd2efc8fe3da16425f4d (diff) | |
parent | e96126ffa53d36ec75a1ee900a6b7e7c82d9bb9c (diff) | |
download | hqemu-628a746cf0d380ba8fc0fff2926c899e323768a7.zip hqemu-628a746cf0d380ba8fc0fff2926c899e323768a7.tar.gz |
Merge remote-tracking branch 'remotes/kevin/tags/for-anthony' into staging
Block patches
# gpg: Signature made Sun 09 Feb 2014 08:12:51 GMT using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"
* remotes/kevin/tags/for-anthony:
block: Fix 32 bit truncation in mark_request_serialising()
blkdebug: Don't leak bs->file on failure
block: Don't call ROUND_UP with negative values
block: bdrv_aligned_pwritev: Assert overlap range
block: Fix memory leaks in bdrv_co_do_pwritev()
raw: Fix BlockLimits passthrough
qemu-iotests: add test for qcow2 preallocation with different cluster sizes
qcow2: check for NULL l2meta
qcow2: fix offset overflow in qcow2_alloc_clusters_at()
qcow2: remove n_start and n_end of qcow2_alloc_cluster_offset()
block/iscsi: always fill bs->bl.opt_transfer_length
block: Fail gracefully with missing filename
qemu-iotests: enable support for NFS protocol
qemu-iotests: enable test 016 and 025 to work with NFS protocol
qemu-iotests: blacklist test 020 for NFS protocol
qemu-iotests: change _supported_proto to file for various tests
block: add native support for NFS
qemu-iotest: Make 077 raw-only
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
50 files changed, 730 insertions, 84 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index adc5973..026ea4f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -937,6 +937,11 @@ M: Peter Lieven <pl@kamp.de> S: Supported F: block/iscsi.c +NFS +M: Peter Lieven <pl@kamp.de> +S: Maintained +F: block/nfs.c + SSH M: Richard W.M. Jones <rjones@redhat.com> S: Supported @@ -832,6 +832,12 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, filename = qdict_get_try_str(options, "filename"); } + if (drv->bdrv_needs_filename && !filename) { + error_setg(errp, "The '%s' block driver requires a file name", + drv->format_name); + return -EINVAL; + } + trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name); node_name = qdict_get_try_str(options, "node-name"); @@ -1031,11 +1037,6 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, goto fail; } qdict_del(options, "filename"); - } else if (drv->bdrv_needs_filename && !filename) { - error_setg(errp, "The '%s' block driver requires a file name", - drv->format_name); - ret = -EINVAL; - goto fail; } if (!drv->bdrv_file_open) { @@ -2239,11 +2240,11 @@ static void tracked_request_begin(BdrvTrackedRequest *req, QLIST_INSERT_HEAD(&bs->tracked_requests, req, list); } -static void mark_request_serialising(BdrvTrackedRequest *req, size_t align) +static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align) { int64_t overlap_offset = req->offset & ~(align - 1); - int overlap_bytes = ROUND_UP(req->offset + req->bytes, align) - - overlap_offset; + unsigned int overlap_bytes = ROUND_UP(req->offset + req->bytes, align) + - overlap_offset; if (!req->serialising) { req->bs->serialising_in_flight++; @@ -2914,8 +2915,8 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs, } total_sectors = DIV_ROUND_UP(len, BDRV_SECTOR_SIZE); - max_nb_sectors = MAX(0, ROUND_UP(total_sectors - sector_num, - align >> BDRV_SECTOR_BITS)); + max_nb_sectors = ROUND_UP(MAX(0, total_sectors - sector_num), + align >> BDRV_SECTOR_BITS); if (max_nb_sectors > 0) { ret = drv->bdrv_co_readv(bs, sector_num, MIN(nb_sectors, max_nb_sectors), qiov); @@ -3133,6 +3134,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs, waited = wait_serialising_requests(req); assert(!waited || !req->serialising); + assert(req->overlap_offset <= offset); + assert(offset + bytes <= req->overlap_offset + req->overlap_bytes); ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req); @@ -3278,9 +3281,9 @@ fail: if (use_local_qiov) { qemu_iovec_destroy(&local_qiov); - qemu_vfree(head_buf); - qemu_vfree(tail_buf); } + qemu_vfree(head_buf); + qemu_vfree(tail_buf); return ret; } diff --git a/block/Makefile.objs b/block/Makefile.objs index 4e8c91e..e254a21 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -12,6 +12,7 @@ block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o ifeq ($(CONFIG_POSIX),y) block-obj-y += nbd.o nbd-client.o sheepdog.o block-obj-$(CONFIG_LIBISCSI) += iscsi.o +block-obj-$(CONFIG_LIBNFS) += nfs.o block-obj-$(CONFIG_CURL) += curl.o block-obj-$(CONFIG_RBD) += rbd.o block-obj-$(CONFIG_GLUSTERFS) += gluster.o diff --git a/block/blkdebug.c b/block/blkdebug.c index 56c4cd0..8eb0db0 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -396,14 +396,14 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, if (error_is_set(&local_err)) { error_propagate(errp, local_err); ret = -EINVAL; - goto fail; + goto out; } /* Read rules from config file or command line options */ config = qemu_opt_get(opts, "config"); ret = read_config(s, config, options, errp); if (ret) { - goto fail; + goto out; } /* Set initial state */ @@ -414,7 +414,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, flags, true, false, &local_err); if (ret < 0) { error_propagate(errp, local_err); - goto fail; + goto out; } /* Set request alignment */ @@ -424,11 +424,15 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, } else { error_setg(errp, "Invalid alignment"); ret = -EINVAL; - goto fail; + goto fail_unref; } ret = 0; -fail: + goto out; + +fail_unref: + bdrv_unref(bs->file); +out: qemu_opts_del(opts); return ret; } diff --git a/block/iscsi.c b/block/iscsi.c index 6f4af72..8d0f966 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1330,10 +1330,9 @@ static int iscsi_refresh_limits(BlockDriverState *bs) } bs->bl.write_zeroes_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran, iscsilun); - - bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len, - iscsilun); } + bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len, + iscsilun); return 0; } diff --git a/block/nfs.c b/block/nfs.c new file mode 100644 index 0000000..ef731f0 --- /dev/null +++ b/block/nfs.c @@ -0,0 +1,439 @@ +/* + * QEMU Block driver for native access to files on NFS shares + * + * Copyright (c) 2014 Peter Lieven <pl@kamp.de> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "config-host.h" + +#include <poll.h> +#include "qemu-common.h" +#include "qemu/config-file.h" +#include "qemu/error-report.h" +#include "block/block_int.h" +#include "trace.h" +#include "qemu/iov.h" +#include "qemu/uri.h" +#include "sysemu/sysemu.h" +#include <nfsc/libnfs.h> + +typedef struct NFSClient { + struct nfs_context *context; + struct nfsfh *fh; + int events; + bool has_zero_init; +} NFSClient; + +typedef struct NFSRPC { + int ret; + int complete; + QEMUIOVector *iov; + struct stat *st; + Coroutine *co; + QEMUBH *bh; +} NFSRPC; + +static void nfs_process_read(void *arg); +static void nfs_process_write(void *arg); + +static void nfs_set_events(NFSClient *client) +{ + int ev = nfs_which_events(client->context); + if (ev != client->events) { + qemu_aio_set_fd_handler(nfs_get_fd(client->context), + (ev & POLLIN) ? nfs_process_read : NULL, + (ev & POLLOUT) ? nfs_process_write : NULL, + client); + + } + client->events = ev; +} + +static void nfs_process_read(void *arg) +{ + NFSClient *client = arg; + nfs_service(client->context, POLLIN); + nfs_set_events(client); +} + +static void nfs_process_write(void *arg) +{ + NFSClient *client = arg; + nfs_service(client->context, POLLOUT); + nfs_set_events(client); +} + +static void nfs_co_init_task(NFSClient *client, NFSRPC *task) +{ + *task = (NFSRPC) { + .co = qemu_coroutine_self(), + }; +} + +static void nfs_co_generic_bh_cb(void *opaque) +{ + NFSRPC *task = opaque; + qemu_bh_delete(task->bh); + qemu_coroutine_enter(task->co, NULL); +} + +static void +nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data, + void *private_data) +{ + NFSRPC *task = private_data; + task->complete = 1; + task->ret = ret; + if (task->ret > 0 && task->iov) { + if (task->ret <= task->iov->size) { + qemu_iovec_from_buf(task->iov, 0, data, task->ret); + } else { + task->ret = -EIO; + } + } + if (task->ret == 0 && task->st) { + memcpy(task->st, data, sizeof(struct stat)); + } + if (task->co) { + task->bh = qemu_bh_new(nfs_co_generic_bh_cb, task); + qemu_bh_schedule(task->bh); + } +} + +static int coroutine_fn nfs_co_readv(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, + QEMUIOVector *iov) +{ + NFSClient *client = bs->opaque; + NFSRPC task; + + nfs_co_init_task(client, &task); + task.iov = iov; + + if (nfs_pread_async(client->context, client->fh, + sector_num * BDRV_SECTOR_SIZE, + nb_sectors * BDRV_SECTOR_SIZE, + nfs_co_generic_cb, &task) != 0) { + return -ENOMEM; + } + + while (!task.complete) { + nfs_set_events(client); + qemu_coroutine_yield(); + } + + if (task.ret < 0) { + return task.ret; + } + + /* zero pad short reads */ + if (task.ret < iov->size) { + qemu_iovec_memset(iov, task.ret, 0, iov->size - task.ret); + } + + return 0; +} + +static int coroutine_fn nfs_co_writev(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, + QEMUIOVector *iov) +{ + NFSClient *client = bs->opaque; + NFSRPC task; + char *buf = NULL; + + nfs_co_init_task(client, &task); + + buf = g_malloc(nb_sectors * BDRV_SECTOR_SIZE); + qemu_iovec_to_buf(iov, 0, buf, nb_sectors * BDRV_SECTOR_SIZE); + + if (nfs_pwrite_async(client->context, client->fh, + sector_num * BDRV_SECTOR_SIZE, + nb_sectors * BDRV_SECTOR_SIZE, + buf, nfs_co_generic_cb, &task) != 0) { + g_free(buf); + return -ENOMEM; + } + + while (!task.complete) { + nfs_set_events(client); + qemu_coroutine_yield(); + } + + g_free(buf); + + if (task.ret != nb_sectors * BDRV_SECTOR_SIZE) { + return task.ret < 0 ? task.ret : -EIO; + } + + return 0; +} + +static int coroutine_fn nfs_co_flush(BlockDriverState *bs) +{ + NFSClient *client = bs->opaque; + NFSRPC task; + + nfs_co_init_task(client, &task); + + if (nfs_fsync_async(client->context, client->fh, nfs_co_generic_cb, + &task) != 0) { + return -ENOMEM; + } + + while (!task.complete) { + nfs_set_events(client); + qemu_coroutine_yield(); + } + + return task.ret; +} + +/* TODO Convert to fine grained options */ +static QemuOptsList runtime_opts = { + .name = "nfs", + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), + .desc = { + { + .name = "filename", + .type = QEMU_OPT_STRING, + .help = "URL to the NFS file", + }, + { /* end of list */ } + }, +}; + +static void nfs_client_close(NFSClient *client) +{ + if (client->context) { + if (client->fh) { + nfs_close(client->context, client->fh); + } + qemu_aio_set_fd_handler(nfs_get_fd(client->context), NULL, NULL, NULL); + nfs_destroy_context(client->context); + } + memset(client, 0, sizeof(NFSClient)); +} + +static void nfs_file_close(BlockDriverState *bs) +{ + NFSClient *client = bs->opaque; + nfs_client_close(client); +} + +static int64_t nfs_client_open(NFSClient *client, const char *filename, + int flags, Error **errp) +{ + int ret = -EINVAL, i; + struct stat st; + URI *uri; + QueryParams *qp = NULL; + char *file = NULL, *strp = NULL; + + uri = uri_parse(filename); + if (!uri) { + error_setg(errp, "Invalid URL specified"); + goto fail; + } + strp = strrchr(uri->path, '/'); + if (strp == NULL) { + error_setg(errp, "Invalid URL specified"); + goto fail; + } + file = g_strdup(strp); + *strp = 0; + + client->context = nfs_init_context(); + if (client->context == NULL) { + error_setg(errp, "Failed to init NFS context"); + goto fail; + } + + qp = query_params_parse(uri->query); + for (i = 0; i < qp->n; i++) { + if (!qp->p[i].value) { + error_setg(errp, "Value for NFS parameter expected: %s", + qp->p[i].name); + goto fail; + } + if (!strncmp(qp->p[i].name, "uid", 3)) { + nfs_set_uid(client->context, atoi(qp->p[i].value)); + } else if (!strncmp(qp->p[i].name, "gid", 3)) { + nfs_set_gid(client->context, atoi(qp->p[i].value)); + } else if (!strncmp(qp->p[i].name, "tcp-syncnt", 10)) { + nfs_set_tcp_syncnt(client->context, atoi(qp->p[i].value)); + } else { + error_setg(errp, "Unknown NFS parameter name: %s", + qp->p[i].name); + goto fail; + } + } + + ret = nfs_mount(client->context, uri->server, uri->path); + if (ret < 0) { + error_setg(errp, "Failed to mount nfs share: %s", + nfs_get_error(client->context)); + goto fail; + } + + if (flags & O_CREAT) { + ret = nfs_creat(client->context, file, 0600, &client->fh); + if (ret < 0) { + error_setg(errp, "Failed to create file: %s", + nfs_get_error(client->context)); + goto fail; + } + } else { + ret = nfs_open(client->context, file, flags, &client->fh); + if (ret < 0) { + error_setg(errp, "Failed to open file : %s", + nfs_get_error(client->context)); + goto fail; + } + } + + ret = nfs_fstat(client->context, client->fh, &st); + if (ret < 0) { + error_setg(errp, "Failed to fstat file: %s", + nfs_get_error(client->context)); + goto fail; + } + + ret = DIV_ROUND_UP(st.st_size, BDRV_SECTOR_SIZE); + client->has_zero_init = S_ISREG(st.st_mode); + goto out; +fail: + nfs_client_close(client); +out: + if (qp) { + query_params_free(qp); + } + uri_free(uri); + g_free(file); + return ret; +} + +static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) { + NFSClient *client = bs->opaque; + int64_t ret; + QemuOpts *opts; + Error *local_err = NULL; + + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (error_is_set(&local_err)) { + error_propagate(errp, local_err); + return -EINVAL; + } + ret = nfs_client_open(client, qemu_opt_get(opts, "filename"), + (flags & BDRV_O_RDWR) ? O_RDWR : O_RDONLY, + errp); + if (ret < 0) { + return ret; + } + bs->total_sectors = ret; + return 0; +} + +static int nfs_file_create(const char *url, QEMUOptionParameter *options, + Error **errp) +{ + int ret = 0; + int64_t total_size = 0; + NFSClient *client = g_malloc0(sizeof(NFSClient)); + + /* Read out options */ + while (options && options->name) { + if (!strcmp(options->name, "size")) { + total_size = options->value.n; + } + options++; + } + + ret = nfs_client_open(client, url, O_CREAT, errp); + if (ret < 0) { + goto out; + } + ret = nfs_ftruncate(client->context, client->fh, total_size); + nfs_client_close(client); +out: + g_free(client); + return ret; +} + +static int nfs_has_zero_init(BlockDriverState *bs) +{ + NFSClient *client = bs->opaque; + return client->has_zero_init; +} + +static int64_t nfs_get_allocated_file_size(BlockDriverState *bs) +{ + NFSClient *client = bs->opaque; + NFSRPC task = {0}; + struct stat st; + + task.st = &st; + if (nfs_fstat_async(client->context, client->fh, nfs_co_generic_cb, + &task) != 0) { + return -ENOMEM; + } + + while (!task.complete) { + nfs_set_events(client); + qemu_aio_wait(); + } + + return (task.ret < 0 ? task.ret : st.st_blocks * st.st_blksize); +} + +static int nfs_file_truncate(BlockDriverState *bs, int64_t offset) +{ + NFSClient *client = bs->opaque; + return nfs_ftruncate(client->context, client->fh, offset); +} + +static BlockDriver bdrv_nfs = { + .format_name = "nfs", + .protocol_name = "nfs", + + .instance_size = sizeof(NFSClient), + .bdrv_needs_filename = true, + .bdrv_has_zero_init = nfs_has_zero_init, + .bdrv_get_allocated_file_size = nfs_get_allocated_file_size, + .bdrv_truncate = nfs_file_truncate, + + .bdrv_file_open = nfs_file_open, + .bdrv_close = nfs_file_close, + .bdrv_create = nfs_file_create, + + .bdrv_co_readv = nfs_co_readv, + .bdrv_co_writev = nfs_co_writev, + .bdrv_co_flush_to_disk = nfs_co_flush, +}; + +static void nfs_block_init(void) +{ + bdrv_register(&bdrv_nfs); +} + +block_init(nfs_block_init); diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 8534084..c57f39d 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1182,7 +1182,7 @@ fail: * Return 0 on success and -errno in error cases */ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, - int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m) + int *num, uint64_t *host_offset, QCowL2Meta **m) { BDRVQcowState *s = bs->opaque; uint64_t start, remaining; @@ -1190,15 +1190,13 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, uint64_t cur_bytes; int ret; - trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset, - n_start, n_end); + trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset, *num); - assert(n_start * BDRV_SECTOR_SIZE == offset_into_cluster(s, offset)); - offset = start_of_cluster(s, offset); + assert((offset & ~BDRV_SECTOR_MASK) == 0); again: - start = offset + (n_start << BDRV_SECTOR_BITS); - remaining = (n_end - n_start) << BDRV_SECTOR_BITS; + start = offset; + remaining = *num << BDRV_SECTOR_BITS; cluster_offset = 0; *host_offset = 0; cur_bytes = 0; @@ -1284,7 +1282,7 @@ again: } } - *num = (n_end - n_start) - (remaining >> BDRV_SECTOR_BITS); + *num -= remaining >> BDRV_SECTOR_BITS; assert(*num > 0); assert(*host_offset != 0); diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index c974abe..8712d8b 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -676,7 +676,13 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset, BDRVQcowState *s = bs->opaque; uint64_t cluster_index; uint64_t old_free_cluster_index; - int i, refcount, ret; + uint64_t i; + int refcount, ret; + + assert(nb_clusters >= 0); + if (nb_clusters == 0) { + return 0; + } /* Check how many clusters there are free */ cluster_index = offset >> s->cluster_bits; diff --git a/block/qcow2.c b/block/qcow2.c index 99a1ad1..0b4335c 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1000,7 +1000,6 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, { BDRVQcowState *s = bs->opaque; int index_in_cluster; - int n_end; int ret; int cur_nr_sectors; /* number of sectors in current iteration */ uint64_t cluster_offset; @@ -1024,14 +1023,16 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, trace_qcow2_writev_start_part(qemu_coroutine_self()); index_in_cluster = sector_num & (s->cluster_sectors - 1); - n_end = index_in_cluster + remaining_sectors; + cur_nr_sectors = remaining_sectors; if (s->crypt_method && - n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors) { - n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors; + cur_nr_sectors > + QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster) { + cur_nr_sectors = + QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster; } ret = qcow2_alloc_cluster_offset(bs, sector_num << 9, - index_in_cluster, n_end, &cur_nr_sectors, &cluster_offset, &l2meta); + &cur_nr_sectors, &cluster_offset, &l2meta); if (ret < 0) { goto fail; } @@ -1403,34 +1404,34 @@ static int preallocate(BlockDriverState *bs) int ret; QCowL2Meta *meta; - nb_sectors = bdrv_getlength(bs) >> 9; + nb_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; offset = 0; while (nb_sectors) { - num = MIN(nb_sectors, INT_MAX >> 9); - ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num, + num = MIN(nb_sectors, INT_MAX >> BDRV_SECTOR_BITS); + ret = qcow2_alloc_cluster_offset(bs, offset, &num, &host_offset, &meta); if (ret < 0) { return ret; } - ret = qcow2_alloc_cluster_link_l2(bs, meta); - if (ret < 0) { - qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters, - QCOW2_DISCARD_NEVER); - return ret; - } - - /* There are no dependent requests, but we need to remove our request - * from the list of in-flight requests */ if (meta != NULL) { + ret = qcow2_alloc_cluster_link_l2(bs, meta); + if (ret < 0) { + qcow2_free_any_clusters(bs, meta->alloc_offset, + meta->nb_clusters, QCOW2_DISCARD_NEVER); + return ret; + } + + /* There are no dependent requests, but we need to remove our + * request from the list of in-flight requests */ QLIST_REMOVE(meta, next_in_flight); } /* TODO Preallocate data if requested */ nb_sectors -= num; - offset += num << 9; + offset += num << BDRV_SECTOR_BITS; } /* @@ -1439,9 +1440,10 @@ static int preallocate(BlockDriverState *bs) * EOF). Extend the image to the last allocated sector. */ if (host_offset != 0) { - uint8_t buf[512]; - memset(buf, 0, 512); - ret = bdrv_write(bs->file, (host_offset >> 9) + num - 1, buf, 1); + uint8_t buf[BDRV_SECTOR_SIZE]; + memset(buf, 0, BDRV_SECTOR_SIZE); + ret = bdrv_write(bs->file, (host_offset >> BDRV_SECTOR_BITS) + num - 1, + buf, 1); if (ret < 0) { return ret; } diff --git a/block/qcow2.h b/block/qcow2.h index b5b7d13..0b0eac8 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -468,7 +468,7 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num, int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, int *num, uint64_t *cluster_offset); int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, - int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m); + int *num, uint64_t *host_offset, QCowL2Meta **m); uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offset, int compressed_size); diff --git a/block/raw_bsd.c b/block/raw_bsd.c index 978ae7a..af8706d 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -90,6 +90,12 @@ static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return bdrv_get_info(bs->file, bdi); } +static int raw_refresh_limits(BlockDriverState *bs) +{ + bs->bl = bs->file->bl; + return 0; +} + static int raw_truncate(BlockDriverState *bs, int64_t offset) { return bdrv_truncate(bs->file, offset); @@ -150,7 +156,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { bs->sg = bs->file->sg; - bs->bl = bs->file->bl; return 0; } @@ -182,6 +187,7 @@ static BlockDriver bdrv_raw = { .bdrv_getlength = &raw_getlength, .has_variable_length = true, .bdrv_get_info = &raw_get_info, + .bdrv_refresh_limits = &raw_refresh_limits, .bdrv_is_inserted = &raw_is_inserted, .bdrv_media_changed = &raw_media_changed, .bdrv_eject = &raw_eject, @@ -251,6 +251,7 @@ vss_win32_sdk="" win_sdk="no" want_tools="yes" libiscsi="" +libnfs="" coroutine="" coroutine_pool="" seccomp="" @@ -840,6 +841,10 @@ for opt do ;; --enable-libiscsi) libiscsi="yes" ;; + --disable-libnfs) libnfs="no" + ;; + --enable-libnfs) libnfs="yes" + ;; --enable-profiler) profiler="yes" ;; --disable-cocoa) cocoa="no" @@ -1229,6 +1234,8 @@ Advanced options (experts only): --enable-rbd enable building the rados block device (rbd) --disable-libiscsi disable iscsi support --enable-libiscsi enable iscsi support + --disable-libnfs disable nfs support + --enable-libnfs enable nfs support --disable-smartcard-nss disable smartcard nss support --enable-smartcard-nss enable smartcard nss support --disable-libusb disable libusb (for usb passthrough) @@ -3600,6 +3607,20 @@ elif test "$debug" = "no" ; then CFLAGS="-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS" fi +########################################## +# Do we have libnfs +if test "$libnfs" != "no" ; then + if $pkg_config --atleast-version=1.9.2 libnfs; then + libnfs="yes" + libnfs_libs=$($pkg_config --libs libnfs) + LIBS="$LIBS $libnfs_libs" + else + if test "$libnfs" = "yes" ; then + feature_not_found "libnfs" + fi + libnfs="no" + fi +fi # Disable zero malloc errors for official releases unless explicitly told to # enable/disable @@ -3829,6 +3850,7 @@ echo "libiscsi support $libiscsi (1.4.0)" else echo "libiscsi support $libiscsi" fi +echo "libnfs support $libnfs" echo "build guest agent $guest_agent" echo "QGA VSS support $guest_agent_with_vss" echo "seccomp support $seccomp" @@ -4165,6 +4187,10 @@ if test "$libiscsi" = "yes" ; then fi fi +if test "$libnfs" = "yes" ; then + echo "CONFIG_LIBNFS=y" >> $config_host_mak +fi + if test "$seccomp" = "yes"; then echo "CONFIG_SECCOMP=y" >> $config_host_mak fi diff --git a/qapi-schema.json b/qapi-schema.json index 05ced9d..7cfb5e5 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -4371,6 +4371,7 @@ # TODO gluster: Wait for structured options # TODO iscsi: Wait for structured options # TODO nbd: Should take InetSocketAddress for 'host'? +# TODO nfs: Wait for structured options # TODO rbd: Wait for structured options # TODO sheepdog: Wait for structured options # TODO ssh: Should take InetSocketAddress for 'host'? diff --git a/tests/qemu-iotests/013 b/tests/qemu-iotests/013 index 389f4b8..ea3cab9 100755 --- a/tests/qemu-iotests/013 +++ b/tests/qemu-iotests/013 @@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # much of this could be generic for any format supporting compression. _supported_fmt qcow qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux TEST_OFFSETS="0 4294967296" diff --git a/tests/qemu-iotests/014 b/tests/qemu-iotests/014 index 0edeb4b..b23c2db 100755 --- a/tests/qemu-iotests/014 +++ b/tests/qemu-iotests/014 @@ -43,7 +43,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # much of this could be generic for any format supporting snapshots _supported_fmt qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux TEST_OFFSETS="0 4294967296" diff --git a/tests/qemu-iotests/016 b/tests/qemu-iotests/016 index b87a32b..7ea9e94 100755 --- a/tests/qemu-iotests/016 +++ b/tests/qemu-iotests/016 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt raw -_supported_proto file sheepdog +_supported_proto file sheepdog nfs _supported_os Linux diff --git a/tests/qemu-iotests/018 b/tests/qemu-iotests/018 index 6f7f054..d8a7d43 100755 --- a/tests/qemu-iotests/018 +++ b/tests/qemu-iotests/018 @@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # Any format supporting backing files _supported_fmt qcow qcow2 vmdk qed -_supported_proto generic +_supported_proto file _supported_os Linux _unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019 index b43e70f..e67445c 100755 --- a/tests/qemu-iotests/019 +++ b/tests/qemu-iotests/019 @@ -45,7 +45,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # Any format supporting backing files _supported_fmt qcow qcow2 vmdk qed -_supported_proto generic +_supported_proto file _supported_os Linux _unsupported_imgopts "subformat=monolithicFlat" \ "subformat=twoGbMaxExtentFlat" \ diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020 index 73a0429..2f258dc 100755 --- a/tests/qemu-iotests/020 +++ b/tests/qemu-iotests/020 @@ -49,6 +49,11 @@ _unsupported_imgopts "subformat=monolithicFlat" \ "subformat=twoGbMaxExtentFlat" \ "subformat=twoGbMaxExtentSparse" +# NFS does not support bdrv_reopen_prepare thus qemu-img commit fails. +if [ "$IMGPROTO" = "nfs" ]; then + _notrun "image protocol $IMGPROTO does not support bdrv_commit" +fi + TEST_OFFSETS="0 4294967296" _make_test_img 6G diff --git a/tests/qemu-iotests/023 b/tests/qemu-iotests/023 index 090ed23..9ad06b9 100755 --- a/tests/qemu-iotests/023 +++ b/tests/qemu-iotests/023 @@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # much of this could be generic for any format supporting compression. _supported_fmt qcow qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux TEST_OFFSETS="0 4294967296" diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024 index be974f0..9bf99e1 100755 --- a/tests/qemu-iotests/024 +++ b/tests/qemu-iotests/024 @@ -43,7 +43,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # Currently only qcow2 and qed support rebasing _supported_fmt qcow2 qed -_supported_proto generic +_supported_proto file _supported_os Linux CLUSTER_SIZE=65536 diff --git a/tests/qemu-iotests/025 b/tests/qemu-iotests/025 index 9426c93..a5f45b4 100755 --- a/tests/qemu-iotests/025 +++ b/tests/qemu-iotests/025 @@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.pattern _supported_fmt raw qcow2 qed -_supported_proto file sheepdog rbd +_supported_proto file sheepdog rbd nfs _supported_os Linux echo "=== Creating image" diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026 index c9c5f83..df2884b 100755 --- a/tests/qemu-iotests/026 +++ b/tests/qemu-iotests/026 @@ -42,7 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # Currently only qcow2 supports rebasing _supported_fmt qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux _default_cache_mode "writethrough" _supported_cache_modes "writethrough" "none" diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028 index 93a9fa6..a99e4fa 100755 --- a/tests/qemu-iotests/028 +++ b/tests/qemu-iotests/028 @@ -45,7 +45,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # Any format supporting backing files except vmdk and qcow which do not support # smaller backing files. _supported_fmt qcow2 qed -_supported_proto generic +_supported_proto file _supported_os Linux # Choose a size that is not necessarily a cluster size multiple for image diff --git a/tests/qemu-iotests/031 b/tests/qemu-iotests/031 index c9070b0..1d920ea 100755 --- a/tests/qemu-iotests/031 +++ b/tests/qemu-iotests/031 @@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # This tests qcow2-specific low-level functionality _supported_fmt qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux CLUSTER_SIZE=65536 diff --git a/tests/qemu-iotests/034 b/tests/qemu-iotests/034 index 7349789..69c7858 100755 --- a/tests/qemu-iotests/034 +++ b/tests/qemu-iotests/034 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt qcow qcow2 vmdk qed -_supported_proto generic +_supported_proto file _supported_os Linux _unsupported_imgopts "subformat=monolithicFlat" \ "subformat=twoGbMaxExtentFlat" \ diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036 index e049a64..03b6aa9 100755 --- a/tests/qemu-iotests/036 +++ b/tests/qemu-iotests/036 @@ -44,7 +44,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # This tests qcow2-specific low-level functionality _supported_fmt qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux # Only qcow2v3 and later supports feature bits diff --git a/tests/qemu-iotests/037 b/tests/qemu-iotests/037 index e444349..9171d8c 100755 --- a/tests/qemu-iotests/037 +++ b/tests/qemu-iotests/037 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt qcow qcow2 vmdk qed -_supported_proto generic +_supported_proto file _supported_os Linux _unsupported_imgopts "subformat=monolithicFlat" \ "subformat=twoGbMaxExtentFlat" \ diff --git a/tests/qemu-iotests/038 b/tests/qemu-iotests/038 index 7bb7906..cfaf00a 100755 --- a/tests/qemu-iotests/038 +++ b/tests/qemu-iotests/038 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt qcow2 qed -_supported_proto generic +_supported_proto file _supported_os Linux CLUSTER_SIZE=2M diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039 index 6abf472..9b355c0 100755 --- a/tests/qemu-iotests/039 +++ b/tests/qemu-iotests/039 @@ -42,7 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux _default_cache_mode "writethrough" _supported_cache_modes "writethrough" diff --git a/tests/qemu-iotests/043 b/tests/qemu-iotests/043 index d7f1231..b316b97 100755 --- a/tests/qemu-iotests/043 +++ b/tests/qemu-iotests/043 @@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # Any format supporting backing files _supported_fmt qcow2 qed -_supported_proto generic +_supported_proto file _supported_os Linux diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046 index 3f17ceb..2d44bbb 100755 --- a/tests/qemu-iotests/046 +++ b/tests/qemu-iotests/046 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux CLUSTER_SIZE=64k diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index b23d91b..46345fb 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -172,6 +172,18 @@ run_qemu -drive file="$TEST_IMG",file.driver=file run_qemu -drive file="$TEST_IMG",file.driver=qcow2 echo +echo === Leaving out required options === +echo + +run_qemu -drive driver=file +run_qemu -drive driver=nbd +run_qemu -drive driver=raw +run_qemu -drive file.driver=file +run_qemu -drive file.driver=nbd +run_qemu -drive file.driver=raw +run_qemu -drive foo=bar + +echo echo === Parsing protocol from file name === echo diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index d0c5173..30e2dbd 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -225,6 +225,30 @@ Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: could not open disk image TEST_DIR/t.qcow2: Block format 'qcow2' used by device '' doesn't support the option 'filename' +=== Leaving out required options === + +Testing: -drive driver=file +QEMU_PROG: -drive driver=file: could not open disk image ide0-hd0: The 'file' block driver requires a file name + +Testing: -drive driver=nbd +QEMU_PROG: -drive driver=nbd: could not open disk image ide0-hd0: Could not open image: Invalid argument + +Testing: -drive driver=raw +QEMU_PROG: -drive driver=raw: could not open disk image ide0-hd0: Can't use 'raw' as a block driver for the protocol level + +Testing: -drive file.driver=file +QEMU_PROG: -drive file.driver=file: could not open disk image ide0-hd0: The 'file' block driver requires a file name + +Testing: -drive file.driver=nbd +QEMU_PROG: -drive file.driver=nbd: could not open disk image ide0-hd0: Could not open image: Invalid argument + +Testing: -drive file.driver=raw +QEMU_PROG: -drive file.driver=raw: could not open disk image ide0-hd0: Can't use 'raw' as a block driver for the protocol level + +Testing: -drive foo=bar +QEMU_PROG: -drive foo=bar: could not open disk image ide0-hd0: Must specify either driver or file + + === Parsing protocol from file name === Testing: -hda foo:bar diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052 index 4d4e411..6bdae92 100755 --- a/tests/qemu-iotests/052 +++ b/tests/qemu-iotests/052 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt generic -_supported_proto generic +_supported_proto file _supported_os Linux _default_cache_mode "writethrough" _supported_cache_modes "writethrough" diff --git a/tests/qemu-iotests/054 b/tests/qemu-iotests/054 index 5a0d1b1..c8b7082 100755 --- a/tests/qemu-iotests/054 +++ b/tests/qemu-iotests/054 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux echo diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 index 2d604d3..ca5aa16 100755 --- a/tests/qemu-iotests/059 +++ b/tests/qemu-iotests/059 @@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # This tests vmdk-specific low-level functionality _supported_fmt vmdk -_supported_proto generic +_supported_proto file _supported_os Linux _unsupported_imgopts "subformat=monolithicFlat" \ "subformat=twoGbMaxExtentFlat" \ diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 index bbb1909..af8ed9f 100755 --- a/tests/qemu-iotests/060 +++ b/tests/qemu-iotests/060 @@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # This tests qocw2-specific low-level functionality _supported_fmt qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux rt_offset=65536 # 0x10000 (XXX: just an assumption) diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 index e42f9bd..d3a6b38 100755 --- a/tests/qemu-iotests/061 +++ b/tests/qemu-iotests/061 @@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # This tests qocw2-specific low-level functionality _supported_fmt qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux echo diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063 index 77503a2..a47493a 100755 --- a/tests/qemu-iotests/063 +++ b/tests/qemu-iotests/063 @@ -42,7 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.pattern _supported_fmt qcow qcow2 vmdk qed raw -_supported_proto generic +_supported_proto file _supported_os Linux _unsupported_imgopts "subformat=monolithicFlat" \ "subformat=twoGbMaxExtentFlat" \ diff --git a/tests/qemu-iotests/069 b/tests/qemu-iotests/069 index 50347d9..e661598 100755 --- a/tests/qemu-iotests/069 +++ b/tests/qemu-iotests/069 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt cow qed qcow qcow2 vmdk -_supported_proto generic +_supported_proto file _supported_os Linux _unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071 index dbc07c6..3924e51 100755 --- a/tests/qemu-iotests/071 +++ b/tests/qemu-iotests/071 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt qcow2 -_supported_proto generic +_supported_proto file _supported_os Linux function do_run_qemu() diff --git a/tests/qemu-iotests/072 b/tests/qemu-iotests/072 index a3876c2..58faa8b 100755 --- a/tests/qemu-iotests/072 +++ b/tests/qemu-iotests/072 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt vpc vmdk vhdx vdi qed qcow2 qcow cow -_supported_proto generic +_supported_proto file _supported_os Linux IMG_SIZE=64M diff --git a/tests/qemu-iotests/077 b/tests/qemu-iotests/077 index bbf7b51..4dd1bdd 100755 --- a/tests/qemu-iotests/077 +++ b/tests/qemu-iotests/077 @@ -38,7 +38,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt generic +_supported_fmt raw _supported_proto generic _supported_os Linux diff --git a/tests/qemu-iotests/079 b/tests/qemu-iotests/079 new file mode 100755 index 0000000..2142bbb --- /dev/null +++ b/tests/qemu-iotests/079 @@ -0,0 +1,63 @@ +#!/bin/bash +# +# Test qcow2 preallocation with different cluster_sizes +# +# Copyright (C) 2014 Fujitsu. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=hutao@cn.fujitsu.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +function test_qemu_img() +{ + echo qemu-img "$@" | _filter_testdir + $QEMU_IMG "$@" 2>&1 | _filter_testdir + echo +} + +echo "=== Check option preallocation and cluster_size ===" +echo +cluster_sizes="16384 32768 65536 131072 262144 524288 1048576 2097152 4194304" + +for s in $cluster_sizes; do + test_qemu_img create -f $IMGFMT -o preallocation=metadata,cluster_size=$s "$TEST_IMG" 4G +done + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/079.out b/tests/qemu-iotests/079.out new file mode 100644 index 0000000..ef4b8c9 --- /dev/null +++ b/tests/qemu-iotests/079.out @@ -0,0 +1,32 @@ +QA output created by 079 +=== Check option preallocation and cluster_size === + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=16384 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=16384 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=32768 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=32768 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=65536 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=131072 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=131072 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=262144 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=262144 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=524288 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=524288 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=1048576 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=1048576 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=2097152 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=2097152 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=4194304 TEST_DIR/t.qcow2 4G +qemu-img: TEST_DIR/t.qcow2: Cluster size must be a power of two between 512 and 2048k +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=4194304 preallocation='metadata' lazy_refcounts=off + +*** done diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index 8b4e22c..5795358 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -144,10 +144,12 @@ check options -vpc test vpc -vhdx test vhdx -vmdk test vmdk + -file test file (default) -rbd test rbd -sheepdog test sheepdog -nbd test nbd -ssh test ssh + -nfs test nfs -xdiff graphical mode diff -nocache use O_DIRECT on backing file -misalign misalign memory allocations @@ -211,22 +213,36 @@ testlist options xpand=false ;; + -file) + IMGPROTO=file + xpand=false + ;; + -rbd) IMGPROTO=rbd xpand=false ;; + -sheepdog) IMGPROTO=sheepdog xpand=false ;; + -nbd) IMGPROTO=nbd xpand=false ;; + -ssh) IMGPROTO=ssh xpand=false ;; + + -nfs) + IMGPROTO=nfs + xpand=false + ;; + -nocache) CACHEMODE="none" CACHEMODE_IS_DEFAULT=false @@ -238,10 +254,10 @@ testlist options xpand=false ;; - -valgrind) - valgrind=true + -valgrind) + valgrind=true xpand=false - ;; + ;; -g) # -g group ... pick from group file group=true diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 0f68156..71e9a74 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -61,6 +61,9 @@ elif [ "$IMGPROTO" = "nbd" ]; then elif [ "$IMGPROTO" = "ssh" ]; then TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" +elif [ "$IMGPROTO" = "nfs" ]; then + TEST_DIR="nfs://127.0.0.1/$TEST_DIR" + TEST_IMG=$TEST_DIR/t.$IMGFMT else TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT fi diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 03c762f..d8be74a 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -82,3 +82,4 @@ 073 rw auto 074 rw auto 077 rw auto +079 rw auto diff --git a/trace-events b/trace-events index 1b668d1..ab11f97 100644 --- a/trace-events +++ b/trace-events @@ -495,7 +495,7 @@ qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d" qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64 # block/qcow2-cluster.c -qcow2_alloc_clusters_offset(void *co, uint64_t offset, int n_start, int n_end) "co %p offet %" PRIx64 " n_start %d n_end %d" +qcow2_alloc_clusters_offset(void *co, uint64_t offset, int num) "co %p offet %" PRIx64 " num %d" qcow2_handle_copied(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 qcow2_handle_alloc(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 qcow2_do_alloc_clusters_offset(void *co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " nb_clusters %d" |