Skip to content

Commit

Permalink
qemu-img: add --shrink flag for resize
Browse files Browse the repository at this point in the history
The flag is additional precaution against data loss. Perhaps in the future the
operation shrink without this flag will be blocked for all formats, but for now
we need to maintain compatibility with raw.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 20170918124230.8152-2-pbutsykin@virtuozzo.com
[mreitz: Added a missing space to a warning]
Signed-off-by: Max Reitz <mreitz@redhat.com>
  • Loading branch information
pbutsykin authored and XanClic committed Sep 26, 2017
1 parent 69ff158 commit 4ffca89
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 6 deletions.
4 changes: 2 additions & 2 deletions qemu-img-cmds.hx
Expand Up @@ -89,9 +89,9 @@ STEXI
ETEXI

DEF("resize", img_resize,
"resize [--object objectdef] [--image-opts] [-q] filename [+ | -]size")
"resize [--object objectdef] [--image-opts] [-q] [--shrink] filename [+ | -]size")
STEXI
@item resize [--object @var{objectdef}] [--image-opts] [-q] @var{filename} [+ | -]@var{size}
@item resize [--object @var{objectdef}] [--image-opts] [-q] [--shrink] @var{filename} [+ | -]@var{size}
ETEXI

STEXI
Expand Down
23 changes: 23 additions & 0 deletions qemu-img.c
Expand Up @@ -64,6 +64,7 @@ enum {
OPTION_TARGET_IMAGE_OPTS = 263,
OPTION_SIZE = 264,
OPTION_PREALLOCATION = 265,
OPTION_SHRINK = 266,
};

typedef enum OutputFormat {
Expand Down Expand Up @@ -3436,6 +3437,7 @@ static int img_resize(int argc, char **argv)
},
};
bool image_opts = false;
bool shrink = false;

/* Remove size from argv manually so that negative numbers are not treated
* as options by getopt. */
Expand All @@ -3454,6 +3456,7 @@ static int img_resize(int argc, char **argv)
{"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{"preallocation", required_argument, 0, OPTION_PREALLOCATION},
{"shrink", no_argument, 0, OPTION_SHRINK},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, ":f:hq",
Expand Down Expand Up @@ -3496,6 +3499,9 @@ static int img_resize(int argc, char **argv)
return 1;
}
break;
case OPTION_SHRINK:
shrink = true;
break;
}
}
if (optind != argc - 1) {
Expand Down Expand Up @@ -3569,6 +3575,23 @@ static int img_resize(int argc, char **argv)
goto out;
}

if (total_size < current_size && !shrink) {
warn_report("Shrinking an image will delete all data beyond the "
"shrunken image's end. Before performing such an "
"operation, make sure there is no important data there.");

if (g_strcmp0(bdrv_get_format_name(blk_bs(blk)), "raw") != 0) {
error_report(
"Use the --shrink option to perform a shrink operation.");
ret = -1;
goto out;
} else {
warn_report("Using the --shrink option will suppress this message. "
"Note that future versions of qemu-img may refuse to "
"shrink images without this option.");
}
}

ret = blk_truncate(blk, total_size, prealloc, &err);
if (!ret) {
qprintf(quiet, "Image resized.\n");
Expand Down
6 changes: 5 additions & 1 deletion qemu-img.texi
Expand Up @@ -545,14 +545,18 @@ qemu-img rebase -b base.img diff.qcow2
At this point, @code{modified.img} can be discarded, since
@code{base.img + diff.qcow2} contains the same information.

@item resize [--preallocation=@var{prealloc}] @var{filename} [+ | -]@var{size}
@item resize [--shrink] [--preallocation=@var{prealloc}] @var{filename} [+ | -]@var{size}

Change the disk image as if it had been created with @var{size}.

Before using this command to shrink a disk image, you MUST use file system and
partitioning tools inside the VM to reduce allocated file systems and partition
sizes accordingly. Failure to do so will result in data loss!

When shrinking images, the @code{--shrink} option must be given. This informs
qemu-img that the user acknowledges all loss of data beyond the truncated
image's end.

After using this command to grow a disk image, you must use file system and
partitioning tools inside the VM to actually begin using the new space on the
device.
Expand Down
4 changes: 2 additions & 2 deletions tests/qemu-iotests/102
Expand Up @@ -54,7 +54,7 @@ _make_test_img $IMG_SIZE
$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
# Remove data cluster from image (first cluster: image header, second: reftable,
# third: refblock, fourth: L1 table, fifth: L2 table)
$QEMU_IMG resize -f raw "$TEST_IMG" $((5 * 64 * 1024))
$QEMU_IMG resize -f raw --shrink "$TEST_IMG" $((5 * 64 * 1024))

$QEMU_IO -c map "$TEST_IMG"
$QEMU_IMG map "$TEST_IMG"
Expand All @@ -69,7 +69,7 @@ $QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io

qemu_comm_method=monitor _launch_qemu -drive if=none,file="$TEST_IMG",id=drv0

$QEMU_IMG resize -f raw "$TEST_IMG" $((5 * 64 * 1024))
$QEMU_IMG resize -f raw --shrink "$TEST_IMG" $((5 * 64 * 1024))

_send_qemu_cmd $QEMU_HANDLE 'qemu-io drv0 map' 'allocated' \
| sed -e 's/^(qemu).*qemu-io drv0 map...$/(qemu) qemu-io drv0 map/'
Expand Down
2 changes: 1 addition & 1 deletion tests/qemu-iotests/106
Expand Up @@ -83,7 +83,7 @@ echo '=== Testing image shrinking ==='
for growth_mode in falloc full off; do
echo
echo "--- growth_mode=$growth_mode ---"
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" -${GROWTH_SIZE}K
$QEMU_IMG resize -f "$IMGFMT" --shrink --preallocation=$growth_mode "$TEST_IMG" -${GROWTH_SIZE}K
done

# success, all done
Expand Down

0 comments on commit 4ffca89

Please sign in to comment.