ia64/xen-unstable

changeset 19269:7f573cb76db4

blktap: Allow creation of qcow2 files.

Signed-off-by: Yang Zhang <yang.zhang@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 03 13:22:28 2009 +0000 (2009-03-03)
parents 71af89e70fee
children 4b7d638a8b89
files tools/blktap/drivers/block-qcow2.c tools/blktap/drivers/qcow-create.c tools/blktap/drivers/tapdisk.h
line diff
     1.1 --- a/tools/blktap/drivers/block-qcow2.c	Tue Mar 03 13:17:05 2009 +0000
     1.2 +++ b/tools/blktap/drivers/block-qcow2.c	Tue Mar 03 13:22:28 2009 +0000
     1.3 @@ -1980,6 +1980,91 @@ static int qcow_validate_parent(struct d
     1.4  	return 0;
     1.5  }
     1.6  
     1.7 +int qcow2_create(const char *filename, uint64_t total_size,
     1.8 +                      const char *backing_file, int flags)
     1.9 +{
    1.10 +    int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
    1.11 +    QCowHeader header;
    1.12 +    uint64_t tmp, offset;
    1.13 +    QCowCreateState s1, *s = &s1;
    1.14 +
    1.15 +    memset(s, 0, sizeof(*s));
    1.16 +
    1.17 +    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
    1.18 +    if (fd < 0)
    1.19 +        return -1;
    1.20 +    memset(&header, 0, sizeof(header));
    1.21 +    header.magic = cpu_to_be32(QCOW_MAGIC);
    1.22 +    header.version = cpu_to_be32(QCOW_VERSION);
    1.23 +    header.size = cpu_to_be64(total_size * 512);
    1.24 +    header_size = sizeof(header);
    1.25 +    backing_filename_len = 0;
    1.26 +    if (backing_file) {
    1.27 +        header.backing_file_offset = cpu_to_be64(header_size);
    1.28 +        backing_filename_len = strlen(backing_file);
    1.29 +        header.backing_file_size = cpu_to_be32(backing_filename_len);
    1.30 +        header_size += backing_filename_len;
    1.31 +    }
    1.32 +    s->cluster_bits = 12;  /* 4 KB clusters */
    1.33 +    s->cluster_size = 1 << s->cluster_bits;
    1.34 +    header.cluster_bits = cpu_to_be32(s->cluster_bits);
    1.35 +    header_size = (header_size + 7) & ~7;
    1.36 +    if (flags & BLOCK_FLAG_ENCRYPT) {
    1.37 +        header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
    1.38 +    } else {
    1.39 +        header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
    1.40 +    }
    1.41 +    l2_bits = s->cluster_bits - 3;
    1.42 +    shift = s->cluster_bits + l2_bits;
    1.43 +    l1_size = (((total_size * 512) + (1LL << shift) - 1) >> shift);
    1.44 +    offset = align_offset(header_size, s->cluster_size);
    1.45 +    s->l1_table_offset = offset;
    1.46 +    header.l1_table_offset = cpu_to_be64(s->l1_table_offset);
    1.47 +    header.l1_size = cpu_to_be32(l1_size);
    1.48 +    offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
    1.49 +
    1.50 +    s->refcount_table = qemu_mallocz(s->cluster_size);
    1.51 +    s->refcount_block = qemu_mallocz(s->cluster_size);
    1.52 +
    1.53 +    s->refcount_table_offset = offset;
    1.54 +    header.refcount_table_offset = cpu_to_be64(offset);
    1.55 +    header.refcount_table_clusters = cpu_to_be32(1);
    1.56 +    offset += s->cluster_size;
    1.57 +
    1.58 +    s->refcount_table[0] = cpu_to_be64(offset);
    1.59 +    s->refcount_block_offset = offset;
    1.60 +    offset += s->cluster_size;
    1.61 +
    1.62 +    /* update refcounts */
    1.63 +    create_refcount_update(s, 0, header_size);
    1.64 +    create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t));
    1.65 +    create_refcount_update(s, s->refcount_table_offset, s->cluster_size);
    1.66 +    create_refcount_update(s, s->refcount_block_offset, s->cluster_size);
    1.67 +
    1.68 +    /* write all the data */
    1.69 +    write(fd, &header, sizeof(header));
    1.70 +    if (backing_file) {
    1.71 +        write(fd, backing_file, backing_filename_len);
    1.72 +    }
    1.73 +    lseek(fd, s->l1_table_offset, SEEK_SET);
    1.74 +    tmp = 0;
    1.75 +    for(i = 0;i < l1_size; i++) {
    1.76 +        write(fd, &tmp, sizeof(tmp));
    1.77 +    }
    1.78 +    lseek(fd, s->refcount_table_offset, SEEK_SET);
    1.79 +    write(fd, s->refcount_table, s->cluster_size);
    1.80 +
    1.81 +    lseek(fd, s->refcount_block_offset, SEEK_SET);
    1.82 +    write(fd, s->refcount_block, s->cluster_size);
    1.83 +
    1.84 +    qemu_free(s->refcount_table);
    1.85 +    qemu_free(s->refcount_block);
    1.86 +    close(fd);
    1.87 +    return 0;
    1.88 +}
    1.89 +
    1.90 +
    1.91 +
    1.92  struct tap_disk tapdisk_qcow2 = {
    1.93  	"qcow2",
    1.94  	sizeof(BDRVQcowState),
     2.1 --- a/tools/blktap/drivers/qcow-create.c	Tue Mar 03 13:17:05 2009 +0000
     2.2 +++ b/tools/blktap/drivers/qcow-create.c	Tue Mar 03 13:22:28 2009 +0000
     2.3 @@ -52,7 +52,7 @@ static void help(void)
     2.4  {
     2.5  	fprintf(stderr, "Qcow-utils: v1.0.0\n");
     2.6  	fprintf(stderr, 
     2.7 -		"usage: qcow-create [-h help] [-r reserve] <SIZE(MB)> <FILENAME> "
     2.8 +		"usage: qcow-create [-h help] [-r reserve] [-f format] <SIZE(MB)> <FILENAME> "
     2.9  		"[<BACKING_FILENAME>]\n"); 
    2.10  	exit(-1);
    2.11  }
    2.12 @@ -61,11 +61,13 @@ int main(int argc, char *argv[])
    2.13  {
    2.14  	int ret = -1, c, backed = 0;
    2.15  	int sparse =  1;
    2.16 +	char *fmt = "qcow";
    2.17  	uint64_t size;
    2.18  	char filename[MAX_NAME_LEN], bfilename[MAX_NAME_LEN];
    2.19 +	char *tmpfile;
    2.20  
    2.21          for(;;) {
    2.22 -                c = getopt(argc, argv, "hr");
    2.23 +                c = getopt(argc, argv, "hrf");
    2.24                  if (c == -1)
    2.25                          break;
    2.26                  switch(c) {
    2.27 @@ -73,6 +75,9 @@ int main(int argc, char *argv[])
    2.28                          help();
    2.29                          exit(0);
    2.30                          break;
    2.31 +                case 'f':
    2.32 +                        fmt = argv[optind++];
    2.33 +                        break;
    2.34                  case 'r':
    2.35  			sparse = 0;
    2.36  			break;
    2.37 @@ -105,11 +110,16 @@ int main(int argc, char *argv[])
    2.38  		}
    2.39  	}
    2.40  
    2.41 -	DFPRINTF("Creating file size %llu, name %s\n",(long long unsigned)size, filename);
    2.42 -	if (!backed)
    2.43 -		ret = qcow_create(filename,size,NULL,sparse);
    2.44 -	else
    2.45 -		ret = qcow_create(filename,size,bfilename,sparse);
    2.46 +    tmpfile = backed ? bfilename: NULL; 
    2.47 +    if (!strcmp(fmt, "qcow")) {
    2.48 +        ret = qcow_create(filename, size, tmpfile, sparse);
    2.49 +    } else if(!strcmp(fmt, "qcow2")) {
    2.50 +        ret = qcow2_create(filename, size, tmpfile, sparse);
    2.51 +    } else {
    2.52 +        fprintf(stderr,"Unsupport format:%s\n", fmt);
    2.53 +        exit(-1);
    2.54 +    } 
    2.55 +    DFPRINTF("Creating file size %llu, name %s\n",(long long unsigned)size, filename);
    2.56  
    2.57  	if (ret < 0)
    2.58  		DPRINTF("Unable to create QCOW file\n");
     3.1 --- a/tools/blktap/drivers/tapdisk.h	Tue Mar 03 13:17:05 2009 +0000
     3.2 +++ b/tools/blktap/drivers/tapdisk.h	Tue Mar 03 13:22:28 2009 +0000
     3.3 @@ -266,4 +266,7 @@ typedef struct fd_list_entry {
     3.4  
     3.5  int qcow_create(const char *filename, uint64_t total_size,
     3.6  		const char *backing_file, int flags);
     3.7 +
     3.8 +int qcow2_create(const char *filename, uint64_t total_size,
     3.9 +		const char *backing_file, int flags);
    3.10  #endif /*TAPDISK_H_*/