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:
Peter Maydell 2018-11-05 18:03:32 +00:00
commit 3cb99f4124
42 changed files with 1267 additions and 777 deletions

62
block.c
View File

@ -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");

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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) */

View File

@ -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)

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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");
}

View File

@ -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;

View File

@ -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)

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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',

View File

@ -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");
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

147
tests/qemu-iotests/232 Executable file
View File

@ -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

View File

@ -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

View File

@ -227,3 +227,4 @@
227 auto quick
229 auto quick
231 auto quick
232 auto quick

View File

@ -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
View File

@ -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]);
}