aboutsummaryrefslogtreecommitdiffstats
path: root/tools/blktap
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-03-03 13:22:28 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-03-03 13:22:28 +0000
commit86d2a1cec5b560f448dc1fbd0d9c775a0a89e0dd (patch)
tree828fba068bbf4c6e3b31904b86247eb849ec49d9 /tools/blktap
parentb47276c18fabaf6f0dbb855d3b1d2063b1c73e01 (diff)
downloadxen-86d2a1cec5b560f448dc1fbd0d9c775a0a89e0dd.tar.gz
xen-86d2a1cec5b560f448dc1fbd0d9c775a0a89e0dd.tar.bz2
xen-86d2a1cec5b560f448dc1fbd0d9c775a0a89e0dd.zip
blktap: Allow creation of qcow2 files.
Signed-off-by: Yang Zhang <yang.zhang@intel.com>
Diffstat (limited to 'tools/blktap')
-rw-r--r--tools/blktap/drivers/block-qcow2.c85
-rw-r--r--tools/blktap/drivers/qcow-create.c24
-rw-r--r--tools/blktap/drivers/tapdisk.h3
3 files changed, 105 insertions, 7 deletions
diff --git a/tools/blktap/drivers/block-qcow2.c b/tools/blktap/drivers/block-qcow2.c
index 8bdd33ea37..744022697c 100644
--- a/tools/blktap/drivers/block-qcow2.c
+++ b/tools/blktap/drivers/block-qcow2.c
@@ -1980,6 +1980,91 @@ static int qcow_validate_parent(struct disk_driver *child,
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 --git a/tools/blktap/drivers/qcow-create.c b/tools/blktap/drivers/qcow-create.c
index 5ff50648a8..25abfcd1d4 100644
--- a/tools/blktap/drivers/qcow-create.c
+++ b/tools/blktap/drivers/qcow-create.c
@@ -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,11 +61,13 @@ 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) {
@@ -73,6 +75,9 @@ int main(int argc, char *argv[])
help();
exit(0);
break;
+ case 'f':
+ fmt = argv[optind++];
+ break;
case 'r':
sparse = 0;
break;
@@ -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 --git a/tools/blktap/drivers/tapdisk.h b/tools/blktap/drivers/tapdisk.h
index c8a21827ff..22450ff03b 100644
--- a/tools/blktap/drivers/tapdisk.h
+++ b/tools/blktap/drivers/tapdisk.h
@@ -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_*/