qemu-img info: Add cache mode option

When querying block limits, different cache modes (in particular
O_DIRECT or not) can result in different limits. Add an option to
'qemu-img info' that allows the user to specify a cache mode, so that
they can get the block limits for the cache mode they intend to use with
their VM.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-ID: <20251024123041.51254-5-kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Kevin Wolf
2025-10-24 14:30:40 +02:00
parent 5b4b3bfdfc
commit 911992fd6e
3 changed files with 24 additions and 7 deletions

View File

@@ -503,7 +503,7 @@ Command description:
The size syntax is similar to :manpage:`dd(1)`'s size syntax. The size syntax is similar to :manpage:`dd(1)`'s size syntax.
.. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [--limits] [-U] FILENAME .. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [--limits] [-t CACHE] [-U] FILENAME
Give information about the disk image *FILENAME*. Use it in Give information about the disk image *FILENAME*. Use it in
particular to know the size reserved on disk which can be different particular to know the size reserved on disk which can be different

View File

@@ -66,9 +66,9 @@ SRST
ERST ERST
DEF("info", img_info, DEF("info", img_info,
"info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] [--limits] [-U] filename") "info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] [--limits] [-t CACHE] [-U] filename")
SRST SRST
.. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [--limits] [-U] FILENAME .. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [--limits] [-t CACHE] [-U] FILENAME
ERST ERST
DEF("map", img_map, DEF("map", img_map,

View File

@@ -3003,6 +3003,7 @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
static BlockGraphInfoList *collect_image_info_list(bool image_opts, static BlockGraphInfoList *collect_image_info_list(bool image_opts,
const char *filename, const char *filename,
const char *fmt, const char *fmt,
const char *cache,
bool chain, bool limits, bool chain, bool limits,
bool force_share) bool force_share)
{ {
@@ -3010,6 +3011,15 @@ static BlockGraphInfoList *collect_image_info_list(bool image_opts,
BlockGraphInfoList **tail = &head; BlockGraphInfoList **tail = &head;
GHashTable *filenames; GHashTable *filenames;
Error *err = NULL; Error *err = NULL;
int cache_flags = 0;
bool writethrough = false;
int ret;
ret = bdrv_parse_cache_mode(cache, &cache_flags, &writethrough);
if (ret < 0) {
error_report("Invalid cache option: %s", cache);
return NULL;
}
filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL); filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
@@ -3026,8 +3036,8 @@ static BlockGraphInfoList *collect_image_info_list(bool image_opts,
g_hash_table_insert(filenames, (gpointer)filename, NULL); g_hash_table_insert(filenames, (gpointer)filename, NULL);
blk = img_open(image_opts, filename, fmt, blk = img_open(image_opts, filename, fmt,
BDRV_O_NO_BACKING | BDRV_O_NO_IO, false, false, BDRV_O_NO_BACKING | BDRV_O_NO_IO | cache_flags,
force_share); writethrough, false, force_share);
if (!blk) { if (!blk) {
goto err; goto err;
} }
@@ -3087,6 +3097,7 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
OutputFormat output_format = OFORMAT_HUMAN; OutputFormat output_format = OFORMAT_HUMAN;
bool chain = false; bool chain = false;
const char *filename, *fmt; const char *filename, *fmt;
const char *cache = BDRV_DEFAULT_CACHE;
BlockGraphInfoList *list; BlockGraphInfoList *list;
bool image_opts = false; bool image_opts = false;
bool force_share = false; bool force_share = false;
@@ -3099,13 +3110,14 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
{"format", required_argument, 0, 'f'}, {"format", required_argument, 0, 'f'},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN}, {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
{"cache", required_argument, 0, 't'},
{"force-share", no_argument, 0, 'U'}, {"force-share", no_argument, 0, 'U'},
{"limits", no_argument, 0, OPTION_LIMITS}, {"limits", no_argument, 0, OPTION_LIMITS},
{"output", required_argument, 0, OPTION_OUTPUT}, {"output", required_argument, 0, OPTION_OUTPUT},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "hf:U", long_options, NULL); c = getopt_long(argc, argv, "hf:t:U", long_options, NULL);
if (c == -1) { if (c == -1) {
break; break;
} }
@@ -3121,6 +3133,8 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
" (incompatible with -f|--format)\n" " (incompatible with -f|--format)\n"
" --backing-chain\n" " --backing-chain\n"
" display information about the backing chain for copy-on-write overlays\n" " display information about the backing chain for copy-on-write overlays\n"
" -t, --cache CACHE\n"
" cache mode for FILE (default: " BDRV_DEFAULT_CACHE ")\n"
" -U, --force-share\n" " -U, --force-share\n"
" open image in shared mode for concurrent access\n" " open image in shared mode for concurrent access\n"
" --limits\n" " --limits\n"
@@ -3143,6 +3157,9 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
case OPTION_BACKING_CHAIN: case OPTION_BACKING_CHAIN:
chain = true; chain = true;
break; break;
case 't':
cache = optarg;
break;
case 'U': case 'U':
force_share = true; force_share = true;
break; break;
@@ -3164,7 +3181,7 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
} }
filename = argv[optind++]; filename = argv[optind++];
list = collect_image_info_list(image_opts, filename, fmt, chain, list = collect_image_info_list(image_opts, filename, fmt, cache, chain,
limits, force_share); limits, force_share);
if (!list) { if (!list) {
return 1; return 1;