提交 a22f123c 编写于 作者: K Kevin Wolf

qemu-img: Require larger zero areas for sparse handling

By default, require 4k of consecutive zero bytes for qemu-img to make the
output file sparse by not issuing a write request for the zeroed parts. Add an
-S option to allow users to tune this setting.

This helps to avoid situations where a lot of zero sectors and data sectors are
mixed and qemu-img tended to issue many tiny 512 byte writes.
Signed-off-by: NKevin Wolf <kwolf@redhat.com>
上级 c488c7f6
...@@ -28,9 +28,9 @@ STEXI ...@@ -28,9 +28,9 @@ STEXI
ETEXI ETEXI
DEF("convert", img_convert, DEF("convert", img_convert,
"convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] filename [filename2 [...]] output_filename") "convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename")
STEXI STEXI
@item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename} @item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
ETEXI ETEXI
DEF("info", img_info, DEF("info", img_info,
......
...@@ -82,6 +82,8 @@ static void help(void) ...@@ -82,6 +82,8 @@ static void help(void)
" rebasing in this case (useful for renaming the backing file)\n" " rebasing in this case (useful for renaming the backing file)\n"
" '-h' with or without a command shows this help and lists the supported formats\n" " '-h' with or without a command shows this help and lists the supported formats\n"
" '-p' show progress of command (only certain commands)\n" " '-p' show progress of command (only certain commands)\n"
" '-S' indicates the consecutive number of bytes that must contain only zeros\n"
" for qemu-img to create a sparse image during conversion\n"
"\n" "\n"
"Parameters to snapshot subcommand:\n" "Parameters to snapshot subcommand:\n"
" 'snapshot' is the name of the snapshot to create, apply or delete\n" " 'snapshot' is the name of the snapshot to create, apply or delete\n"
...@@ -570,6 +572,48 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum) ...@@ -570,6 +572,48 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
return v; return v;
} }
/*
* Like is_allocated_sectors, but if the buffer starts with a used sector,
* up to 'min' consecutive sectors containing zeros are ignored. This avoids
* breaking up write requests for only small sparse areas.
*/
static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum,
int min)
{
int ret;
int num_checked, num_used;
if (n < min) {
min = n;
}
ret = is_allocated_sectors(buf, n, pnum);
if (!ret) {
return ret;
}
num_used = *pnum;
buf += BDRV_SECTOR_SIZE * *pnum;
n -= *pnum;
num_checked = num_used;
while (n > 0) {
ret = is_allocated_sectors(buf, n, pnum);
buf += BDRV_SECTOR_SIZE * *pnum;
n -= *pnum;
num_checked += *pnum;
if (ret) {
num_used = num_checked;
} else if (*pnum >= min) {
break;
}
}
*pnum = num_used;
return 1;
}
/* /*
* Compares two buffers sector by sector. Returns 0 if the first sector of both * Compares two buffers sector by sector. Returns 0 if the first sector of both
* buffers matches, non-zero otherwise. * buffers matches, non-zero otherwise.
...@@ -620,6 +664,7 @@ static int img_convert(int argc, char **argv) ...@@ -620,6 +664,7 @@ static int img_convert(int argc, char **argv)
char *options = NULL; char *options = NULL;
const char *snapshot_name = NULL; const char *snapshot_name = NULL;
float local_progress; float local_progress;
int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
fmt = NULL; fmt = NULL;
out_fmt = "raw"; out_fmt = "raw";
...@@ -627,7 +672,7 @@ static int img_convert(int argc, char **argv) ...@@ -627,7 +672,7 @@ static int img_convert(int argc, char **argv)
out_baseimg = NULL; out_baseimg = NULL;
compress = 0; compress = 0;
for(;;) { for(;;) {
c = getopt(argc, argv, "f:O:B:s:hce6o:pt:"); c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:");
if (c == -1) { if (c == -1) {
break; break;
} }
...@@ -662,6 +707,18 @@ static int img_convert(int argc, char **argv) ...@@ -662,6 +707,18 @@ static int img_convert(int argc, char **argv)
case 's': case 's':
snapshot_name = optarg; snapshot_name = optarg;
break; break;
case 'S':
{
int64_t sval;
sval = strtosz_suffix(optarg, NULL, STRTOSZ_DEFSUFFIX_B);
if (sval < 0) {
error_report("Invalid minimum zero buffer size for sparse output specified");
return 1;
}
min_sparse = sval / BDRV_SECTOR_SIZE;
break;
}
case 'p': case 'p':
progress = 1; progress = 1;
break; break;
...@@ -970,7 +1027,7 @@ static int img_convert(int argc, char **argv) ...@@ -970,7 +1027,7 @@ static int img_convert(int argc, char **argv)
sectors that are entirely 0, since whatever data was sectors that are entirely 0, since whatever data was
already there is garbage, not 0s. */ already there is garbage, not 0s. */
if (!has_zero_init || out_baseimg || if (!has_zero_init || out_baseimg ||
is_allocated_sectors(buf1, n, &n1)) { is_allocated_sectors_min(buf1, n, &n1, min_sparse)) {
ret = bdrv_write(out_bs, sector_num, buf1, n1); ret = bdrv_write(out_bs, sector_num, buf1, n1);
if (ret < 0) { if (ret < 0) {
error_report("error while writing sector %" PRId64 error_report("error while writing sector %" PRId64
......
...@@ -40,6 +40,11 @@ indicates that target image must be compressed (qcow format only) ...@@ -40,6 +40,11 @@ indicates that target image must be compressed (qcow format only)
with or without a command shows help and lists the supported formats with or without a command shows help and lists the supported formats
@item -p @item -p
display progress bar (convert and rebase commands only) display progress bar (convert and rebase commands only)
@item -S @var{size}
indicates the consecutive number of bytes that must contain only zeros
for qemu-img to create a sparse image during conversion. This value is rounded
down to the nearest 512 bytes. You may use the common size suffixes like
@code{k} for kilobytes.
@end table @end table
Parameters to snapshot subcommand: Parameters to snapshot subcommand:
...@@ -86,7 +91,7 @@ it doesn't need to be specified separately in this case. ...@@ -86,7 +91,7 @@ it doesn't need to be specified separately in this case.
Commit the changes recorded in @var{filename} in its base image. Commit the changes recorded in @var{filename} in its base image.
@item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename} @item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename} Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename}
using format @var{output_fmt}. It can be optionally compressed (@code{-c} using format @var{output_fmt}. It can be optionally compressed (@code{-c}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册