mirror of https://github.com/xemu-project/xemu.git
Block layer patches:
- auto-read-only option to fix commit job when used with -blockdev - Fix help text related qemu-iotests failure (by improving the help text and updating the reference output) - quorum: Add missing checks when adding/removing child nodes - Don't take address of fields in packed structs - vvfat: Fix crash when reporting error about too many files in directory -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJb4GM9AAoJEH8JsnLIjy/WsxAP/35JK6qJJYf4aYl6oq570G6X nyyTtoo70++DZqUDY5OE3uavKM8pQxAmGRURwII+qn805X6pnh1bAl31dB3tvlt9 7E1WCcde/dOpWqVEwYkgXgHIkhjtbaW0iG36IcVAFKN0YhnVyARo01Ft+NXTlWmG GtfqgrquACITRI9P3j0VatpQZO6WgFDUM8l/013I5u5Med3UPniHwc0lJhjT5HaI 9I2+OdLlAMAwfrMjohMDboENSPvOm0gp+uy9Y0qBMLx7MR7P3P0W+nmpHbdY1Ae5 wt/10GcTw1wZ15jsVuAbX7SJsAb7pTktlh290EQpHUTm7nLagbU/e530xpVVEKiB 6GNfHV+ANGK/lWXE2D3XxLuNAjIYopvjjbiUNH2atkzu3OaBAe3WjjZkIRI6ThCp fIrHP4LIVcp5VT21nZywUXzg1KMa0N0UbzEgASIlGjohsURCQrczP3qyeKdMxsQc FQTR5okKiPj9Y/RAcLwV5znXYJvmjzMAuIwzdy3oy5b46eAxNj6BIMzOQMgEvIkH 2CrONsxWE0aAVHQc4zoEMPEUMRPH/KMbls2khg/02oXsiPqmwold9Fc5kf/p+egn V6tUhC3eO8q4fvAinsOIjOWmyjCnHBuat/n0YwgJr98Mb9WO/wgqSIRuoMRNk55s D6nO1Mnd4EDQMY3P7lU2 =/9Om -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block layer patches: - auto-read-only option to fix commit job when used with -blockdev - Fix help text related qemu-iotests failure (by improving the help text and updating the reference output) - quorum: Add missing checks when adding/removing child nodes - Don't take address of fields in packed structs - vvfat: Fix crash when reporting error about too many files in directory # gpg: Signature made Mon 05 Nov 2018 15:35:25 GMT # gpg: using RSA key 7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (36 commits) include: Add a comment to explain the origin of sizes' lookup table vdi: Use a literal number of bytes for DEFAULT_CLUSTER_SIZE fw_cfg: Drop newline in @file description object: Make option help nicer to read qdev-monitor: Make device options help nicer chardev: Indent list of chardevs option: Make option help nicer to read qemu-iotests: Test auto-read-only with -drive and -blockdev block: Make auto-read-only=on default for -drive iscsi: Support auto-read-only option gluster: Support auto-read-only option curl: Support auto-read-only option file-posix: Support auto-read-only option nbd: Support auto-read-only option block: Require auto-read-only for existing fallbacks rbd: Close image in qemu_rbd_open() error path block: Add auto-read-only option block: Update flags in bdrv_set_read_only() iotest: Test x-blockdev-change on a Quorum quorum: Forbid adding children in blkverify mode ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3cb99f4124
62
block.c
62
block.c
|
@ -266,22 +266,41 @@ int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* TODO Remove (deprecated since 2.11)
|
||||
* Block drivers are not supposed to automatically change bs->read_only.
|
||||
* Instead, they should just check whether they can provide what the user
|
||||
* explicitly requested and error out if read-write is requested, but they can
|
||||
* only provide read-only access. */
|
||||
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
|
||||
/*
|
||||
* Called by a driver that can only provide a read-only image.
|
||||
*
|
||||
* Returns 0 if the node is already read-only or it could switch the node to
|
||||
* read-only because BDRV_O_AUTO_RDONLY is set.
|
||||
*
|
||||
* Returns -EACCES if the node is read-write and BDRV_O_AUTO_RDONLY is not set
|
||||
* or bdrv_can_set_read_only() forbids making the node read-only. If @errmsg
|
||||
* is not NULL, it is used as the error message for the Error object.
|
||||
*/
|
||||
int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
|
||||
Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = bdrv_can_set_read_only(bs, read_only, false, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
if (!(bs->open_flags & BDRV_O_RDWR)) {
|
||||
return 0;
|
||||
}
|
||||
if (!(bs->open_flags & BDRV_O_AUTO_RDONLY)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bs->read_only = read_only;
|
||||
ret = bdrv_can_set_read_only(bs, true, false, NULL);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bs->read_only = true;
|
||||
bs->open_flags &= ~BDRV_O_RDWR;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
error_setg(errp, "%s", errmsg ?: "Image is read-only");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
void bdrv_get_full_backing_filename_from_filename(const char *backed,
|
||||
|
@ -923,6 +942,7 @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
|
|||
|
||||
/* Inherit the read-only option from the parent if it's not set */
|
||||
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
|
||||
qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
|
||||
|
||||
/* Our block drivers take care to send flushes and respect unmap policy,
|
||||
* so we can default to enable both on lower layers regardless of the
|
||||
|
@ -1046,6 +1066,7 @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
|
|||
|
||||
/* backing files always opened read-only */
|
||||
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
|
||||
qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
|
||||
flags &= ~BDRV_O_COPY_ON_READ;
|
||||
|
||||
/* snapshot=on is handled on the top layer */
|
||||
|
@ -1135,6 +1156,10 @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
|
|||
*flags |= BDRV_O_RDWR;
|
||||
}
|
||||
|
||||
assert(qemu_opt_find(opts, BDRV_OPT_AUTO_READ_ONLY));
|
||||
if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) {
|
||||
*flags |= BDRV_O_AUTO_RDONLY;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_options_from_flags(QDict *options, int flags)
|
||||
|
@ -1149,6 +1174,10 @@ static void update_options_from_flags(QDict *options, int flags)
|
|||
if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
|
||||
qdict_put_bool(options, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
|
||||
}
|
||||
if (!qdict_haskey(options, BDRV_OPT_AUTO_READ_ONLY)) {
|
||||
qdict_put_bool(options, BDRV_OPT_AUTO_READ_ONLY,
|
||||
flags & BDRV_O_AUTO_RDONLY);
|
||||
}
|
||||
}
|
||||
|
||||
static void bdrv_assign_node_name(BlockDriverState *bs,
|
||||
|
@ -1321,13 +1350,18 @@ QemuOptsList bdrv_runtime_opts = {
|
|||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Node is opened in read-only mode",
|
||||
},
|
||||
{
|
||||
.name = BDRV_OPT_AUTO_READ_ONLY,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Node can become read-only if opening read-write fails",
|
||||
},
|
||||
{
|
||||
.name = "detect-zeroes",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "try to optimize zero writes (off, on, unmap)",
|
||||
},
|
||||
{
|
||||
.name = "discard",
|
||||
.name = BDRV_OPT_DISCARD,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "discard operation (ignore/off, unmap/on)",
|
||||
},
|
||||
|
@ -1432,7 +1466,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
|
|||
}
|
||||
}
|
||||
|
||||
discard = qemu_opt_get(opts, "discard");
|
||||
discard = qemu_opt_get(opts, BDRV_OPT_DISCARD);
|
||||
if (discard != NULL) {
|
||||
if (bdrv_parse_discard_flags(discard, &bs->open_flags) != 0) {
|
||||
error_setg(errp, "Invalid discard option");
|
||||
|
@ -2479,6 +2513,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
|
|||
qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
|
||||
qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
|
||||
qdict_set_default_str(qdict, BDRV_OPT_READ_ONLY, "off");
|
||||
qdict_set_default_str(qdict, BDRV_OPT_AUTO_READ_ONLY, "off");
|
||||
|
||||
}
|
||||
|
||||
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
|
||||
|
@ -3186,7 +3222,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
|||
|
||||
update_flags_from_options(&reopen_state->flags, opts);
|
||||
|
||||
discard = qemu_opt_get_del(opts, "discard");
|
||||
discard = qemu_opt_get_del(opts, BDRV_OPT_DISCARD);
|
||||
if (discard != NULL) {
|
||||
if (bdrv_parse_discard_flags(discard, &reopen_state->flags) != 0) {
|
||||
error_setg(errp, "Invalid discard option");
|
||||
|
|
|
@ -1708,7 +1708,7 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
|
|||
}
|
||||
}
|
||||
|
||||
int blk_is_read_only(BlockBackend *blk)
|
||||
bool blk_is_read_only(BlockBackend *blk)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
|
||||
|
@ -1719,18 +1719,18 @@ int blk_is_read_only(BlockBackend *blk)
|
|||
}
|
||||
}
|
||||
|
||||
int blk_is_sg(BlockBackend *blk)
|
||||
bool blk_is_sg(BlockBackend *blk)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
|
||||
if (!bs) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return bdrv_is_sg(bs);
|
||||
}
|
||||
|
||||
int blk_enable_write_cache(BlockBackend *blk)
|
||||
bool blk_enable_write_cache(BlockBackend *blk)
|
||||
{
|
||||
return blk->enable_write_cache;
|
||||
}
|
||||
|
|
|
@ -105,23 +105,18 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
struct bochs_header bochs;
|
||||
int ret;
|
||||
|
||||
/* No write support yet */
|
||||
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
|
||||
false, errp);
|
||||
if (!bs->file) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!bdrv_is_read_only(bs)) {
|
||||
error_report("Opening bochs images without an explicit read-only=on "
|
||||
"option is deprecated. Future versions will refuse to "
|
||||
"open the image instead of automatically marking the "
|
||||
"image read-only.");
|
||||
ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
|
|
@ -67,23 +67,17 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
uint32_t offsets_size, max_compressed_block_size = 1, i;
|
||||
int ret;
|
||||
|
||||
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
|
||||
false, errp);
|
||||
if (!bs->file) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!bdrv_is_read_only(bs)) {
|
||||
error_report("Opening cloop images without an explicit read-only=on "
|
||||
"option is deprecated. Future versions will refuse to "
|
||||
"open the image instead of automatically marking the "
|
||||
"image read-only.");
|
||||
ret = bdrv_set_read_only(bs, true, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* read header */
|
||||
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -684,10 +684,10 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
const char *protocol_delimiter;
|
||||
int ret;
|
||||
|
||||
|
||||
if (flags & BDRV_O_RDWR) {
|
||||
error_setg(errp, "curl block device does not support writes");
|
||||
return -EROFS;
|
||||
ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes",
|
||||
errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!libcurl_initialized) {
|
||||
|
|
16
block/dmg.c
16
block/dmg.c
|
@ -413,23 +413,17 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
int64_t offset;
|
||||
int ret;
|
||||
|
||||
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
|
||||
false, errp);
|
||||
if (!bs->file) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!bdrv_is_read_only(bs)) {
|
||||
error_report("Opening dmg images without an explicit read-only=on "
|
||||
"option is deprecated. Future versions will refuse to "
|
||||
"open the image instead of automatically marking the "
|
||||
"image read-only.");
|
||||
ret = bdrv_set_read_only(bs, true, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
block_module_load_one("dmg-bz2");
|
||||
|
||||
s->n_chunks = 0;
|
||||
|
|
|
@ -527,9 +527,22 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
|||
|
||||
s->fd = -1;
|
||||
fd = qemu_open(filename, s->open_flags, 0644);
|
||||
if (fd < 0) {
|
||||
ret = -errno;
|
||||
error_setg_errno(errp, errno, "Could not open '%s'", filename);
|
||||
ret = fd < 0 ? -errno : 0;
|
||||
|
||||
if (ret == -EACCES || ret == -EROFS) {
|
||||
/* Try to degrade to read-only, but if it doesn't work, still use the
|
||||
* normal error message. */
|
||||
if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
|
||||
bdrv_flags &= ~BDRV_O_RDWR;
|
||||
raw_parse_flags(bdrv_flags, &s->open_flags);
|
||||
assert(!(s->open_flags & O_CREAT));
|
||||
fd = qemu_open(filename, s->open_flags);
|
||||
ret = fd < 0 ? -errno : 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not open '%s'", filename);
|
||||
if (ret == -EROFS) {
|
||||
ret = -EACCES;
|
||||
}
|
||||
|
|
|
@ -849,8 +849,16 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
|
|||
qemu_gluster_parse_flags(bdrv_flags, &open_flags);
|
||||
|
||||
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
|
||||
if (!s->fd) {
|
||||
ret = -errno;
|
||||
ret = s->fd ? 0 : -errno;
|
||||
|
||||
if (ret == -EACCES || ret == -EROFS) {
|
||||
/* Try to degrade to read-only, but if it doesn't work, still use the
|
||||
* normal error message. */
|
||||
if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
|
||||
open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
|
||||
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
|
||||
ret = s->fd ? 0 : -errno;
|
||||
}
|
||||
}
|
||||
|
||||
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
|
||||
|
|
|
@ -1878,9 +1878,11 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
/* Check the write protect flag of the LUN if we want to write */
|
||||
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
|
||||
iscsilun->write_protected) {
|
||||
error_setg(errp, "Cannot open a write protected LUN as read-write");
|
||||
ret = -EACCES;
|
||||
goto out;
|
||||
ret = bdrv_apply_auto_read_only(bs, "LUN is write protected", errp);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
flags &= ~BDRV_O_RDWR;
|
||||
}
|
||||
|
||||
iscsi_readcapacity_sync(iscsilun, &local_err);
|
||||
|
|
|
@ -992,11 +992,11 @@ int nbd_client_init(BlockDriverState *bs,
|
|||
logout("Failed to negotiate with the NBD server\n");
|
||||
return ret;
|
||||
}
|
||||
if (client->info.flags & NBD_FLAG_READ_ONLY &&
|
||||
!bdrv_is_read_only(bs)) {
|
||||
error_setg(errp,
|
||||
"request for write access conflicts with read-only export");
|
||||
return -EACCES;
|
||||
if (client->info.flags & NBD_FLAG_READ_ONLY) {
|
||||
ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (client->info.flags & NBD_FLAG_SEND_FUA) {
|
||||
bs->supported_write_flags = BDRV_REQ_FUA;
|
||||
|
|
18
block/qcow.c
18
block/qcow.c
|
@ -140,14 +140,14 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
be32_to_cpus(&header.magic);
|
||||
be32_to_cpus(&header.version);
|
||||
be64_to_cpus(&header.backing_file_offset);
|
||||
be32_to_cpus(&header.backing_file_size);
|
||||
be32_to_cpus(&header.mtime);
|
||||
be64_to_cpus(&header.size);
|
||||
be32_to_cpus(&header.crypt_method);
|
||||
be64_to_cpus(&header.l1_table_offset);
|
||||
header.magic = be32_to_cpu(header.magic);
|
||||
header.version = be32_to_cpu(header.version);
|
||||
header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
|
||||
header.backing_file_size = be32_to_cpu(header.backing_file_size);
|
||||
header.mtime = be32_to_cpu(header.mtime);
|
||||
header.size = be64_to_cpu(header.size);
|
||||
header.crypt_method = be32_to_cpu(header.crypt_method);
|
||||
header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
|
||||
|
||||
if (header.magic != QCOW_MAGIC) {
|
||||
error_setg(errp, "Image not in qcow format");
|
||||
|
@ -270,7 +270,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
}
|
||||
|
||||
for(i = 0;i < s->l1_size; i++) {
|
||||
be64_to_cpus(&s->l1_table[i]);
|
||||
s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
|
||||
}
|
||||
|
||||
/* alloc L2 cache (max. 64k * 16 * 8 = 8 MB) */
|
||||
|
|
|
@ -118,7 +118,7 @@ static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
|
|||
size_t i;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
cpu_to_be64s(&bitmap_table[i]);
|
||||
bitmap_table[i] = cpu_to_be64(bitmap_table[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
|
|||
}
|
||||
|
||||
for (i = 0; i < tb->size; ++i) {
|
||||
be64_to_cpus(&table[i]);
|
||||
table[i] = be64_to_cpu(table[i]);
|
||||
ret = check_table_entry(table[i], s->cluster_size);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
|
@ -394,20 +394,20 @@ fail:
|
|||
|
||||
static inline void bitmap_dir_entry_to_cpu(Qcow2BitmapDirEntry *entry)
|
||||
{
|
||||
be64_to_cpus(&entry->bitmap_table_offset);
|
||||
be32_to_cpus(&entry->bitmap_table_size);
|
||||
be32_to_cpus(&entry->flags);
|
||||
be16_to_cpus(&entry->name_size);
|
||||
be32_to_cpus(&entry->extra_data_size);
|
||||
entry->bitmap_table_offset = be64_to_cpu(entry->bitmap_table_offset);
|
||||
entry->bitmap_table_size = be32_to_cpu(entry->bitmap_table_size);
|
||||
entry->flags = be32_to_cpu(entry->flags);
|
||||
entry->name_size = be16_to_cpu(entry->name_size);
|
||||
entry->extra_data_size = be32_to_cpu(entry->extra_data_size);
|
||||
}
|
||||
|
||||
static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
|
||||
{
|
||||
cpu_to_be64s(&entry->bitmap_table_offset);
|
||||
cpu_to_be32s(&entry->bitmap_table_size);
|
||||
cpu_to_be32s(&entry->flags);
|
||||
cpu_to_be16s(&entry->name_size);
|
||||
cpu_to_be32s(&entry->extra_data_size);
|
||||
entry->bitmap_table_offset = cpu_to_be64(entry->bitmap_table_offset);
|
||||
entry->bitmap_table_size = cpu_to_be32(entry->bitmap_table_size);
|
||||
entry->flags = cpu_to_be32(entry->flags);
|
||||
entry->name_size = cpu_to_be16(entry->name_size);
|
||||
entry->extra_data_size = cpu_to_be32(entry->extra_data_size);
|
||||
}
|
||||
|
||||
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
|
||||
|
|
|
@ -210,8 +210,8 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
|||
"pread fail from offset %" PRIu64, offset);
|
||||
return 1;
|
||||
}
|
||||
be32_to_cpus(&ext.magic);
|
||||
be32_to_cpus(&ext.len);
|
||||
ext.magic = be32_to_cpu(ext.magic);
|
||||
ext.len = be32_to_cpu(ext.len);
|
||||
offset += sizeof(ext);
|
||||
#ifdef DEBUG_EXT
|
||||
printf("ext.magic = 0x%x\n", ext.magic);
|
||||
|
@ -279,8 +279,8 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
|||
"Unable to read CRYPTO header extension");
|
||||
return ret;
|
||||
}
|
||||
be64_to_cpus(&s->crypto_header.offset);
|
||||
be64_to_cpus(&s->crypto_header.length);
|
||||
s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
|
||||
s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
|
||||
|
||||
if ((s->crypto_header.offset % s->cluster_size) != 0) {
|
||||
error_setg(errp, "Encryption header offset '%" PRIu64 "' is "
|
||||
|
@ -342,9 +342,11 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
be32_to_cpus(&bitmaps_ext.nb_bitmaps);
|
||||
be64_to_cpus(&bitmaps_ext.bitmap_directory_size);
|
||||
be64_to_cpus(&bitmaps_ext.bitmap_directory_offset);
|
||||
bitmaps_ext.nb_bitmaps = be32_to_cpu(bitmaps_ext.nb_bitmaps);
|
||||
bitmaps_ext.bitmap_directory_size =
|
||||
be64_to_cpu(bitmaps_ext.bitmap_directory_size);
|
||||
bitmaps_ext.bitmap_directory_offset =
|
||||
be64_to_cpu(bitmaps_ext.bitmap_directory_offset);
|
||||
|
||||
if (bitmaps_ext.nb_bitmaps > QCOW2_MAX_BITMAPS) {
|
||||
error_setg(errp,
|
||||
|
@ -1159,19 +1161,20 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
|
|||
error_setg_errno(errp, -ret, "Could not read qcow2 header");
|
||||
goto fail;
|
||||
}
|
||||
be32_to_cpus(&header.magic);
|
||||
be32_to_cpus(&header.version);
|
||||
be64_to_cpus(&header.backing_file_offset);
|
||||
be32_to_cpus(&header.backing_file_size);
|
||||
be64_to_cpus(&header.size);
|
||||
be32_to_cpus(&header.cluster_bits);
|
||||
be32_to_cpus(&header.crypt_method);
|
||||
be64_to_cpus(&header.l1_table_offset);
|
||||
be32_to_cpus(&header.l1_size);
|
||||
be64_to_cpus(&header.refcount_table_offset);
|
||||
be32_to_cpus(&header.refcount_table_clusters);
|
||||
be64_to_cpus(&header.snapshots_offset);
|
||||
be32_to_cpus(&header.nb_snapshots);
|
||||
header.magic = be32_to_cpu(header.magic);
|
||||
header.version = be32_to_cpu(header.version);
|
||||
header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
|
||||
header.backing_file_size = be32_to_cpu(header.backing_file_size);
|
||||
header.size = be64_to_cpu(header.size);
|
||||
header.cluster_bits = be32_to_cpu(header.cluster_bits);
|
||||
header.crypt_method = be32_to_cpu(header.crypt_method);
|
||||
header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
|
||||
header.l1_size = be32_to_cpu(header.l1_size);
|
||||
header.refcount_table_offset = be64_to_cpu(header.refcount_table_offset);
|
||||
header.refcount_table_clusters =
|
||||
be32_to_cpu(header.refcount_table_clusters);
|
||||
header.snapshots_offset = be64_to_cpu(header.snapshots_offset);
|
||||
header.nb_snapshots = be32_to_cpu(header.nb_snapshots);
|
||||
|
||||
if (header.magic != QCOW_MAGIC) {
|
||||
error_setg(errp, "Image is not in qcow2 format");
|
||||
|
@ -1207,11 +1210,12 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
|
|||
header.refcount_order = 4;
|
||||
header.header_length = 72;
|
||||
} else {
|
||||
be64_to_cpus(&header.incompatible_features);
|
||||
be64_to_cpus(&header.compatible_features);
|
||||
be64_to_cpus(&header.autoclear_features);
|
||||
be32_to_cpus(&header.refcount_order);
|
||||
be32_to_cpus(&header.header_length);
|
||||
header.incompatible_features =
|
||||
be64_to_cpu(header.incompatible_features);
|
||||
header.compatible_features = be64_to_cpu(header.compatible_features);
|
||||
header.autoclear_features = be64_to_cpu(header.autoclear_features);
|
||||
header.refcount_order = be32_to_cpu(header.refcount_order);
|
||||
header.header_length = be32_to_cpu(header.header_length);
|
||||
|
||||
if (header.header_length < 104) {
|
||||
error_setg(errp, "qcow2 header too short");
|
||||
|
@ -1400,7 +1404,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
|
|||
goto fail;
|
||||
}
|
||||
for(i = 0;i < s->l1_size; i++) {
|
||||
be64_to_cpus(&s->l1_table[i]);
|
||||
s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1673,7 +1677,7 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
|
|||
|
||||
if (bs->encrypted) {
|
||||
/* Encryption works on a sector granularity */
|
||||
bs->bl.request_alignment = BDRV_SECTOR_SIZE;
|
||||
bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
|
||||
}
|
||||
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
|
||||
bs->bl.pdiscard_alignment = s->cluster_size;
|
||||
|
@ -2392,13 +2396,13 @@ int qcow2_update_header(BlockDriverState *bs)
|
|||
|
||||
/* Full disk encryption header pointer extension */
|
||||
if (s->crypto_header.offset != 0) {
|
||||
cpu_to_be64s(&s->crypto_header.offset);
|
||||
cpu_to_be64s(&s->crypto_header.length);
|
||||
s->crypto_header.offset = cpu_to_be64(s->crypto_header.offset);
|
||||
s->crypto_header.length = cpu_to_be64(s->crypto_header.length);
|
||||
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_CRYPTO_HEADER,
|
||||
&s->crypto_header, sizeof(s->crypto_header),
|
||||
buflen);
|
||||
be64_to_cpus(&s->crypto_header.offset);
|
||||
be64_to_cpus(&s->crypto_header.length);
|
||||
s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
|
||||
s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -437,23 +437,7 @@ static bool quorum_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64 " ",
|
||||
acb->offset, acb->bytes);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static bool quorum_compare(QuorumAIOCB *acb,
|
||||
QEMUIOVector *a,
|
||||
QEMUIOVector *b)
|
||||
static bool quorum_compare(QuorumAIOCB *acb, QEMUIOVector *a, QEMUIOVector *b)
|
||||
{
|
||||
BDRVQuorumState *s = acb->bs->opaque;
|
||||
ssize_t offset;
|
||||
|
@ -462,8 +446,10 @@ static bool quorum_compare(QuorumAIOCB *acb,
|
|||
if (s->is_blkverify) {
|
||||
offset = qemu_iovec_compare(a, b);
|
||||
if (offset != -1) {
|
||||
quorum_err(acb, "contents mismatch at offset %" PRIu64,
|
||||
acb->offset + offset);
|
||||
fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64
|
||||
" contents mismatch at offset %" PRIu64 "\n",
|
||||
acb->offset, acb->bytes, acb->offset + offset);
|
||||
exit(1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -926,13 +912,12 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
s->read_pattern = ret;
|
||||
|
||||
if (s->read_pattern == QUORUM_READ_PATTERN_QUORUM) {
|
||||
/* is the driver in blkverify mode */
|
||||
if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false) &&
|
||||
s->num_children == 2 && s->threshold == 2) {
|
||||
s->is_blkverify = true;
|
||||
} else if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false)) {
|
||||
fprintf(stderr, "blkverify mode is set by setting blkverify=on "
|
||||
"and using two files with vote_threshold=2\n");
|
||||
s->is_blkverify = qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false);
|
||||
if (s->is_blkverify && (s->num_children != 2 || s->threshold != 2)) {
|
||||
error_setg(&local_err, "blkverify=on can only be set if there are "
|
||||
"exactly two files and vote-threshold is 2");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
s->rewrite_corrupted = qemu_opt_get_bool(opts, QUORUM_OPT_REWRITE,
|
||||
|
@ -1007,6 +992,11 @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
|
|||
char indexstr[32];
|
||||
int ret;
|
||||
|
||||
if (s->is_blkverify) {
|
||||
error_setg(errp, "Cannot add a child to a quorum in blkverify mode");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(s->num_children <= INT_MAX / sizeof(BdrvChild *));
|
||||
if (s->num_children == INT_MAX / sizeof(BdrvChild *) ||
|
||||
s->next_child_index == UINT_MAX) {
|
||||
|
@ -1061,6 +1051,9 @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
|
|||
return;
|
||||
}
|
||||
|
||||
/* We know now that num_children > threshold, so blkverify must be false */
|
||||
assert(!s->is_blkverify);
|
||||
|
||||
bdrv_drained_begin(bs);
|
||||
|
||||
/* We can safely remove this child now */
|
||||
|
|
14
block/rbd.c
14
block/rbd.c
|
@ -780,16 +780,10 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
/* If we are using an rbd snapshot, we must be r/o, otherwise
|
||||
* leave as-is */
|
||||
if (s->snap != NULL) {
|
||||
if (!bdrv_is_read_only(bs)) {
|
||||
error_report("Opening rbd snapshots without an explicit "
|
||||
"read-only=on option is deprecated. Future versions "
|
||||
"will refuse to open the image instead of "
|
||||
"automatically marking the image read-only.");
|
||||
r = bdrv_set_read_only(bs, true, &local_err);
|
||||
if (r < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
goto failed_open;
|
||||
}
|
||||
r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp);
|
||||
if (r < 0) {
|
||||
rbd_close(s->image);
|
||||
goto failed_open;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
68
block/vdi.c
68
block/vdi.c
|
@ -85,7 +85,7 @@
|
|||
#define BLOCK_OPT_STATIC "static"
|
||||
|
||||
#define SECTOR_SIZE 512
|
||||
#define DEFAULT_CLUSTER_SIZE (1 * MiB)
|
||||
#define DEFAULT_CLUSTER_SIZE S_1MiB
|
||||
|
||||
#if defined(CONFIG_VDI_DEBUG)
|
||||
#define VDI_DEBUG 1
|
||||
|
@ -187,22 +187,22 @@ typedef struct {
|
|||
|
||||
static void vdi_header_to_cpu(VdiHeader *header)
|
||||
{
|
||||
le32_to_cpus(&header->signature);
|
||||
le32_to_cpus(&header->version);
|
||||
le32_to_cpus(&header->header_size);
|
||||
le32_to_cpus(&header->image_type);
|
||||
le32_to_cpus(&header->image_flags);
|
||||
le32_to_cpus(&header->offset_bmap);
|
||||
le32_to_cpus(&header->offset_data);
|
||||
le32_to_cpus(&header->cylinders);
|
||||
le32_to_cpus(&header->heads);
|
||||
le32_to_cpus(&header->sectors);
|
||||
le32_to_cpus(&header->sector_size);
|
||||
le64_to_cpus(&header->disk_size);
|
||||
le32_to_cpus(&header->block_size);
|
||||
le32_to_cpus(&header->block_extra);
|
||||
le32_to_cpus(&header->blocks_in_image);
|
||||
le32_to_cpus(&header->blocks_allocated);
|
||||
header->signature = le32_to_cpu(header->signature);
|
||||
header->version = le32_to_cpu(header->version);
|
||||
header->header_size = le32_to_cpu(header->header_size);
|
||||
header->image_type = le32_to_cpu(header->image_type);
|
||||
header->image_flags = le32_to_cpu(header->image_flags);
|
||||
header->offset_bmap = le32_to_cpu(header->offset_bmap);
|
||||
header->offset_data = le32_to_cpu(header->offset_data);
|
||||
header->cylinders = le32_to_cpu(header->cylinders);
|
||||
header->heads = le32_to_cpu(header->heads);
|
||||
header->sectors = le32_to_cpu(header->sectors);
|
||||
header->sector_size = le32_to_cpu(header->sector_size);
|
||||
header->disk_size = le64_to_cpu(header->disk_size);
|
||||
header->block_size = le32_to_cpu(header->block_size);
|
||||
header->block_extra = le32_to_cpu(header->block_extra);
|
||||
header->blocks_in_image = le32_to_cpu(header->blocks_in_image);
|
||||
header->blocks_allocated = le32_to_cpu(header->blocks_allocated);
|
||||
qemu_uuid_bswap(&header->uuid_image);
|
||||
qemu_uuid_bswap(&header->uuid_last_snap);
|
||||
qemu_uuid_bswap(&header->uuid_link);
|
||||
|
@ -211,22 +211,22 @@ static void vdi_header_to_cpu(VdiHeader *header)
|
|||
|
||||
static void vdi_header_to_le(VdiHeader *header)
|
||||
{
|
||||
cpu_to_le32s(&header->signature);
|
||||
cpu_to_le32s(&header->version);
|
||||
cpu_to_le32s(&header->header_size);
|
||||
cpu_to_le32s(&header->image_type);
|
||||
cpu_to_le32s(&header->image_flags);
|
||||
cpu_to_le32s(&header->offset_bmap);
|
||||
cpu_to_le32s(&header->offset_data);
|
||||
cpu_to_le32s(&header->cylinders);
|
||||
cpu_to_le32s(&header->heads);
|
||||
cpu_to_le32s(&header->sectors);
|
||||
cpu_to_le32s(&header->sector_size);
|
||||
cpu_to_le64s(&header->disk_size);
|
||||
cpu_to_le32s(&header->block_size);
|
||||
cpu_to_le32s(&header->block_extra);
|
||||
cpu_to_le32s(&header->blocks_in_image);
|
||||
cpu_to_le32s(&header->blocks_allocated);
|
||||
header->signature = cpu_to_le32(header->signature);
|
||||
header->version = cpu_to_le32(header->version);
|
||||
header->header_size = cpu_to_le32(header->header_size);
|
||||
header->image_type = cpu_to_le32(header->image_type);
|
||||
header->image_flags = cpu_to_le32(header->image_flags);
|
||||
header->offset_bmap = cpu_to_le32(header->offset_bmap);
|
||||
header->offset_data = cpu_to_le32(header->offset_data);
|
||||
header->cylinders = cpu_to_le32(header->cylinders);
|
||||
header->heads = cpu_to_le32(header->heads);
|
||||
header->sectors = cpu_to_le32(header->sectors);
|
||||
header->sector_size = cpu_to_le32(header->sector_size);
|
||||
header->disk_size = cpu_to_le64(header->disk_size);
|
||||
header->block_size = cpu_to_le32(header->block_size);
|
||||
header->block_extra = cpu_to_le32(header->block_extra);
|
||||
header->blocks_in_image = cpu_to_le32(header->blocks_in_image);
|
||||
header->blocks_allocated = cpu_to_le32(header->blocks_allocated);
|
||||
qemu_uuid_bswap(&header->uuid_image);
|
||||
qemu_uuid_bswap(&header->uuid_last_snap);
|
||||
qemu_uuid_bswap(&header->uuid_link);
|
||||
|
@ -432,7 +432,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
goto fail;
|
||||
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
|
||||
error_setg(errp, "unsupported VDI image (block size %" PRIu32
|
||||
" is not %" PRIu64 ")",
|
||||
" is not %" PRIu32 ")",
|
||||
header.block_size, DEFAULT_CLUSTER_SIZE);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
|
|
|
@ -35,18 +35,18 @@ void vhdx_header_le_import(VHDXHeader *h)
|
|||
{
|
||||
assert(h != NULL);
|
||||
|
||||
le32_to_cpus(&h->signature);
|
||||
le32_to_cpus(&h->checksum);
|
||||
le64_to_cpus(&h->sequence_number);
|
||||
h->signature = le32_to_cpu(h->signature);
|
||||
h->checksum = le32_to_cpu(h->checksum);
|
||||
h->sequence_number = le64_to_cpu(h->sequence_number);
|
||||
|
||||
leguid_to_cpus(&h->file_write_guid);
|
||||
leguid_to_cpus(&h->data_write_guid);
|
||||
leguid_to_cpus(&h->log_guid);
|
||||
|
||||
le16_to_cpus(&h->log_version);
|
||||
le16_to_cpus(&h->version);
|
||||
le32_to_cpus(&h->log_length);
|
||||
le64_to_cpus(&h->log_offset);
|
||||
h->log_version = le16_to_cpu(h->log_version);
|
||||
h->version = le16_to_cpu(h->version);
|
||||
h->log_length = le32_to_cpu(h->log_length);
|
||||
h->log_offset = le64_to_cpu(h->log_offset);
|
||||
}
|
||||
|
||||
void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h)
|
||||
|
@ -80,68 +80,68 @@ void vhdx_log_desc_le_import(VHDXLogDescriptor *d)
|
|||
{
|
||||
assert(d != NULL);
|
||||
|
||||
le32_to_cpus(&d->signature);
|
||||
le64_to_cpus(&d->file_offset);
|
||||
le64_to_cpus(&d->sequence_number);
|
||||
d->signature = le32_to_cpu(d->signature);
|
||||
d->file_offset = le64_to_cpu(d->file_offset);
|
||||
d->sequence_number = le64_to_cpu(d->sequence_number);
|
||||
}
|
||||
|
||||
void vhdx_log_desc_le_export(VHDXLogDescriptor *d)
|
||||
{
|
||||
assert(d != NULL);
|
||||
|
||||
cpu_to_le32s(&d->signature);
|
||||
cpu_to_le32s(&d->trailing_bytes);
|
||||
cpu_to_le64s(&d->leading_bytes);
|
||||
cpu_to_le64s(&d->file_offset);
|
||||
cpu_to_le64s(&d->sequence_number);
|
||||
d->signature = cpu_to_le32(d->signature);
|
||||
d->trailing_bytes = cpu_to_le32(d->trailing_bytes);
|
||||
d->leading_bytes = cpu_to_le64(d->leading_bytes);
|
||||
d->file_offset = cpu_to_le64(d->file_offset);
|
||||
d->sequence_number = cpu_to_le64(d->sequence_number);
|
||||
}
|
||||
|
||||
void vhdx_log_data_le_import(VHDXLogDataSector *d)
|
||||
{
|
||||
assert(d != NULL);
|
||||
|
||||
le32_to_cpus(&d->data_signature);
|
||||
le32_to_cpus(&d->sequence_high);
|
||||
le32_to_cpus(&d->sequence_low);
|
||||
d->data_signature = le32_to_cpu(d->data_signature);
|
||||
d->sequence_high = le32_to_cpu(d->sequence_high);
|
||||
d->sequence_low = le32_to_cpu(d->sequence_low);
|
||||
}
|
||||
|
||||
void vhdx_log_data_le_export(VHDXLogDataSector *d)
|
||||
{
|
||||
assert(d != NULL);
|
||||
|
||||
cpu_to_le32s(&d->data_signature);
|
||||
cpu_to_le32s(&d->sequence_high);
|
||||
cpu_to_le32s(&d->sequence_low);
|
||||
d->data_signature = cpu_to_le32(d->data_signature);
|
||||
d->sequence_high = cpu_to_le32(d->sequence_high);
|
||||
d->sequence_low = cpu_to_le32(d->sequence_low);
|
||||
}
|
||||
|
||||
void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr)
|
||||
{
|
||||
assert(hdr != NULL);
|
||||
|
||||
le32_to_cpus(&hdr->signature);
|
||||
le32_to_cpus(&hdr->checksum);
|
||||
le32_to_cpus(&hdr->entry_length);
|
||||
le32_to_cpus(&hdr->tail);
|
||||
le64_to_cpus(&hdr->sequence_number);
|
||||
le32_to_cpus(&hdr->descriptor_count);
|
||||
hdr->signature = le32_to_cpu(hdr->signature);
|
||||
hdr->checksum = le32_to_cpu(hdr->checksum);
|
||||
hdr->entry_length = le32_to_cpu(hdr->entry_length);
|
||||
hdr->tail = le32_to_cpu(hdr->tail);
|
||||
hdr->sequence_number = le64_to_cpu(hdr->sequence_number);
|
||||
hdr->descriptor_count = le32_to_cpu(hdr->descriptor_count);
|
||||
leguid_to_cpus(&hdr->log_guid);
|
||||
le64_to_cpus(&hdr->flushed_file_offset);
|
||||
le64_to_cpus(&hdr->last_file_offset);
|
||||
hdr->flushed_file_offset = le64_to_cpu(hdr->flushed_file_offset);
|
||||
hdr->last_file_offset = le64_to_cpu(hdr->last_file_offset);
|
||||
}
|
||||
|
||||
void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr)
|
||||
{
|
||||
assert(hdr != NULL);
|
||||
|
||||
cpu_to_le32s(&hdr->signature);
|
||||
cpu_to_le32s(&hdr->checksum);
|
||||
cpu_to_le32s(&hdr->entry_length);
|
||||
cpu_to_le32s(&hdr->tail);
|
||||
cpu_to_le64s(&hdr->sequence_number);
|
||||
cpu_to_le32s(&hdr->descriptor_count);
|
||||
hdr->signature = cpu_to_le32(hdr->signature);
|
||||
hdr->checksum = cpu_to_le32(hdr->checksum);
|
||||
hdr->entry_length = cpu_to_le32(hdr->entry_length);
|
||||
hdr->tail = cpu_to_le32(hdr->tail);
|
||||
hdr->sequence_number = cpu_to_le64(hdr->sequence_number);
|
||||
hdr->descriptor_count = cpu_to_le32(hdr->descriptor_count);
|
||||
cpu_to_leguids(&hdr->log_guid);
|
||||
cpu_to_le64s(&hdr->flushed_file_offset);
|
||||
cpu_to_le64s(&hdr->last_file_offset);
|
||||
hdr->flushed_file_offset = cpu_to_le64(hdr->flushed_file_offset);
|
||||
hdr->last_file_offset = cpu_to_le64(hdr->last_file_offset);
|
||||
}
|
||||
|
||||
|
||||
|
@ -150,18 +150,18 @@ void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr)
|
|||
{
|
||||
assert(hdr != NULL);
|
||||
|
||||
le32_to_cpus(&hdr->signature);
|
||||
le32_to_cpus(&hdr->checksum);
|
||||
le32_to_cpus(&hdr->entry_count);
|
||||
hdr->signature = le32_to_cpu(hdr->signature);
|
||||
hdr->checksum = le32_to_cpu(hdr->checksum);
|
||||
hdr->entry_count = le32_to_cpu(hdr->entry_count);
|
||||
}
|
||||
|
||||
void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr)
|
||||
{
|
||||
assert(hdr != NULL);
|
||||
|
||||
cpu_to_le32s(&hdr->signature);
|
||||
cpu_to_le32s(&hdr->checksum);
|
||||
cpu_to_le32s(&hdr->entry_count);
|
||||
hdr->signature = cpu_to_le32(hdr->signature);
|
||||
hdr->checksum = cpu_to_le32(hdr->checksum);
|
||||
hdr->entry_count = cpu_to_le32(hdr->entry_count);
|
||||
}
|
||||
|
||||
void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
|
||||
|
@ -169,9 +169,9 @@ void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
|
|||
assert(e != NULL);
|
||||
|
||||
leguid_to_cpus(&e->guid);
|
||||
le64_to_cpus(&e->file_offset);
|
||||
le32_to_cpus(&e->length);
|
||||
le32_to_cpus(&e->data_bits);
|
||||
e->file_offset = le64_to_cpu(e->file_offset);
|
||||
e->length = le32_to_cpu(e->length);
|
||||
e->data_bits = le32_to_cpu(e->data_bits);
|
||||
}
|
||||
|
||||
void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
|
||||
|
@ -179,9 +179,9 @@ void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
|
|||
assert(e != NULL);
|
||||
|
||||
cpu_to_leguids(&e->guid);
|
||||
cpu_to_le64s(&e->file_offset);
|
||||
cpu_to_le32s(&e->length);
|
||||
cpu_to_le32s(&e->data_bits);
|
||||
e->file_offset = cpu_to_le64(e->file_offset);
|
||||
e->length = cpu_to_le32(e->length);
|
||||
e->data_bits = cpu_to_le32(e->data_bits);
|
||||
}
|
||||
|
||||
|
||||
|
@ -190,16 +190,16 @@ void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr)
|
|||
{
|
||||
assert(hdr != NULL);
|
||||
|
||||
le64_to_cpus(&hdr->signature);
|
||||
le16_to_cpus(&hdr->entry_count);
|
||||
hdr->signature = le64_to_cpu(hdr->signature);
|
||||
hdr->entry_count = le16_to_cpu(hdr->entry_count);
|
||||
}
|
||||
|
||||
void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr)
|
||||
{
|
||||
assert(hdr != NULL);
|
||||
|
||||
cpu_to_le64s(&hdr->signature);
|
||||
cpu_to_le16s(&hdr->entry_count);
|
||||
hdr->signature = cpu_to_le64(hdr->signature);
|
||||
hdr->entry_count = cpu_to_le16(hdr->entry_count);
|
||||
}
|
||||
|
||||
void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
|
||||
|
@ -207,16 +207,16 @@ void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
|
|||
assert(e != NULL);
|
||||
|
||||
leguid_to_cpus(&e->item_id);
|
||||
le32_to_cpus(&e->offset);
|
||||
le32_to_cpus(&e->length);
|
||||
le32_to_cpus(&e->data_bits);
|
||||
e->offset = le32_to_cpu(e->offset);
|
||||
e->length = le32_to_cpu(e->length);
|
||||
e->data_bits = le32_to_cpu(e->data_bits);
|
||||
}
|
||||
void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e)
|
||||
{
|
||||
assert(e != NULL);
|
||||
|
||||
cpu_to_leguids(&e->item_id);
|
||||
cpu_to_le32s(&e->offset);
|
||||
cpu_to_le32s(&e->length);
|
||||
cpu_to_le32s(&e->data_bits);
|
||||
e->offset = cpu_to_le32(e->offset);
|
||||
e->length = cpu_to_le32(e->length);
|
||||
e->data_bits = cpu_to_le32(e->data_bits);
|
||||
}
|
||||
|
|
|
@ -835,11 +835,11 @@ static void vhdx_log_raw_to_le_sector(VHDXLogDescriptor *desc,
|
|||
/* 8 + 4084 + 4 = 4096, 1 log sector */
|
||||
memcpy(&desc->leading_bytes, data, 8);
|
||||
data += 8;
|
||||
cpu_to_le64s(&desc->leading_bytes);
|
||||
desc->leading_bytes = cpu_to_le64(desc->leading_bytes);
|
||||
memcpy(sector->data, data, 4084);
|
||||
data += 4084;
|
||||
memcpy(&desc->trailing_bytes, data, 4);
|
||||
cpu_to_le32s(&desc->trailing_bytes);
|
||||
desc->trailing_bytes = cpu_to_le32(desc->trailing_bytes);
|
||||
data += 4;
|
||||
|
||||
sector->sequence_high = (uint32_t) (seq >> 32);
|
||||
|
|
18
block/vhdx.c
18
block/vhdx.c
|
@ -156,7 +156,7 @@ uint32_t vhdx_update_checksum(uint8_t *buf, size_t size, int crc_offset)
|
|||
|
||||
memset(buf + crc_offset, 0, sizeof(crc));
|
||||
crc = crc32c(0xffffffff, buf, size);
|
||||
cpu_to_le32s(&crc);
|
||||
crc = cpu_to_le32(crc);
|
||||
memcpy(buf + crc_offset, &crc, sizeof(crc));
|
||||
|
||||
return crc;
|
||||
|
@ -753,8 +753,8 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
le32_to_cpus(&s->params.block_size);
|
||||
le32_to_cpus(&s->params.data_bits);
|
||||
s->params.block_size = le32_to_cpu(s->params.block_size);
|
||||
s->params.data_bits = le32_to_cpu(s->params.data_bits);
|
||||
|
||||
|
||||
/* We now have the file parameters, so we can tell if this is a
|
||||
|
@ -803,9 +803,9 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
le64_to_cpus(&s->virtual_disk_size);
|
||||
le32_to_cpus(&s->logical_sector_size);
|
||||
le32_to_cpus(&s->physical_sector_size);
|
||||
s->virtual_disk_size = le64_to_cpu(s->virtual_disk_size);
|
||||
s->logical_sector_size = le32_to_cpu(s->logical_sector_size);
|
||||
s->physical_sector_size = le32_to_cpu(s->physical_sector_size);
|
||||
|
||||
if (s->params.block_size < VHDX_BLOCK_SIZE_MIN ||
|
||||
s->params.block_size > VHDX_BLOCK_SIZE_MAX) {
|
||||
|
@ -985,7 +985,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
/* endian convert, and verify populated BAT field file offsets against
|
||||
* region table and log entries */
|
||||
for (i = 0; i < s->bat_entries; i++) {
|
||||
le64_to_cpus(&s->bat[i]);
|
||||
s->bat[i] = le64_to_cpu(s->bat[i]);
|
||||
if (payblocks--) {
|
||||
/* payload bat entries */
|
||||
if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) ==
|
||||
|
@ -1509,7 +1509,7 @@ static int vhdx_create_new_metadata(BlockBackend *blk,
|
|||
mt_file_params->block_size = cpu_to_le32(block_size);
|
||||
if (type == VHDX_TYPE_FIXED) {
|
||||
mt_file_params->data_bits |= VHDX_PARAMS_LEAVE_BLOCKS_ALLOCED;
|
||||
cpu_to_le32s(&mt_file_params->data_bits);
|
||||
mt_file_params->data_bits = cpu_to_le32(mt_file_params->data_bits);
|
||||
}
|
||||
|
||||
vhdx_guid_generate(&mt_page83->page_83_data);
|
||||
|
@ -1656,7 +1656,7 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
|
|||
sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);
|
||||
vhdx_update_bat_table_entry(blk_bs(blk), s, &sinfo, &unused, &unused,
|
||||
block_state);
|
||||
cpu_to_le64s(&s->bat[sinfo.bat_idx]);
|
||||
s->bat[sinfo.bat_idx] = cpu_to_le64(s->bat[sinfo.bat_idx]);
|
||||
sector_num += s->sectors_per_block;
|
||||
}
|
||||
ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
|
||||
|
|
12
block/vhdx.h
12
block/vhdx.h
|
@ -420,16 +420,16 @@ int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
|
|||
|
||||
static inline void leguid_to_cpus(MSGUID *guid)
|
||||
{
|
||||
le32_to_cpus(&guid->data1);
|
||||
le16_to_cpus(&guid->data2);
|
||||
le16_to_cpus(&guid->data3);
|
||||
guid->data1 = le32_to_cpu(guid->data1);
|
||||
guid->data2 = le16_to_cpu(guid->data2);
|
||||
guid->data3 = le16_to_cpu(guid->data3);
|
||||
}
|
||||
|
||||
static inline void cpu_to_leguids(MSGUID *guid)
|
||||
{
|
||||
cpu_to_le32s(&guid->data1);
|
||||
cpu_to_le16s(&guid->data2);
|
||||
cpu_to_le16s(&guid->data3);
|
||||
guid->data1 = cpu_to_le32(guid->data1);
|
||||
guid->data2 = cpu_to_le16(guid->data2);
|
||||
guid->data3 = cpu_to_le16(guid->data3);
|
||||
}
|
||||
|
||||
void vhdx_header_le_import(VHDXHeader *h);
|
||||
|
|
|
@ -456,10 +456,12 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
}
|
||||
|
||||
qemu_co_mutex_init(&s->lock);
|
||||
qemu_opts_del(opts);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
qemu_opts_del(opts);
|
||||
qemu_vfree(s->pagetable);
|
||||
#ifdef CACHE
|
||||
g_free(s->pageentry_u8);
|
||||
|
|
|
@ -973,10 +973,10 @@ static int init_directories(BDRVVVFATState* s,
|
|||
mapping = array_get(&(s->mapping), i);
|
||||
|
||||
if (mapping->mode & MODE_DIRECTORY) {
|
||||
char *path = mapping->path;
|
||||
mapping->begin = cluster;
|
||||
if(read_directory(s, i)) {
|
||||
error_setg(errp, "Could not read directory %s",
|
||||
mapping->path);
|
||||
error_setg(errp, "Could not read directory %s", path);
|
||||
return -1;
|
||||
}
|
||||
mapping = array_get(&(s->mapping), i);
|
||||
|
@ -1262,15 +1262,9 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
"Unable to set VVFAT to 'rw' when drive is read-only");
|
||||
goto fail;
|
||||
}
|
||||
} else if (!bdrv_is_read_only(bs)) {
|
||||
error_report("Opening non-rw vvfat images without an explicit "
|
||||
"read-only=on option is deprecated. Future versions "
|
||||
"will refuse to open the image instead of "
|
||||
"automatically marking the image read-only.");
|
||||
/* read only is the default for safety */
|
||||
ret = bdrv_set_read_only(bs, true, &local_err);
|
||||
} else {
|
||||
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -3130,6 +3124,7 @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
|
|||
int parent_flags, QDict *parent_options)
|
||||
{
|
||||
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
|
||||
qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
|
||||
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
|
||||
}
|
||||
|
||||
|
|
|
@ -590,6 +590,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
|
|||
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
|
||||
qdict_set_default_str(bs_opts, BDRV_OPT_READ_ONLY,
|
||||
read_only ? "on" : "off");
|
||||
qdict_set_default_str(bs_opts, BDRV_OPT_AUTO_READ_ONLY, "on");
|
||||
assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0);
|
||||
|
||||
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
||||
|
@ -2651,7 +2652,7 @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
|
|||
|
||||
bdrv_flags = blk_get_open_flags_from_root_state(blk);
|
||||
bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
|
||||
BDRV_O_PROTOCOL);
|
||||
BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
|
||||
|
||||
if (!has_read_only) {
|
||||
read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
|
||||
|
|
|
@ -572,7 +572,7 @@ help_string_append(const char *name, void *opaque)
|
|||
{
|
||||
GString *str = opaque;
|
||||
|
||||
g_string_append_printf(str, "\n%s", name);
|
||||
g_string_append_printf(str, "\n %s", name);
|
||||
}
|
||||
|
||||
static const char *chardev_alias_translate(const char *name)
|
||||
|
|
|
@ -102,6 +102,8 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
|
|||
Error **errp)
|
||||
{
|
||||
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
|
||||
block->sector_size = QCRYPTO_BLOCK_QCOW_SECTOR_SIZE;
|
||||
block->payload_offset = 0;
|
||||
return 0;
|
||||
} else {
|
||||
if (!options->u.qcow.key_secret) {
|
||||
|
|
|
@ -115,6 +115,7 @@ typedef struct HDGeometry {
|
|||
select an appropriate protocol driver,
|
||||
ignoring the format layer */
|
||||
#define BDRV_O_NO_IO 0x10000 /* don't initialize for I/O */
|
||||
#define BDRV_O_AUTO_RDONLY 0x20000 /* degrade to read-only if opening read-write fails */
|
||||
|
||||
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH)
|
||||
|
||||
|
@ -125,6 +126,7 @@ typedef struct HDGeometry {
|
|||
#define BDRV_OPT_CACHE_DIRECT "cache.direct"
|
||||
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
|
||||
#define BDRV_OPT_READ_ONLY "read-only"
|
||||
#define BDRV_OPT_AUTO_READ_ONLY "auto-read-only"
|
||||
#define BDRV_OPT_DISCARD "discard"
|
||||
#define BDRV_OPT_FORCE_SHARE "force-share"
|
||||
|
||||
|
@ -436,7 +438,8 @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
|
|||
bool bdrv_is_read_only(BlockDriverState *bs);
|
||||
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
|
||||
bool ignore_allow_rdw, Error **errp);
|
||||
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
|
||||
int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
|
||||
Error **errp);
|
||||
bool bdrv_is_writable(BlockDriverState *bs);
|
||||
bool bdrv_is_sg(BlockDriverState *bs);
|
||||
bool bdrv_is_inserted(BlockDriverState *bs);
|
||||
|
|
|
@ -132,7 +132,7 @@ typedef int (*qemu_opts_loopfunc)(void *opaque, QemuOpts *opts, Error **errp);
|
|||
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
|
||||
void *opaque, Error **errp);
|
||||
void qemu_opts_print(QemuOpts *opts, const char *sep);
|
||||
void qemu_opts_print_help(QemuOptsList *list);
|
||||
void qemu_opts_print_help(QemuOptsList *list, bool print_caption);
|
||||
void qemu_opts_free(QemuOptsList *list);
|
||||
QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list);
|
||||
|
||||
|
|
|
@ -17,6 +17,24 @@
|
|||
#define PiB (INT64_C(1) << 50)
|
||||
#define EiB (INT64_C(1) << 60)
|
||||
|
||||
/*
|
||||
* The following lookup table is intended to be used when a literal string of
|
||||
* the number of bytes is required (for example if it needs to be stringified).
|
||||
* It can also be used for generic shortcuts of power-of-two sizes.
|
||||
* This table is generated using the AWK script below:
|
||||
*
|
||||
* BEGIN {
|
||||
* suffix="KMGTPE";
|
||||
* for(i=10; i<64; i++) {
|
||||
* val=2**i;
|
||||
* s=substr(suffix, int(i/10), 1);
|
||||
* n=2**(i%10);
|
||||
* pad=21-int(log(n)/log(10));
|
||||
* printf("#define S_%d%siB %*d\n", n, s, pad, val);
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
#define S_1KiB 1024
|
||||
#define S_2KiB 2048
|
||||
#define S_4KiB 4096
|
||||
|
|
|
@ -166,9 +166,9 @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
|
|||
int error);
|
||||
void blk_error_action(BlockBackend *blk, BlockErrorAction action,
|
||||
bool is_read, int error);
|
||||
int blk_is_read_only(BlockBackend *blk);
|
||||
int blk_is_sg(BlockBackend *blk);
|
||||
int blk_enable_write_cache(BlockBackend *blk);
|
||||
bool blk_is_read_only(BlockBackend *blk);
|
||||
bool blk_is_sg(BlockBackend *blk);
|
||||
bool blk_enable_write_cache(BlockBackend *blk);
|
||||
void blk_set_enable_write_cache(BlockBackend *blk, bool wce);
|
||||
void blk_invalidate_cache(BlockBackend *blk, Error **errp);
|
||||
bool blk_is_inserted(BlockBackend *blk);
|
||||
|
|
|
@ -3656,6 +3656,12 @@
|
|||
# either generally or in certain configurations. In this case,
|
||||
# the default value does not work and the option must be
|
||||
# specified explicitly.
|
||||
# @auto-read-only: if true and @read-only is false, QEMU may automatically
|
||||
# decide not to open the image read-write as requested, but
|
||||
# fall back to read-only instead (and switch between the modes
|
||||
# later), e.g. depending on whether the image file is writable
|
||||
# or whether a writing user is attached to the node
|
||||
# (default: false, since 3.1)
|
||||
# @detect-zeroes: detect and optimize zero writes (Since 2.1)
|
||||
# (default: off)
|
||||
# @force-share: force share all permission on added nodes.
|
||||
|
@ -3671,6 +3677,7 @@
|
|||
'*discard': 'BlockdevDiscardOptions',
|
||||
'*cache': 'BlockdevCacheOptions',
|
||||
'*read-only': 'bool',
|
||||
'*auto-read-only': 'bool',
|
||||
'*force-share': 'bool',
|
||||
'*detect-zeroes': 'BlockdevDetectZeroesOptions' },
|
||||
'discriminator': 'driver',
|
||||
|
|
|
@ -285,10 +285,19 @@ int qdev_device_help(QemuOpts *opts)
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (prop_list) {
|
||||
out_printf("%s options:\n", driver);
|
||||
} else {
|
||||
out_printf("There are no options for %s.\n", driver);
|
||||
}
|
||||
for (prop = prop_list; prop; prop = prop->next) {
|
||||
out_printf("%s.%s=%s", driver, prop->value->name, prop->value->type);
|
||||
int len;
|
||||
out_printf(" %s=<%s>%n", prop->value->name, prop->value->type, &len);
|
||||
if (prop->value->has_description) {
|
||||
out_printf(" (%s)\n", prop->value->description);
|
||||
if (len < 24) {
|
||||
out_printf("%*s", 24 - len, "");
|
||||
}
|
||||
out_printf(" - %s\n", prop->value->description);
|
||||
} else {
|
||||
out_printf("\n");
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ static int print_block_option_help(const char *filename, const char *fmt)
|
|||
}
|
||||
|
||||
printf("Supported options:\n");
|
||||
qemu_opts_print_help(create_opts);
|
||||
qemu_opts_print_help(create_opts, false);
|
||||
qemu_opts_free(create_opts);
|
||||
return 0;
|
||||
}
|
||||
|
@ -3773,7 +3773,7 @@ static int print_amend_option_help(const char *format)
|
|||
assert(drv->create_opts);
|
||||
|
||||
printf("Creation options for '%s':\n", format);
|
||||
qemu_opts_print_help(drv->create_opts);
|
||||
qemu_opts_print_help(drv->create_opts, false);
|
||||
printf("\nNote that not all of these options may be amendable.\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -907,7 +907,7 @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
|
|||
memset(cmp_buf, pattern, qiov.size);
|
||||
if (memcmp(buf, cmp_buf, qiov.size)) {
|
||||
printf("Pattern verification failed at offset %"
|
||||
PRId64 ", %zd bytes\n", offset, qiov.size);
|
||||
PRId64 ", %zu bytes\n", offset, qiov.size);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
g_free(cmp_buf);
|
||||
|
@ -1294,7 +1294,7 @@ static void aio_read_done(void *opaque, int ret)
|
|||
memset(cmp_buf, ctx->pattern, ctx->qiov.size);
|
||||
if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
|
||||
printf("Pattern verification failed at offset %"
|
||||
PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
|
||||
PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
|
||||
}
|
||||
g_free(cmp_buf);
|
||||
}
|
||||
|
|
|
@ -168,6 +168,122 @@ echo "== checking that quorum is broken =="
|
|||
|
||||
$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== checking the blkverify mode with broken content =="
|
||||
|
||||
quorum="driver=raw,file.driver=quorum,file.vote-threshold=2,file.blkverify=on"
|
||||
quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw"
|
||||
quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw"
|
||||
quorum="$quorum,file.children.0.driver=raw"
|
||||
quorum="$quorum,file.children.1.driver=raw"
|
||||
|
||||
$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== writing the same data to both files =="
|
||||
|
||||
$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== checking the blkverify mode with valid content =="
|
||||
|
||||
$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== checking the blkverify mode with invalid settings =="
|
||||
|
||||
quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw"
|
||||
quorum="$quorum,file.children.2.driver=raw"
|
||||
|
||||
$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== dynamically adding a child to a quorum =="
|
||||
|
||||
for verify in false true; do
|
||||
run_qemu <<EOF
|
||||
{ "execute": "qmp_capabilities" }
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"driver": "quorum",
|
||||
"node-name": "drive0-quorum",
|
||||
"vote-threshold": 2,
|
||||
"blkverify": ${verify},
|
||||
"children": [
|
||||
{
|
||||
"driver": "$IMGFMT",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_DIR/1.raw"
|
||||
}
|
||||
},
|
||||
{
|
||||
"driver": "$IMGFMT",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_DIR/2.raw"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"node-name": "drive3",
|
||||
"driver": "$IMGFMT",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_DIR/2.raw"
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "execute": "x-blockdev-change",
|
||||
"arguments": { "parent": "drive0-quorum",
|
||||
"node": "drive3" } }
|
||||
{ "execute": "quit" }
|
||||
EOF
|
||||
done
|
||||
|
||||
echo
|
||||
echo "== dynamically removing a child from a quorum =="
|
||||
|
||||
for verify in false true; do
|
||||
for vote_threshold in 1 2; do
|
||||
run_qemu <<EOF
|
||||
{ "execute": "qmp_capabilities" }
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"driver": "quorum",
|
||||
"node-name": "drive0-quorum",
|
||||
"vote-threshold": ${vote_threshold},
|
||||
"blkverify": ${verify},
|
||||
"children": [
|
||||
{
|
||||
"driver": "$IMGFMT",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_DIR/1.raw"
|
||||
}
|
||||
},
|
||||
{
|
||||
"driver": "$IMGFMT",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_DIR/2.raw"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
{ "execute": "x-blockdev-change",
|
||||
"arguments": { "parent": "drive0-quorum",
|
||||
"child": "children.1" } }
|
||||
{ "execute": "quit" }
|
||||
EOF
|
||||
done
|
||||
done
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
|
|
|
@ -55,4 +55,74 @@ wrote 10485760/10485760 bytes at offset 0
|
|||
|
||||
== checking that quorum is broken ==
|
||||
read failed: Input/output error
|
||||
|
||||
== checking the blkverify mode with broken content ==
|
||||
quorum: offset=0 bytes=10485760 contents mismatch at offset 0
|
||||
|
||||
== writing the same data to both files ==
|
||||
wrote 10485760/10485760 bytes at offset 0
|
||||
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 10485760/10485760 bytes at offset 0
|
||||
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
== checking the blkverify mode with valid content ==
|
||||
read 10485760/10485760 bytes at offset 0
|
||||
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
== checking the blkverify mode with invalid settings ==
|
||||
can't open: blkverify=on can only be set if there are exactly two files and vote-threshold is 2
|
||||
|
||||
== dynamically adding a child to a quorum ==
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Cannot add a child to a quorum in blkverify mode"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
|
||||
|
||||
|
||||
== dynamically removing a child from a quorum ==
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "blkverify=on can only be set if there are exactly two files and vote-threshold is 2"}}
|
||||
{"error": {"class": "GenericError", "desc": "Cannot find device=drive0-quorum nor node_name=drive0-quorum"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
|
||||
|
||||
*** done
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt generic
|
||||
_supported_fmt raw
|
||||
_supported_proto nbd
|
||||
_supported_os Linux
|
||||
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Test for auto-read-only
|
||||
#
|
||||
# Copyright (C) 2018 Red Hat, Inc.
|
||||
#
|
||||
# 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=kwolf@redhat.com
|
||||
|
||||
seq=`basename $0`
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here=`pwd`
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
rm -f $TEST_IMG.snap
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt generic
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
function do_run_qemu()
|
||||
{
|
||||
echo Testing: "$@"
|
||||
(
|
||||
if ! test -t 0; then
|
||||
while read cmd; do
|
||||
echo $cmd
|
||||
done
|
||||
fi
|
||||
echo quit
|
||||
) | $QEMU -nographic -monitor stdio -nodefaults "$@"
|
||||
echo
|
||||
}
|
||||
|
||||
function run_qemu()
|
||||
{
|
||||
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp |
|
||||
_filter_generated_node_ids | _filter_imgfmt
|
||||
}
|
||||
|
||||
function run_qemu_info_block()
|
||||
{
|
||||
echo "info block -n" | run_qemu "$@" | grep -e "(file" -e "QEMU_PROG"
|
||||
}
|
||||
|
||||
size=128M
|
||||
|
||||
_make_test_img $size
|
||||
|
||||
echo
|
||||
echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
|
||||
echo
|
||||
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
|
||||
echo
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
|
||||
echo
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
|
||||
|
||||
echo
|
||||
echo "=== -drive with read-only image: read-only/auto-read-only combinations ==="
|
||||
echo
|
||||
|
||||
chmod a-w $TEST_IMG
|
||||
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
|
||||
echo
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
|
||||
echo
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
|
||||
run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
|
||||
|
||||
echo
|
||||
echo "=== -blockdev with read-write image: read-only/auto-read-only combinations ==="
|
||||
echo
|
||||
|
||||
chmod a+w $TEST_IMG
|
||||
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
|
||||
echo
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
|
||||
echo
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
|
||||
|
||||
echo
|
||||
echo "=== -blockdev with read-only image: read-only/auto-read-only combinations ==="
|
||||
echo
|
||||
|
||||
chmod a-w $TEST_IMG
|
||||
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
|
||||
echo
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
|
||||
echo
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
|
||||
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
|
@ -0,0 +1,59 @@
|
|||
QA output created by 232
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
|
||||
=== -drive with read-write image: read-only/auto-read-only combinations ===
|
||||
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file)
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file)
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file)
|
||||
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file)
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file)
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file)
|
||||
|
||||
=== -drive with read-only image: read-only/auto-read-only combinations ===
|
||||
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
|
||||
QEMU_PROG: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=none,read-only=off,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
|
||||
QEMU_PROG: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=none,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
|
||||
=== -blockdev with read-write image: read-only/auto-read-only combinations ===
|
||||
|
||||
node0: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
node0: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
node0: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
|
||||
node0: TEST_DIR/t.IMGFMT (file)
|
||||
node0: TEST_DIR/t.IMGFMT (file)
|
||||
node0: TEST_DIR/t.IMGFMT (file)
|
||||
|
||||
node0: TEST_DIR/t.IMGFMT (file)
|
||||
node0: TEST_DIR/t.IMGFMT (file)
|
||||
node0: TEST_DIR/t.IMGFMT (file)
|
||||
|
||||
=== -blockdev with read-only image: read-only/auto-read-only combinations ===
|
||||
|
||||
node0: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
node0: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
node0: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
|
||||
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read-only=off,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
|
||||
node0: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
|
||||
|
||||
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
|
||||
node0: TEST_DIR/t.IMGFMT (file, read-only)
|
||||
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
|
||||
*** done
|
|
@ -227,3 +227,4 @@
|
|||
227 auto quick
|
||||
229 auto quick
|
||||
231 auto quick
|
||||
232 auto quick
|
||||
|
|
|
@ -224,7 +224,14 @@ static const char *opt_type_to_string(enum QemuOptType type)
|
|||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
void qemu_opts_print_help(QemuOptsList *list)
|
||||
/**
|
||||
* Print the list of options available in the given list. If
|
||||
* @print_caption is true, a caption (including the list name, if it
|
||||
* exists) is printed. The options itself will be indented, so
|
||||
* @print_caption should only be set to false if the caller prints its
|
||||
* own custom caption (so that the indentation makes sense).
|
||||
*/
|
||||
void qemu_opts_print_help(QemuOptsList *list, bool print_caption)
|
||||
{
|
||||
QemuOptDesc *desc;
|
||||
int i;
|
||||
|
@ -234,12 +241,12 @@ void qemu_opts_print_help(QemuOptsList *list)
|
|||
desc = list->desc;
|
||||
while (desc && desc->name) {
|
||||
GString *str = g_string_new(NULL);
|
||||
if (list->name) {
|
||||
g_string_append_printf(str, "%s.", list->name);
|
||||
}
|
||||
g_string_append_printf(str, "%s=%s", desc->name,
|
||||
g_string_append_printf(str, " %s=<%s>", desc->name,
|
||||
opt_type_to_string(desc->type));
|
||||
if (desc->help) {
|
||||
if (str->len < 24) {
|
||||
g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
|
||||
}
|
||||
g_string_append_printf(str, " - %s", desc->help);
|
||||
}
|
||||
g_ptr_array_add(array, g_string_free(str, false));
|
||||
|
@ -247,6 +254,19 @@ void qemu_opts_print_help(QemuOptsList *list)
|
|||
}
|
||||
|
||||
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
|
||||
if (print_caption && array->len > 0) {
|
||||
if (list->name) {
|
||||
printf("%s options:\n", list->name);
|
||||
} else {
|
||||
printf("Options:\n");
|
||||
}
|
||||
} else if (array->len == 0) {
|
||||
if (list->name) {
|
||||
printf("There are no options for %s.\n", list->name);
|
||||
} else {
|
||||
printf("No options available.\n");
|
||||
}
|
||||
}
|
||||
for (i = 0; i < array->len; i++) {
|
||||
printf("%s\n", (char *)array->pdata[i]);
|
||||
}
|
||||
|
@ -930,7 +950,7 @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
|
|||
opts = opts_parse(list, params, permit_abbrev, false, &invalidp, &err);
|
||||
if (err) {
|
||||
if (invalidp && has_help_option(params)) {
|
||||
qemu_opts_print_help(list);
|
||||
qemu_opts_print_help(list, true);
|
||||
error_free(err);
|
||||
} else {
|
||||
error_report_err(err);
|
||||
|
|
15
vl.c
15
vl.c
|
@ -537,7 +537,7 @@ static QemuOptsList qemu_fw_cfg_opts = {
|
|||
}, {
|
||||
.name = "file",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Sets the name of the file from which\n"
|
||||
.help = "Sets the name of the file from which "
|
||||
"the fw_cfg blob will be loaded",
|
||||
}, {
|
||||
.name = "string",
|
||||
|
@ -2743,7 +2743,7 @@ static bool object_create_initial(const char *type, QemuOpts *opts)
|
|||
list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
|
||||
for (l = list; l != NULL; l = l->next) {
|
||||
ObjectClass *oc = OBJECT_CLASS(l->data);
|
||||
printf("%s\n", object_class_get_name(oc));
|
||||
printf(" %s\n", object_class_get_name(oc));
|
||||
}
|
||||
g_slist_free(list);
|
||||
exit(0);
|
||||
|
@ -2765,14 +2765,21 @@ static bool object_create_initial(const char *type, QemuOpts *opts)
|
|||
}
|
||||
|
||||
str = g_string_new(NULL);
|
||||
g_string_append_printf(str, "%s.%s=%s", type,
|
||||
prop->name, prop->type);
|
||||
g_string_append_printf(str, " %s=<%s>", prop->name, prop->type);
|
||||
if (prop->description) {
|
||||
if (str->len < 24) {
|
||||
g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
|
||||
}
|
||||
g_string_append_printf(str, " - %s", prop->description);
|
||||
}
|
||||
g_ptr_array_add(array, g_string_free(str, false));
|
||||
}
|
||||
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
|
||||
if (array->len > 0) {
|
||||
printf("%s options:\n", type);
|
||||
} else {
|
||||
printf("There are no options for %s.\n", type);
|
||||
}
|
||||
for (i = 0; i < array->len; i++) {
|
||||
printf("%s\n", (char *)array->pdata[i]);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue