From 71e04ed52548f7d5061be5835fcf0f40bde90d57 Mon Sep 17 00:00:00 2001 From: Robert Wang Date: Tue, 9 Aug 2011 13:18:57 +0800 Subject: [PATCH] something wrong. --- Makefile.objs | 1 + block/add-cow.c | 43 ++++++++++++------------------------------- block/add-cow.h | 2 -- block/raw-posix.c | 49 ++++++++++++++++++++++++++++++++++++------------- block/raw.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- block_int.h | 2 ++ 6 files changed, 94 insertions(+), 48 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 432b6198e9..0efa13b47c 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -34,6 +34,7 @@ block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow block-nested-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-nested-y += qed-check.o block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o +block-nested-y += add-cow.o block-nested-$(CONFIG_WIN32) += raw-win32.o block-nested-$(CONFIG_POSIX) += raw-posix.o block-nested-$(CONFIG_CURL) += curl.o diff --git a/block/add-cow.c b/block/add-cow.c index d6c69fefc5..c20f94a87e 100644 --- a/block/add-cow.c +++ b/block/add-cow.c @@ -2,7 +2,6 @@ #include #include #include -#include #include "block/add-cow.h" #include "qemu-common.h" @@ -33,10 +32,7 @@ int create_cow_file(const char *backing_file,const char *backing_format, const c if(!cow_file || !backing_file || !size) return 0; - char* buf = qemu_malloc(bitmap_size); - memset(buf,0x0,bitmap_size); - - + char* buf = qemu_mallocz(bitmap_size); memset(&header,0,sizeof(header)); sprintf(header.backing_file,"%s",backing_file); @@ -70,11 +66,7 @@ inline int my_cow_set_bit(BlockDriverState *bs, int64_t bitnum) uint8_t bitmap; int ret; - /*ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap)); - if (ret < 0) { - return ret; - }*/ - int cow_fd = open("my_vm.cow", O_RDWR | O_BINARY, + int cow_fd = open(bs->cow_file, O_RDWR | O_BINARY, 0644); if (cow_fd < 0) return -errno; @@ -85,10 +77,6 @@ inline int my_cow_set_bit(BlockDriverState *bs, int64_t bitnum) bitmap |= (1 << (bitnum % 8)); - /*ret = bdrv_pwrite_sync(bs->file, offset, &bitmap, sizeof(bitmap)); - if (ret < 0) { - return ret; - }*/ ret = pwrite(cow_fd,&bitmap,sizeof(bitmap),offset); if( ret < 0 ) return ret; @@ -100,47 +88,40 @@ inline int my_is_bit_set(BlockDriverState *bs, int64_t bitnum) { uint64_t offset = sizeof(struct add_cow_head) + bitnum / 8; uint8_t bitmap; - fprintf(stderr,"\t\t\tbitnum = %lld,cow_file=%s\n",bitnum,bs->cow_file[0]?bs->cow_file:"NULL"); - int cow_fd = open("my_vm.cow", O_RDONLY | O_BINARY, + + int cow_fd = open(bs->cow_file, O_RDONLY | O_BINARY, 0644); if (cow_fd < 0) { close(cow_fd); return -errno; - } + } if(pread(cow_fd,&bitmap,sizeof(bitmap),offset) == -1) { close(cow_fd); return -errno; - } + } close(cow_fd); return !!(bitmap & (1 << (bitnum % 8))); } -/* Return true if first block has been changed (ie. current version is - * in COW file). Set the number of continuous blocks for which that - * is true. */ int my_cow_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *num_same) { int changed; if (nb_sectors == 0) { - *num_same = nb_sectors; - return 0; + *num_same = nb_sectors; + return 0; } changed = my_is_bit_set(bs, sector_num); if (changed < 0) { - return 0; /* XXX: how to return I/O errors? */ + return 0; } -fprintf(stderr,"sector_num = %lld,nb_sectors=%d,*num_same = %d\n",sector_num,nb_sectors,*num_same); - for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) { -fprintf(stderr,"\tsector_num = %lld,nb_sectors=%d,*num_same = %d\n",sector_num,nb_sectors,*num_same); - if (my_is_bit_set(bs, sector_num + *num_same) != changed) -fprintf(stderr,"\t\tsector_num = %lld,nb_sectors=%d,*num_same = %d\n",sector_num,nb_sectors,*num_same); - - break; + for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) { + if (my_is_bit_set(bs, sector_num + *num_same) != changed) + break; } return changed; diff --git a/block/add-cow.h b/block/add-cow.h index 94f6d12ff5..f8a7c032ba 100644 --- a/block/add-cow.h +++ b/block/add-cow.h @@ -1,11 +1,9 @@ #ifndef QEMU_ADD_COW_H - #include #include #include #include #include -#include #include "qemu-common.h" diff --git a/block/raw-posix.c b/block/raw-posix.c index c5c99446c0..96a6012f38 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -80,6 +80,8 @@ #include #endif +#include "block/add-cow.h" + //#define DEBUG_FLOPPY //#define DEBUG_BLOCK @@ -112,7 +114,7 @@ reopen it to see if the disk has been changed */ #define FD_OPEN_TIMEOUT (1000000000) -#define MAX_BLOCKSIZE 4096 +#define MAX_BLOCKSIZE 4096 typedef struct BDRVRawState { int fd; @@ -270,6 +272,12 @@ out_close: static int raw_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRawState *s = bs->opaque; + struct add_cow_head cow_header; + + if(bs->cow_file[0] && (get_add_cow_head(bs->cow_file,&cow_header) <0 )) { + DEBUG_BLOCK_PRINT("get_add_cow_head() failed: %d = %s\n", + errno, strerror(errno)); + } s->type = FTYPE_FILE; return raw_open_common(bs, filename, flags, 0); @@ -743,7 +751,7 @@ again: #endif if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { #ifdef DIOCGMEDIASIZE - if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) + if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) #elif defined(DIOCGPART) { struct partinfo pi; @@ -808,12 +816,25 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) int fd; int result = 0; int64_t total_size = 0; + char *backing_file = NULL; + char *backing_fmt = NULL; + char *cow_file = NULL; /* Read out options */ while (options && options->name) { if (!strcmp(options->name, BLOCK_OPT_SIZE)) { total_size = options->value.n / BDRV_SECTOR_SIZE; } + else if(!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { + backing_file = options->value.s; + } + else if(!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) { + backing_fmt = options->value.s; + } + else if(!strcmp(options->name, BLOCK_OPT_COW_FILE)) { + cow_file = options->value.s; + } + options++; } @@ -829,6 +850,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) result = -errno; } } + + create_cow_file(backing_file,backing_fmt,cow_file,total_size); return result; } @@ -1161,13 +1184,13 @@ static BlockDriver bdrv_host_device = { .bdrv_has_zero_init = hdev_has_zero_init, .bdrv_flush = raw_flush, - .bdrv_aio_readv = raw_aio_readv, - .bdrv_aio_writev = raw_aio_writev, - .bdrv_aio_flush = raw_aio_flush, + .bdrv_aio_readv = raw_aio_readv, + .bdrv_aio_writev = raw_aio_writev, + .bdrv_aio_flush = raw_aio_flush, .bdrv_read = raw_read, .bdrv_write = raw_write, - .bdrv_getlength = raw_getlength, + .bdrv_getlength = raw_getlength, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, @@ -1274,7 +1297,7 @@ static BlockDriver bdrv_host_floppy = { .format_name = "host_floppy", .protocol_name = "host_floppy", .instance_size = sizeof(BDRVRawState), - .bdrv_probe_device = floppy_probe_device, + .bdrv_probe_device = floppy_probe_device, .bdrv_file_open = floppy_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, @@ -1284,11 +1307,11 @@ static BlockDriver bdrv_host_floppy = { .bdrv_aio_readv = raw_aio_readv, .bdrv_aio_writev = raw_aio_writev, - .bdrv_aio_flush = raw_aio_flush, + .bdrv_aio_flush = raw_aio_flush, .bdrv_read = raw_read, .bdrv_write = raw_write, - .bdrv_getlength = raw_getlength, + .bdrv_getlength = raw_getlength, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, @@ -1375,7 +1398,7 @@ static BlockDriver bdrv_host_cdrom = { .format_name = "host_cdrom", .protocol_name = "host_cdrom", .instance_size = sizeof(BDRVRawState), - .bdrv_probe_device = cdrom_probe_device, + .bdrv_probe_device = cdrom_probe_device, .bdrv_file_open = cdrom_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, @@ -1385,7 +1408,7 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_aio_readv = raw_aio_readv, .bdrv_aio_writev = raw_aio_writev, - .bdrv_aio_flush = raw_aio_flush, + .bdrv_aio_flush = raw_aio_flush, .bdrv_read = raw_read, .bdrv_write = raw_write, @@ -1496,7 +1519,7 @@ static BlockDriver bdrv_host_cdrom = { .format_name = "host_cdrom", .protocol_name = "host_cdrom", .instance_size = sizeof(BDRVRawState), - .bdrv_probe_device = cdrom_probe_device, + .bdrv_probe_device = cdrom_probe_device, .bdrv_file_open = cdrom_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, @@ -1506,7 +1529,7 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_aio_readv = raw_aio_readv, .bdrv_aio_writev = raw_aio_writev, - .bdrv_aio_flush = raw_aio_flush, + .bdrv_aio_flush = raw_aio_flush, .bdrv_read = raw_read, .bdrv_write = raw_write, diff --git a/block/raw.c b/block/raw.c index cb6203eeca..2d27eb59aa 100644 --- a/block/raw.c +++ b/block/raw.c @@ -2,6 +2,7 @@ #include "qemu-common.h" #include "block_int.h" #include "module.h" +#include "block/add-cow.h" static int raw_open(BlockDriverState *bs, int flags) { @@ -12,13 +13,43 @@ static int raw_open(BlockDriverState *bs, int flags) static int raw_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { - return bdrv_read(bs->file, sector_num, buf, nb_sectors); + //return bdrv_read(bs->file, sector_num, buf, nb_sectors); + int ret, n = 0; + + while (nb_sectors > 0) { + if(!bs->cow_file[0]) { + return bdrv_read(bs->file, sector_num, buf, nb_sectors); + } + else if (my_cow_is_allocated(bs, sector_num, nb_sectors, &n)) { + ret = bdrv_read(bs->file, sector_num , buf, n); + if (ret != n) + return -1; + } else { + if (bs->backing_hd) { + ret = bdrv_read(bs->backing_hd, sector_num, buf, n); + if (ret < 0) + return -1; + } else { + memset(buf, 0, n * 512); + } + } + nb_sectors -= n; + sector_num += n; + buf += n * 512; + } + return 0; } static int raw_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { - return bdrv_write(bs->file, sector_num, buf, nb_sectors); + //return bdrv_write(bs->file, sector_num, buf, nb_sectors); + if(bs->cow_file[0]) { + bdrv_write(bs->file, sector_num, buf, nb_sectors); + return my_cow_update_bitmap(bs,sector_num,nb_sectors); + } + + return bdrv_write(bs->file, sector_num, buf, nb_sectors); } static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs, @@ -108,6 +139,16 @@ static QEMUOptionParameter raw_create_options[] = { .type = OPT_SIZE, .help = "Virtual disk size" }, + { + .name = BLOCK_OPT_BACKING_FILE, + .type = OPT_STRING, + .help = "File name of a base image" + }, + { + .name = BLOCK_OPT_COW_FILE, + .type = OPT_STRING, + .help = "File name of a Copy-On-Write file" + }, { NULL } }; diff --git a/block_int.h b/block_int.h index f6d02b38a7..a1dce45e50 100644 --- a/block_int.h +++ b/block_int.h @@ -41,6 +41,7 @@ #define BLOCK_OPT_TABLE_SIZE "table_size" #define BLOCK_OPT_PREALLOC "preallocation" #define BLOCK_OPT_SUBFMT "subformat" +#define BLOCK_OPT_COW_FILE "cow_file" typedef struct AIOPool { void (*cancel)(BlockDriverAIOCB *acb); @@ -173,6 +174,7 @@ struct BlockDriverState { char backing_file[1024]; /* if non zero, the image is a diff of this file image */ char backing_format[16]; /* if non-zero and backing_file exists */ + char cow_file[1024]; /* add copy-on-write feature support */ int is_temporary; int media_changed; -- 2.11.4.GIT