aboutsummaryrefslogtreecommitdiff
path: root/qemu-img.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu-img.c')
-rw-r--r--qemu-img.c80
1 files changed, 67 insertions, 13 deletions
diff --git a/qemu-img.c b/qemu-img.c
index 32628b3..54137a4 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -40,6 +40,7 @@ typedef struct img_cmd_t {
/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
#define BDRV_O_FLAGS BDRV_O_CACHE_WB
+#define BDRV_DEFAULT_CACHE "writeback"
static void format_print(void *opaque, const char *name)
{
@@ -64,6 +65,8 @@ static void help(void)
"Command parameters:\n"
" 'filename' is a disk image filename\n"
" 'fmt' is the disk image format. It is guessed automatically in most cases\n"
+ " 'cache' is the cache mode used to write the output disk image, the valid\n"
+ " options are: 'none', 'writeback' (default), 'writethrough' and 'unsafe'\n"
" 'size' is the disk image size in bytes. Optional suffixes\n"
" 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
" and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
@@ -180,6 +183,27 @@ static int read_password(char *buf, int buf_size)
}
#endif
+static int set_cache_flag(const char *mode, int *flags)
+{
+ *flags &= ~BDRV_O_CACHE_MASK;
+
+ if (!strcmp(mode, "none") || !strcmp(mode, "off")) {
+ *flags |= BDRV_O_CACHE_WB;
+ *flags |= BDRV_O_NOCACHE;
+ } else if (!strcmp(mode, "writeback")) {
+ *flags |= BDRV_O_CACHE_WB;
+ } else if (!strcmp(mode, "unsafe")) {
+ *flags |= BDRV_O_CACHE_WB;
+ *flags |= BDRV_O_NO_FLUSH;
+ } else if (!strcmp(mode, "writethrough")) {
+ /* this is the default */
+ } else {
+ return -1;
+ }
+
+ return 0;
+}
+
static int print_block_option_help(const char *filename, const char *fmt)
{
BlockDriver *drv, *proto_drv;
@@ -441,13 +465,14 @@ static int img_check(int argc, char **argv)
static int img_commit(int argc, char **argv)
{
- int c, ret;
- const char *filename, *fmt;
+ int c, ret, flags;
+ const char *filename, *fmt, *cache;
BlockDriverState *bs;
fmt = NULL;
+ cache = BDRV_DEFAULT_CACHE;
for(;;) {
- c = getopt(argc, argv, "f:h");
+ c = getopt(argc, argv, "f:ht:");
if (c == -1) {
break;
}
@@ -459,6 +484,9 @@ static int img_commit(int argc, char **argv)
case 'f':
fmt = optarg;
break;
+ case 't':
+ cache = optarg;
+ break;
}
}
if (optind >= argc) {
@@ -466,7 +494,14 @@ static int img_commit(int argc, char **argv)
}
filename = argv[optind++];
- bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
+ flags = BDRV_O_RDWR;
+ ret = set_cache_flag(cache, &flags);
+ if (ret < 0) {
+ error_report("Invalid cache option: %s", cache);
+ return -1;
+ }
+
+ bs = bdrv_new_open(filename, fmt, flags);
if (!bs) {
return 1;
}
@@ -591,8 +626,8 @@ static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
static int img_convert(int argc, char **argv)
{
int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
- int progress = 0;
- const char *fmt, *out_fmt, *out_baseimg, *out_filename;
+ int progress = 0, flags;
+ const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
BlockDriver *drv, *proto_drv;
BlockDriverState **bs = NULL, *out_bs = NULL;
int64_t total_sectors, nb_sectors, sector_num, bs_offset;
@@ -608,10 +643,11 @@ static int img_convert(int argc, char **argv)
fmt = NULL;
out_fmt = "raw";
+ cache = "unsafe";
out_baseimg = NULL;
compress = 0;
for(;;) {
- c = getopt(argc, argv, "f:O:B:s:hce6o:p");
+ c = getopt(argc, argv, "f:O:B:s:hce6o:pt:");
if (c == -1) {
break;
}
@@ -649,6 +685,9 @@ static int img_convert(int argc, char **argv)
case 'p':
progress = 1;
break;
+ case 't':
+ cache = optarg;
+ break;
}
}
@@ -779,8 +818,14 @@ static int img_convert(int argc, char **argv)
goto out;
}
- out_bs = bdrv_new_open(out_filename, out_fmt,
- BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH);
+ flags = BDRV_O_RDWR;
+ ret = set_cache_flag(cache, &flags);
+ if (ret < 0) {
+ error_report("Invalid cache option: %s", cache);
+ return -1;
+ }
+
+ out_bs = bdrv_new_open(out_filename, out_fmt, flags);
if (!out_bs) {
ret = -1;
goto out;
@@ -1225,18 +1270,18 @@ static int img_rebase(int argc, char **argv)
BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
BlockDriver *old_backing_drv, *new_backing_drv;
char *filename;
- const char *fmt, *out_basefmt, *out_baseimg;
+ const char *fmt, *cache, *out_basefmt, *out_baseimg;
int c, flags, ret;
int unsafe = 0;
int progress = 0;
/* Parse commandline parameters */
fmt = NULL;
+ cache = BDRV_DEFAULT_CACHE;
out_baseimg = NULL;
out_basefmt = NULL;
-
for(;;) {
- c = getopt(argc, argv, "uhf:F:b:p");
+ c = getopt(argc, argv, "uhf:F:b:pt:");
if (c == -1) {
break;
}
@@ -1260,6 +1305,9 @@ static int img_rebase(int argc, char **argv)
case 'p':
progress = 1;
break;
+ case 't':
+ cache = optarg;
+ break;
}
}
@@ -1271,13 +1319,19 @@ static int img_rebase(int argc, char **argv)
qemu_progress_init(progress, 2.0);
qemu_progress_print(0, 100);
+ flags = BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
+ ret = set_cache_flag(cache, &flags);
+ if (ret < 0) {
+ error_report("Invalid cache option: %s", cache);
+ return -1;
+ }
+
/*
* Open the images.
*
* Ignore the old backing file for unsafe rebase in case we want to correct
* the reference to a renamed or moved backing file.
*/
- flags = BDRV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
bs = bdrv_new_open(filename, fmt, flags);
if (!bs) {
return 1;