Block patches
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJS9ziDAAoJEH8JsnLIjy/WPLUP/3S9OfbaRWcz5beambW+5i/0 9IeK1jdlb2BkxBu2pMr74RtAmd0JcR5tZTzt5iEGWFZMjwMnGAyiiwqNcraQL/01 UMPwZCeQBbBJihfp+jA9Pez5p5ruWcS2P0wWGgszaLb2zwIk8t20elc9ctmE+/hl kB5O2Ig6TKf/C9grO+9c1QkEfPBygLLZwspm8AFI8gvrqOQ7tpN3LqkVjRyNegUI orprqXEZrWzQuKYhERMgcWOZjtUGILhYuzaCTPpVW9YnnCNzgwjMaKdKK+IgVr2s qdnCjWHJavZp9/3iRjTKURwk9gmeJOlbPp+hUu3maeMj4r8bzQK89p6RSAbiXCuI fC10Z/i5qmftlOdZwiIm19tqEfevgnnSYorZq3ALVR4nC4eruPNjpTIJNJ41Le5M SF90umsw86OkOR2KIm3DfXEla85ftUh/54aaVr80b8lfogJpHa0zfurVZwHGXBOx 7wHFa1bcwRg4F8wAY8ptSwMxp97JGJADvQj+PzlK1WLIeeXp7Nh1jlVBg9HW1YVa AlKJAn2+hvUIuF3wbz8rkS2eKKnkjtsqjkQAWlsoAhQ79FiLBJ4SmgWftNgIqCKt Yh5dUY/bC5gM0O0eR+U4oBl/wqj9s/nei0waJ6snvgXkLJBoN3yuP1C3mfLx1o4v /XubiSe7z3+9zPL30GKb =XErB -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
628a746cf0
|
@ -937,6 +937,11 @@ M: Peter Lieven <pl@kamp.de>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: block/iscsi.c
|
F: block/iscsi.c
|
||||||
|
|
||||||
|
NFS
|
||||||
|
M: Peter Lieven <pl@kamp.de>
|
||||||
|
S: Maintained
|
||||||
|
F: block/nfs.c
|
||||||
|
|
||||||
SSH
|
SSH
|
||||||
M: Richard W.M. Jones <rjones@redhat.com>
|
M: Richard W.M. Jones <rjones@redhat.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
23
block.c
23
block.c
|
@ -832,6 +832,12 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
||||||
filename = qdict_get_try_str(options, "filename");
|
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);
|
trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
|
||||||
|
|
||||||
node_name = qdict_get_try_str(options, "node-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;
|
goto fail;
|
||||||
}
|
}
|
||||||
qdict_del(options, "filename");
|
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) {
|
if (!drv->bdrv_file_open) {
|
||||||
|
@ -2239,10 +2240,10 @@ static void tracked_request_begin(BdrvTrackedRequest *req,
|
||||||
QLIST_INSERT_HEAD(&bs->tracked_requests, req, list);
|
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);
|
int64_t overlap_offset = req->offset & ~(align - 1);
|
||||||
int overlap_bytes = ROUND_UP(req->offset + req->bytes, align)
|
unsigned int overlap_bytes = ROUND_UP(req->offset + req->bytes, align)
|
||||||
- overlap_offset;
|
- overlap_offset;
|
||||||
|
|
||||||
if (!req->serialising) {
|
if (!req->serialising) {
|
||||||
|
@ -2914,8 +2915,8 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs,
|
||||||
}
|
}
|
||||||
|
|
||||||
total_sectors = DIV_ROUND_UP(len, BDRV_SECTOR_SIZE);
|
total_sectors = DIV_ROUND_UP(len, BDRV_SECTOR_SIZE);
|
||||||
max_nb_sectors = MAX(0, ROUND_UP(total_sectors - sector_num,
|
max_nb_sectors = ROUND_UP(MAX(0, total_sectors - sector_num),
|
||||||
align >> BDRV_SECTOR_BITS));
|
align >> BDRV_SECTOR_BITS);
|
||||||
if (max_nb_sectors > 0) {
|
if (max_nb_sectors > 0) {
|
||||||
ret = drv->bdrv_co_readv(bs, sector_num,
|
ret = drv->bdrv_co_readv(bs, sector_num,
|
||||||
MIN(nb_sectors, max_nb_sectors), qiov);
|
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);
|
waited = wait_serialising_requests(req);
|
||||||
assert(!waited || !req->serialising);
|
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);
|
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
|
||||||
|
|
||||||
|
@ -3278,9 +3281,9 @@ fail:
|
||||||
|
|
||||||
if (use_local_qiov) {
|
if (use_local_qiov) {
|
||||||
qemu_iovec_destroy(&local_qiov);
|
qemu_iovec_destroy(&local_qiov);
|
||||||
|
}
|
||||||
qemu_vfree(head_buf);
|
qemu_vfree(head_buf);
|
||||||
qemu_vfree(tail_buf);
|
qemu_vfree(tail_buf);
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
|
||||||
ifeq ($(CONFIG_POSIX),y)
|
ifeq ($(CONFIG_POSIX),y)
|
||||||
block-obj-y += nbd.o nbd-client.o sheepdog.o
|
block-obj-y += nbd.o nbd-client.o sheepdog.o
|
||||||
block-obj-$(CONFIG_LIBISCSI) += iscsi.o
|
block-obj-$(CONFIG_LIBISCSI) += iscsi.o
|
||||||
|
block-obj-$(CONFIG_LIBNFS) += nfs.o
|
||||||
block-obj-$(CONFIG_CURL) += curl.o
|
block-obj-$(CONFIG_CURL) += curl.o
|
||||||
block-obj-$(CONFIG_RBD) += rbd.o
|
block-obj-$(CONFIG_RBD) += rbd.o
|
||||||
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
|
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
|
||||||
|
|
|
@ -396,14 +396,14 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
if (error_is_set(&local_err)) {
|
if (error_is_set(&local_err)) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read rules from config file or command line options */
|
/* Read rules from config file or command line options */
|
||||||
config = qemu_opt_get(opts, "config");
|
config = qemu_opt_get(opts, "config");
|
||||||
ret = read_config(s, config, options, errp);
|
ret = read_config(s, config, options, errp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set initial state */
|
/* Set initial state */
|
||||||
|
@ -414,7 +414,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
flags, true, false, &local_err);
|
flags, true, false, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set request alignment */
|
/* Set request alignment */
|
||||||
|
@ -424,11 +424,15 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "Invalid alignment");
|
error_setg(errp, "Invalid alignment");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail_unref;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fail:
|
goto out;
|
||||||
|
|
||||||
|
fail_unref:
|
||||||
|
bdrv_unref(bs->file);
|
||||||
|
out:
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1330,10 +1330,9 @@ static int iscsi_refresh_limits(BlockDriverState *bs)
|
||||||
}
|
}
|
||||||
bs->bl.write_zeroes_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran,
|
bs->bl.write_zeroes_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran,
|
||||||
iscsilun);
|
iscsilun);
|
||||||
|
}
|
||||||
bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len,
|
bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len,
|
||||||
iscsilun);
|
iscsilun);
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
439
block/nfs.c
Normal file
439
block/nfs.c
Normal file
|
@ -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);
|
|
@ -1182,7 +1182,7 @@ fail:
|
||||||
* Return 0 on success and -errno in error cases
|
* Return 0 on success and -errno in error cases
|
||||||
*/
|
*/
|
||||||
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t 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)
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
uint64_t start, remaining;
|
uint64_t start, remaining;
|
||||||
|
@ -1190,15 +1190,13 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||||
uint64_t cur_bytes;
|
uint64_t cur_bytes;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset,
|
trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset, *num);
|
||||||
n_start, n_end);
|
|
||||||
|
|
||||||
assert(n_start * BDRV_SECTOR_SIZE == offset_into_cluster(s, offset));
|
assert((offset & ~BDRV_SECTOR_MASK) == 0);
|
||||||
offset = start_of_cluster(s, offset);
|
|
||||||
|
|
||||||
again:
|
again:
|
||||||
start = offset + (n_start << BDRV_SECTOR_BITS);
|
start = offset;
|
||||||
remaining = (n_end - n_start) << BDRV_SECTOR_BITS;
|
remaining = *num << BDRV_SECTOR_BITS;
|
||||||
cluster_offset = 0;
|
cluster_offset = 0;
|
||||||
*host_offset = 0;
|
*host_offset = 0;
|
||||||
cur_bytes = 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(*num > 0);
|
||||||
assert(*host_offset != 0);
|
assert(*host_offset != 0);
|
||||||
|
|
||||||
|
|
|
@ -676,7 +676,13 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
uint64_t cluster_index;
|
uint64_t cluster_index;
|
||||||
uint64_t old_free_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 */
|
/* Check how many clusters there are free */
|
||||||
cluster_index = offset >> s->cluster_bits;
|
cluster_index = offset >> s->cluster_bits;
|
||||||
|
|
|
@ -1000,7 +1000,6 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
int index_in_cluster;
|
int index_in_cluster;
|
||||||
int n_end;
|
|
||||||
int ret;
|
int ret;
|
||||||
int cur_nr_sectors; /* number of sectors in current iteration */
|
int cur_nr_sectors; /* number of sectors in current iteration */
|
||||||
uint64_t cluster_offset;
|
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());
|
trace_qcow2_writev_start_part(qemu_coroutine_self());
|
||||||
index_in_cluster = sector_num & (s->cluster_sectors - 1);
|
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 &&
|
if (s->crypt_method &&
|
||||||
n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors) {
|
cur_nr_sectors >
|
||||||
n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_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,
|
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) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -1403,34 +1404,34 @@ static int preallocate(BlockDriverState *bs)
|
||||||
int ret;
|
int ret;
|
||||||
QCowL2Meta *meta;
|
QCowL2Meta *meta;
|
||||||
|
|
||||||
nb_sectors = bdrv_getlength(bs) >> 9;
|
nb_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
while (nb_sectors) {
|
while (nb_sectors) {
|
||||||
num = MIN(nb_sectors, INT_MAX >> 9);
|
num = MIN(nb_sectors, INT_MAX >> BDRV_SECTOR_BITS);
|
||||||
ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num,
|
ret = qcow2_alloc_cluster_offset(bs, offset, &num,
|
||||||
&host_offset, &meta);
|
&host_offset, &meta);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (meta != NULL) {
|
||||||
ret = qcow2_alloc_cluster_link_l2(bs, meta);
|
ret = qcow2_alloc_cluster_link_l2(bs, meta);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters,
|
qcow2_free_any_clusters(bs, meta->alloc_offset,
|
||||||
QCOW2_DISCARD_NEVER);
|
meta->nb_clusters, QCOW2_DISCARD_NEVER);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There are no dependent requests, but we need to remove our request
|
/* There are no dependent requests, but we need to remove our
|
||||||
* from the list of in-flight requests */
|
* request from the list of in-flight requests */
|
||||||
if (meta != NULL) {
|
|
||||||
QLIST_REMOVE(meta, next_in_flight);
|
QLIST_REMOVE(meta, next_in_flight);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO Preallocate data if requested */
|
/* TODO Preallocate data if requested */
|
||||||
|
|
||||||
nb_sectors -= num;
|
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.
|
* EOF). Extend the image to the last allocated sector.
|
||||||
*/
|
*/
|
||||||
if (host_offset != 0) {
|
if (host_offset != 0) {
|
||||||
uint8_t buf[512];
|
uint8_t buf[BDRV_SECTOR_SIZE];
|
||||||
memset(buf, 0, 512);
|
memset(buf, 0, BDRV_SECTOR_SIZE);
|
||||||
ret = bdrv_write(bs->file, (host_offset >> 9) + num - 1, buf, 1);
|
ret = bdrv_write(bs->file, (host_offset >> BDRV_SECTOR_BITS) + num - 1,
|
||||||
|
buf, 1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||||
int *num, uint64_t *cluster_offset);
|
int *num, uint64_t *cluster_offset);
|
||||||
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t 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 qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||||
uint64_t offset,
|
uint64_t offset,
|
||||||
int compressed_size);
|
int compressed_size);
|
||||||
|
|
|
@ -90,6 +90,12 @@ static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||||
return bdrv_get_info(bs->file, 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)
|
static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||||
{
|
{
|
||||||
return bdrv_truncate(bs->file, offset);
|
return bdrv_truncate(bs->file, offset);
|
||||||
|
@ -150,7 +156,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
bs->sg = bs->file->sg;
|
bs->sg = bs->file->sg;
|
||||||
bs->bl = bs->file->bl;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +187,7 @@ static BlockDriver bdrv_raw = {
|
||||||
.bdrv_getlength = &raw_getlength,
|
.bdrv_getlength = &raw_getlength,
|
||||||
.has_variable_length = true,
|
.has_variable_length = true,
|
||||||
.bdrv_get_info = &raw_get_info,
|
.bdrv_get_info = &raw_get_info,
|
||||||
|
.bdrv_refresh_limits = &raw_refresh_limits,
|
||||||
.bdrv_is_inserted = &raw_is_inserted,
|
.bdrv_is_inserted = &raw_is_inserted,
|
||||||
.bdrv_media_changed = &raw_media_changed,
|
.bdrv_media_changed = &raw_media_changed,
|
||||||
.bdrv_eject = &raw_eject,
|
.bdrv_eject = &raw_eject,
|
||||||
|
|
26
configure
vendored
26
configure
vendored
|
@ -251,6 +251,7 @@ vss_win32_sdk=""
|
||||||
win_sdk="no"
|
win_sdk="no"
|
||||||
want_tools="yes"
|
want_tools="yes"
|
||||||
libiscsi=""
|
libiscsi=""
|
||||||
|
libnfs=""
|
||||||
coroutine=""
|
coroutine=""
|
||||||
coroutine_pool=""
|
coroutine_pool=""
|
||||||
seccomp=""
|
seccomp=""
|
||||||
|
@ -840,6 +841,10 @@ for opt do
|
||||||
;;
|
;;
|
||||||
--enable-libiscsi) libiscsi="yes"
|
--enable-libiscsi) libiscsi="yes"
|
||||||
;;
|
;;
|
||||||
|
--disable-libnfs) libnfs="no"
|
||||||
|
;;
|
||||||
|
--enable-libnfs) libnfs="yes"
|
||||||
|
;;
|
||||||
--enable-profiler) profiler="yes"
|
--enable-profiler) profiler="yes"
|
||||||
;;
|
;;
|
||||||
--disable-cocoa) cocoa="no"
|
--disable-cocoa) cocoa="no"
|
||||||
|
@ -1229,6 +1234,8 @@ Advanced options (experts only):
|
||||||
--enable-rbd enable building the rados block device (rbd)
|
--enable-rbd enable building the rados block device (rbd)
|
||||||
--disable-libiscsi disable iscsi support
|
--disable-libiscsi disable iscsi support
|
||||||
--enable-libiscsi enable iscsi support
|
--enable-libiscsi enable iscsi support
|
||||||
|
--disable-libnfs disable nfs support
|
||||||
|
--enable-libnfs enable nfs support
|
||||||
--disable-smartcard-nss disable smartcard nss support
|
--disable-smartcard-nss disable smartcard nss support
|
||||||
--enable-smartcard-nss enable smartcard nss support
|
--enable-smartcard-nss enable smartcard nss support
|
||||||
--disable-libusb disable libusb (for usb passthrough)
|
--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"
|
CFLAGS="-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS"
|
||||||
fi
|
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
|
# Disable zero malloc errors for official releases unless explicitly told to
|
||||||
# enable/disable
|
# enable/disable
|
||||||
|
@ -3829,6 +3850,7 @@ echo "libiscsi support $libiscsi (1.4.0)"
|
||||||
else
|
else
|
||||||
echo "libiscsi support $libiscsi"
|
echo "libiscsi support $libiscsi"
|
||||||
fi
|
fi
|
||||||
|
echo "libnfs support $libnfs"
|
||||||
echo "build guest agent $guest_agent"
|
echo "build guest agent $guest_agent"
|
||||||
echo "QGA VSS support $guest_agent_with_vss"
|
echo "QGA VSS support $guest_agent_with_vss"
|
||||||
echo "seccomp support $seccomp"
|
echo "seccomp support $seccomp"
|
||||||
|
@ -4165,6 +4187,10 @@ if test "$libiscsi" = "yes" ; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$libnfs" = "yes" ; then
|
||||||
|
echo "CONFIG_LIBNFS=y" >> $config_host_mak
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$seccomp" = "yes"; then
|
if test "$seccomp" = "yes"; then
|
||||||
echo "CONFIG_SECCOMP=y" >> $config_host_mak
|
echo "CONFIG_SECCOMP=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -4371,6 +4371,7 @@
|
||||||
# TODO gluster: Wait for structured options
|
# TODO gluster: Wait for structured options
|
||||||
# TODO iscsi: Wait for structured options
|
# TODO iscsi: Wait for structured options
|
||||||
# TODO nbd: Should take InetSocketAddress for 'host'?
|
# TODO nbd: Should take InetSocketAddress for 'host'?
|
||||||
|
# TODO nfs: Wait for structured options
|
||||||
# TODO rbd: Wait for structured options
|
# TODO rbd: Wait for structured options
|
||||||
# TODO sheepdog: Wait for structured options
|
# TODO sheepdog: Wait for structured options
|
||||||
# TODO ssh: Should take InetSocketAddress for 'host'?
|
# TODO ssh: Should take InetSocketAddress for 'host'?
|
||||||
|
|
|
@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# much of this could be generic for any format supporting compression.
|
# much of this could be generic for any format supporting compression.
|
||||||
_supported_fmt qcow qcow2
|
_supported_fmt qcow qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
TEST_OFFSETS="0 4294967296"
|
TEST_OFFSETS="0 4294967296"
|
||||||
|
|
|
@ -43,7 +43,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# much of this could be generic for any format supporting snapshots
|
# much of this could be generic for any format supporting snapshots
|
||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
TEST_OFFSETS="0 4294967296"
|
TEST_OFFSETS="0 4294967296"
|
||||||
|
|
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt raw
|
_supported_fmt raw
|
||||||
_supported_proto file sheepdog
|
_supported_proto file sheepdog nfs
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# Any format supporting backing files
|
# Any format supporting backing files
|
||||||
_supported_fmt qcow qcow2 vmdk qed
|
_supported_fmt qcow qcow2 vmdk qed
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
|
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# Any format supporting backing files
|
# Any format supporting backing files
|
||||||
_supported_fmt qcow qcow2 vmdk qed
|
_supported_fmt qcow qcow2 vmdk qed
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
_unsupported_imgopts "subformat=monolithicFlat" \
|
_unsupported_imgopts "subformat=monolithicFlat" \
|
||||||
"subformat=twoGbMaxExtentFlat" \
|
"subformat=twoGbMaxExtentFlat" \
|
||||||
|
|
|
@ -49,6 +49,11 @@ _unsupported_imgopts "subformat=monolithicFlat" \
|
||||||
"subformat=twoGbMaxExtentFlat" \
|
"subformat=twoGbMaxExtentFlat" \
|
||||||
"subformat=twoGbMaxExtentSparse"
|
"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"
|
TEST_OFFSETS="0 4294967296"
|
||||||
|
|
||||||
_make_test_img 6G
|
_make_test_img 6G
|
||||||
|
|
|
@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# much of this could be generic for any format supporting compression.
|
# much of this could be generic for any format supporting compression.
|
||||||
_supported_fmt qcow qcow2
|
_supported_fmt qcow qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
TEST_OFFSETS="0 4294967296"
|
TEST_OFFSETS="0 4294967296"
|
||||||
|
|
|
@ -43,7 +43,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# Currently only qcow2 and qed support rebasing
|
# Currently only qcow2 and qed support rebasing
|
||||||
_supported_fmt qcow2 qed
|
_supported_fmt qcow2 qed
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
CLUSTER_SIZE=65536
|
CLUSTER_SIZE=65536
|
||||||
|
|
|
@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.pattern
|
. ./common.pattern
|
||||||
|
|
||||||
_supported_fmt raw qcow2 qed
|
_supported_fmt raw qcow2 qed
|
||||||
_supported_proto file sheepdog rbd
|
_supported_proto file sheepdog rbd nfs
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
echo "=== Creating image"
|
echo "=== Creating image"
|
||||||
|
|
|
@ -42,7 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# Currently only qcow2 supports rebasing
|
# Currently only qcow2 supports rebasing
|
||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
_default_cache_mode "writethrough"
|
_default_cache_mode "writethrough"
|
||||||
_supported_cache_modes "writethrough" "none"
|
_supported_cache_modes "writethrough" "none"
|
||||||
|
|
|
@ -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
|
# Any format supporting backing files except vmdk and qcow which do not support
|
||||||
# smaller backing files.
|
# smaller backing files.
|
||||||
_supported_fmt qcow2 qed
|
_supported_fmt qcow2 qed
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
# Choose a size that is not necessarily a cluster size multiple for image
|
# Choose a size that is not necessarily a cluster size multiple for image
|
||||||
|
|
|
@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# This tests qcow2-specific low-level functionality
|
# This tests qcow2-specific low-level functionality
|
||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
CLUSTER_SIZE=65536
|
CLUSTER_SIZE=65536
|
||||||
|
|
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt qcow qcow2 vmdk qed
|
_supported_fmt qcow qcow2 vmdk qed
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
_unsupported_imgopts "subformat=monolithicFlat" \
|
_unsupported_imgopts "subformat=monolithicFlat" \
|
||||||
"subformat=twoGbMaxExtentFlat" \
|
"subformat=twoGbMaxExtentFlat" \
|
||||||
|
|
|
@ -44,7 +44,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# This tests qcow2-specific low-level functionality
|
# This tests qcow2-specific low-level functionality
|
||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
# Only qcow2v3 and later supports feature bits
|
# Only qcow2v3 and later supports feature bits
|
||||||
|
|
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt qcow qcow2 vmdk qed
|
_supported_fmt qcow qcow2 vmdk qed
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
_unsupported_imgopts "subformat=monolithicFlat" \
|
_unsupported_imgopts "subformat=monolithicFlat" \
|
||||||
"subformat=twoGbMaxExtentFlat" \
|
"subformat=twoGbMaxExtentFlat" \
|
||||||
|
|
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt qcow2 qed
|
_supported_fmt qcow2 qed
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
CLUSTER_SIZE=2M
|
CLUSTER_SIZE=2M
|
||||||
|
|
|
@ -42,7 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
_default_cache_mode "writethrough"
|
_default_cache_mode "writethrough"
|
||||||
_supported_cache_modes "writethrough"
|
_supported_cache_modes "writethrough"
|
||||||
|
|
|
@ -41,7 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# Any format supporting backing files
|
# Any format supporting backing files
|
||||||
_supported_fmt qcow2 qed
|
_supported_fmt qcow2 qed
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
CLUSTER_SIZE=64k
|
CLUSTER_SIZE=64k
|
||||||
|
|
|
@ -171,6 +171,18 @@ echo
|
||||||
run_qemu -drive file="$TEST_IMG",file.driver=file
|
run_qemu -drive file="$TEST_IMG",file.driver=file
|
||||||
run_qemu -drive file="$TEST_IMG",file.driver=qcow2
|
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
|
||||||
echo === Parsing protocol from file name ===
|
echo === Parsing protocol from file name ===
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -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'
|
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 ===
|
=== Parsing protocol from file name ===
|
||||||
|
|
||||||
Testing: -hda foo:bar
|
Testing: -hda foo:bar
|
||||||
|
|
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt generic
|
_supported_fmt generic
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
_default_cache_mode "writethrough"
|
_default_cache_mode "writethrough"
|
||||||
_supported_cache_modes "writethrough"
|
_supported_cache_modes "writethrough"
|
||||||
|
|
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# This tests vmdk-specific low-level functionality
|
# This tests vmdk-specific low-level functionality
|
||||||
_supported_fmt vmdk
|
_supported_fmt vmdk
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
_unsupported_imgopts "subformat=monolithicFlat" \
|
_unsupported_imgopts "subformat=monolithicFlat" \
|
||||||
"subformat=twoGbMaxExtentFlat" \
|
"subformat=twoGbMaxExtentFlat" \
|
||||||
|
|
|
@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# This tests qocw2-specific low-level functionality
|
# This tests qocw2-specific low-level functionality
|
||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
rt_offset=65536 # 0x10000 (XXX: just an assumption)
|
rt_offset=65536 # 0x10000 (XXX: just an assumption)
|
||||||
|
|
|
@ -40,7 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
# This tests qocw2-specific low-level functionality
|
# This tests qocw2-specific low-level functionality
|
||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -42,7 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.pattern
|
. ./common.pattern
|
||||||
|
|
||||||
_supported_fmt qcow qcow2 vmdk qed raw
|
_supported_fmt qcow qcow2 vmdk qed raw
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
_unsupported_imgopts "subformat=monolithicFlat" \
|
_unsupported_imgopts "subformat=monolithicFlat" \
|
||||||
"subformat=twoGbMaxExtentFlat" \
|
"subformat=twoGbMaxExtentFlat" \
|
||||||
|
|
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt cow qed qcow qcow2 vmdk
|
_supported_fmt cow qed qcow qcow2 vmdk
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
|
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
function do_run_qemu()
|
function do_run_qemu()
|
||||||
|
|
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt vpc vmdk vhdx vdi qed qcow2 qcow cow
|
_supported_fmt vpc vmdk vhdx vdi qed qcow2 qcow cow
|
||||||
_supported_proto generic
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
IMG_SIZE=64M
|
IMG_SIZE=64M
|
||||||
|
|
|
@ -38,7 +38,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
. ./common.rc
|
. ./common.rc
|
||||||
. ./common.filter
|
. ./common.filter
|
||||||
|
|
||||||
_supported_fmt generic
|
_supported_fmt raw
|
||||||
_supported_proto generic
|
_supported_proto generic
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
|
|
63
tests/qemu-iotests/079
Executable file
63
tests/qemu-iotests/079
Executable file
|
@ -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
|
32
tests/qemu-iotests/079.out
Normal file
32
tests/qemu-iotests/079.out
Normal file
|
@ -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
|
|
@ -144,10 +144,12 @@ check options
|
||||||
-vpc test vpc
|
-vpc test vpc
|
||||||
-vhdx test vhdx
|
-vhdx test vhdx
|
||||||
-vmdk test vmdk
|
-vmdk test vmdk
|
||||||
|
-file test file (default)
|
||||||
-rbd test rbd
|
-rbd test rbd
|
||||||
-sheepdog test sheepdog
|
-sheepdog test sheepdog
|
||||||
-nbd test nbd
|
-nbd test nbd
|
||||||
-ssh test ssh
|
-ssh test ssh
|
||||||
|
-nfs test nfs
|
||||||
-xdiff graphical mode diff
|
-xdiff graphical mode diff
|
||||||
-nocache use O_DIRECT on backing file
|
-nocache use O_DIRECT on backing file
|
||||||
-misalign misalign memory allocations
|
-misalign misalign memory allocations
|
||||||
|
@ -211,22 +213,36 @@ testlist options
|
||||||
xpand=false
|
xpand=false
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
-file)
|
||||||
|
IMGPROTO=file
|
||||||
|
xpand=false
|
||||||
|
;;
|
||||||
|
|
||||||
-rbd)
|
-rbd)
|
||||||
IMGPROTO=rbd
|
IMGPROTO=rbd
|
||||||
xpand=false
|
xpand=false
|
||||||
;;
|
;;
|
||||||
|
|
||||||
-sheepdog)
|
-sheepdog)
|
||||||
IMGPROTO=sheepdog
|
IMGPROTO=sheepdog
|
||||||
xpand=false
|
xpand=false
|
||||||
;;
|
;;
|
||||||
|
|
||||||
-nbd)
|
-nbd)
|
||||||
IMGPROTO=nbd
|
IMGPROTO=nbd
|
||||||
xpand=false
|
xpand=false
|
||||||
;;
|
;;
|
||||||
|
|
||||||
-ssh)
|
-ssh)
|
||||||
IMGPROTO=ssh
|
IMGPROTO=ssh
|
||||||
xpand=false
|
xpand=false
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
-nfs)
|
||||||
|
IMGPROTO=nfs
|
||||||
|
xpand=false
|
||||||
|
;;
|
||||||
|
|
||||||
-nocache)
|
-nocache)
|
||||||
CACHEMODE="none"
|
CACHEMODE="none"
|
||||||
CACHEMODE_IS_DEFAULT=false
|
CACHEMODE_IS_DEFAULT=false
|
||||||
|
|
|
@ -61,6 +61,9 @@ elif [ "$IMGPROTO" = "nbd" ]; then
|
||||||
elif [ "$IMGPROTO" = "ssh" ]; then
|
elif [ "$IMGPROTO" = "ssh" ]; then
|
||||||
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
|
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
|
||||||
TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
|
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
|
else
|
||||||
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
|
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -82,3 +82,4 @@
|
||||||
073 rw auto
|
073 rw auto
|
||||||
074 rw auto
|
074 rw auto
|
||||||
077 rw auto
|
077 rw auto
|
||||||
|
079 rw auto
|
||||||
|
|
|
@ -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
|
qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64
|
||||||
|
|
||||||
# block/qcow2-cluster.c
|
# 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_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_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"
|
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"
|
||||||
|
|
Loading…
Reference in a new issue