[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] blktap: Allow creation of qcow2 files.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1236086548 0 # Node ID 7f573cb76db41a9fc46052867b02e9e0c107aa86 # Parent 71af89e70fee39954496130e92807c42d1405489 blktap: Allow creation of qcow2 files. Signed-off-by: Yang Zhang <yang.zhang@xxxxxxxxx> --- tools/blktap/drivers/block-qcow2.c | 85 +++++++++++++++++++++++++++++++++++++ tools/blktap/drivers/qcow-create.c | 24 +++++++--- tools/blktap/drivers/tapdisk.h | 3 + 3 files changed, 105 insertions(+), 7 deletions(-) diff -r 71af89e70fee -r 7f573cb76db4 tools/blktap/drivers/block-qcow2.c --- a/tools/blktap/drivers/block-qcow2.c Tue Mar 03 13:17:05 2009 +0000 +++ b/tools/blktap/drivers/block-qcow2.c Tue Mar 03 13:22:28 2009 +0000 @@ -1980,6 +1980,91 @@ static int qcow_validate_parent(struct d return 0; } +int qcow2_create(const char *filename, uint64_t total_size, + const char *backing_file, int flags) +{ + int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits; + QCowHeader header; + uint64_t tmp, offset; + QCowCreateState s1, *s = &s1; + + memset(s, 0, sizeof(*s)); + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); + if (fd < 0) + return -1; + memset(&header, 0, sizeof(header)); + header.magic = cpu_to_be32(QCOW_MAGIC); + header.version = cpu_to_be32(QCOW_VERSION); + header.size = cpu_to_be64(total_size * 512); + header_size = sizeof(header); + backing_filename_len = 0; + if (backing_file) { + header.backing_file_offset = cpu_to_be64(header_size); + backing_filename_len = strlen(backing_file); + header.backing_file_size = cpu_to_be32(backing_filename_len); + header_size += backing_filename_len; + } + s->cluster_bits = 12; /* 4 KB clusters */ + s->cluster_size = 1 << s->cluster_bits; + header.cluster_bits = cpu_to_be32(s->cluster_bits); + header_size = (header_size + 7) & ~7; + if (flags & BLOCK_FLAG_ENCRYPT) { + header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES); + } else { + header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); + } + l2_bits = s->cluster_bits - 3; + shift = s->cluster_bits + l2_bits; + l1_size = (((total_size * 512) + (1LL << shift) - 1) >> shift); + offset = align_offset(header_size, s->cluster_size); + s->l1_table_offset = offset; + header.l1_table_offset = cpu_to_be64(s->l1_table_offset); + header.l1_size = cpu_to_be32(l1_size); + offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size); + + s->refcount_table = qemu_mallocz(s->cluster_size); + s->refcount_block = qemu_mallocz(s->cluster_size); + + s->refcount_table_offset = offset; + header.refcount_table_offset = cpu_to_be64(offset); + header.refcount_table_clusters = cpu_to_be32(1); + offset += s->cluster_size; + + s->refcount_table[0] = cpu_to_be64(offset); + s->refcount_block_offset = offset; + offset += s->cluster_size; + + /* update refcounts */ + create_refcount_update(s, 0, header_size); + create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t)); + create_refcount_update(s, s->refcount_table_offset, s->cluster_size); + create_refcount_update(s, s->refcount_block_offset, s->cluster_size); + + /* write all the data */ + write(fd, &header, sizeof(header)); + if (backing_file) { + write(fd, backing_file, backing_filename_len); + } + lseek(fd, s->l1_table_offset, SEEK_SET); + tmp = 0; + for(i = 0;i < l1_size; i++) { + write(fd, &tmp, sizeof(tmp)); + } + lseek(fd, s->refcount_table_offset, SEEK_SET); + write(fd, s->refcount_table, s->cluster_size); + + lseek(fd, s->refcount_block_offset, SEEK_SET); + write(fd, s->refcount_block, s->cluster_size); + + qemu_free(s->refcount_table); + qemu_free(s->refcount_block); + close(fd); + return 0; +} + + + struct tap_disk tapdisk_qcow2 = { "qcow2", sizeof(BDRVQcowState), diff -r 71af89e70fee -r 7f573cb76db4 tools/blktap/drivers/qcow-create.c --- a/tools/blktap/drivers/qcow-create.c Tue Mar 03 13:17:05 2009 +0000 +++ b/tools/blktap/drivers/qcow-create.c Tue Mar 03 13:22:28 2009 +0000 @@ -52,7 +52,7 @@ static void help(void) { fprintf(stderr, "Qcow-utils: v1.0.0\n"); fprintf(stderr, - "usage: qcow-create [-h help] [-r reserve] <SIZE(MB)> <FILENAME> " + "usage: qcow-create [-h help] [-r reserve] [-f format] <SIZE(MB)> <FILENAME> " "[<BACKING_FILENAME>]\n"); exit(-1); } @@ -61,17 +61,22 @@ int main(int argc, char *argv[]) { int ret = -1, c, backed = 0; int sparse = 1; + char *fmt = "qcow"; uint64_t size; char filename[MAX_NAME_LEN], bfilename[MAX_NAME_LEN]; + char *tmpfile; for(;;) { - c = getopt(argc, argv, "hr"); + c = getopt(argc, argv, "hrf"); if (c == -1) break; switch(c) { case 'h': help(); exit(0); + break; + case 'f': + fmt = argv[optind++]; break; case 'r': sparse = 0; @@ -105,11 +110,16 @@ int main(int argc, char *argv[]) } } - DFPRINTF("Creating file size %llu, name %s\n",(long long unsigned)size, filename); - if (!backed) - ret = qcow_create(filename,size,NULL,sparse); - else - ret = qcow_create(filename,size,bfilename,sparse); + tmpfile = backed ? bfilename: NULL; + if (!strcmp(fmt, "qcow")) { + ret = qcow_create(filename, size, tmpfile, sparse); + } else if(!strcmp(fmt, "qcow2")) { + ret = qcow2_create(filename, size, tmpfile, sparse); + } else { + fprintf(stderr,"Unsupport format:%s\n", fmt); + exit(-1); + } + DFPRINTF("Creating file size %llu, name %s\n",(long long unsigned)size, filename); if (ret < 0) DPRINTF("Unable to create QCOW file\n"); diff -r 71af89e70fee -r 7f573cb76db4 tools/blktap/drivers/tapdisk.h --- a/tools/blktap/drivers/tapdisk.h Tue Mar 03 13:17:05 2009 +0000 +++ b/tools/blktap/drivers/tapdisk.h Tue Mar 03 13:22:28 2009 +0000 @@ -266,4 +266,7 @@ typedef struct fd_list_entry { int qcow_create(const char *filename, uint64_t total_size, const char *backing_file, int flags); + +int qcow2_create(const char *filename, uint64_t total_size, + const char *backing_file, int flags); #endif /*TAPDISK_H_*/ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |