This introduces qemu-img create option for sheepdog which allows the data to be preallocated (note that sheepdog always preallocates metadata). The option is disabled by default and you need to enable it like the following: qemu-img create sheepdog:test -o preallocation=data 1G Signed-off-by: FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp> --- block/sheepdog.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 74 insertions(+), 3 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index e62820a..3d2d322 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1291,12 +1291,64 @@ static int do_sd_create(char *filename, int64_t vdi_size, return 0; } +static int sd_prealloc(uint32_t vid, int64_t vdi_size) +{ + int fd, ret; + SheepdogInode *inode; + char *buf; + unsigned long idx, max_idx; + + fd = connect_to_sdog(NULL, NULL); + if (fd < 0) { + return -EIO; + } + + inode = qemu_malloc(sizeof(*inode)); + buf = qemu_malloc(SD_DATA_OBJ_SIZE); + + ret = read_object(fd, (char *)inode, vid_to_vdi_oid(vid), + 0, sizeof(*inode), 0); + + max_idx = (vdi_size + SD_DATA_OBJ_SIZE - 1) / SD_DATA_OBJ_SIZE; + + for (idx = 0; idx < max_idx; idx++) { + uint64_t oid; + oid = vid_to_data_oid(vid, idx); + + if (inode->data_vdi_id[idx]) { + ret = read_object(fd, buf, vid_to_vdi_oid(inode->data_vdi_id[idx]), + 1, SD_DATA_OBJ_SIZE, 0); + if (ret) + goto out; + } else { + memset(buf, 0, SD_DATA_OBJ_SIZE); + } + + ret = write_object(fd, buf, oid, 1, SD_DATA_OBJ_SIZE, 0, 1); + if (ret) + goto out; + + inode->data_vdi_id[idx] = vid; + ret = write_object(fd, (char *)inode, vid_to_vdi_oid(vid), + 1, sizeof(*inode), 0, 0); + if (ret) + goto out; + } +out: + free(inode); + free(buf); + closesocket(fd); + + return ret; +} + static int sd_create(const char *filename, QEMUOptionParameter *options) { int ret; - uint32_t vid = 0; + uint32_t vid = 0, base_vid = 0; int64_t vdi_size = 0; char *backing_file = NULL; + int prealloc = 0; strstart(filename, "sheepdog:", (const char **)&filename); @@ -1305,6 +1357,16 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) vdi_size = options->value.n; } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { backing_file = options->value.s; + } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) { + if (!options->value.s || !strcmp(options->value.s, "off")) { + prealloc = 0; + } else if (!strcmp(options->value.s, "data")) { + prealloc = 1; + } else { + error_report("Invalid preallocation mode: '%s'\n", + options->value.s); + return -EINVAL; + } } options++; } @@ -1338,11 +1400,15 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) return -EINVAL; } - vid = s->inode.vdi_id; + base_vid = s->inode.vdi_id; bdrv_delete(bs); } - return do_sd_create((char *)filename, vdi_size, vid, NULL, 0, NULL, NULL); + ret = do_sd_create((char *)filename, vdi_size, base_vid, &vid, 0, NULL, NULL); + if (!prealloc || ret) + return ret; + + return sd_prealloc(vid, vdi_size); } static void sd_close(BlockDriverState *bs) @@ -1992,6 +2058,11 @@ static QEMUOptionParameter sd_create_options[] = { .type = OPT_STRING, .help = "File name of a base image" }, + { + .name = BLOCK_OPT_PREALLOC, + .type = OPT_STRING, + .help = "Preallocation mode (allowed values: off, data)" + }, { NULL } }; -- 1.7.1 |