]> xenbits.xensource.com Git - qemu-xen-4.0-testing.git/commitdiff
block extendable changes found 2008-04-28 iwj.block-extendable-flag
authorIan Jackson <iwj@mariner.uk.xensource.com>
Mon, 28 Apr 2008 13:31:17 +0000 (14:31 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Mon, 12 May 2008 11:39:51 +0000 (12:39 +0100)
block-qcow.c
block-qcow2.c
block-raw-posix.c
block-raw-win32.c
block-vmdk.c
block.c
block.h
block_int.h

index 59f1c66c56e9aee4b918a37bea135b8b8ededaa0..c4aea0c531a5fb8f7fc8ca33cced27a228447362 100644 (file)
@@ -95,7 +95,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     int len, i, shift, ret;
     QCowHeader header;
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
+    ret = bdrv_file_open(&s->hd, filename, flags | BDRV_O_EXTENDABLE);
     if (ret < 0)
         return ret;
     if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
index 9bad090c4555de95b0cc35a29e399d83ad8db5b6..3663362e2640d74d5d6ca34bb4aa93e968a0fb22 100644 (file)
@@ -191,7 +191,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     int len, i, shift, ret;
     QCowHeader header;
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
+    ret = bdrv_file_open(&s->hd, filename, flags | BDRV_O_EXTENDABLE);
     if (ret < 0)
         return ret;
     if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
index 45d0a932c813e7988b7559e90d8e5823b62f05e3..d57a2d5276e14ae50251c0257736f97a06140ed2 100644 (file)
@@ -925,4 +925,6 @@ BlockDriver bdrv_host_device = {
     .bdrv_set_locked = raw_set_locked,
     /* generic scsi device */
     .bdrv_ioctl = raw_ioctl,
+
+    .bdrv_flags = BLOCK_DRIVER_FLAG_EXTENDABLE
 };
index b86c66e9f2df8b5191b07d7a7fa35700a3db6374..bbd2e315cae1d7c64db6827c5506edac133f63dc 100644 (file)
@@ -549,4 +549,6 @@ BlockDriver bdrv_host_device = {
     .bdrv_pread = raw_pread,
     .bdrv_pwrite = raw_pwrite,
     .bdrv_getlength = raw_getlength,
+
+    .bdrv_flags = BLOCK_DRIVER_FLAG_EXTENDABLE
 };
index 4cacc6a6ab771bda794bee42ee1af4abc0c05aba..e49db6b9139336a2d1723f3a74174130f2302ae0 100644 (file)
@@ -378,7 +378,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
         flags = BDRV_O_RDONLY;
     fprintf(stderr, "(VMDK) image open: flags=0x%x filename=%s\n", flags, bs->filename);
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
+    ret = bdrv_file_open(&s->hd, filename, flags | BDRV_O_EXTENDABLE);
     if (ret < 0)
         return ret;
     if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
diff --git a/block.c b/block.c
index fc32a60c6e2ee41688a94a336360cc7451d8269a..a2515bddcc8e32cb98a62bd45b3b924a1e5f7b8a 100644 (file)
--- a/block.c
+++ b/block.c
@@ -123,6 +123,27 @@ void path_combine(char *dest, int dest_size,
     }
 }
 
+static int bdrv_rw_badreq_sectors(BlockDriverState *bs,
+                               int64_t sector_num, int nb_sectors)
+{
+    return (
+       nb_sectors < 0 ||
+       nb_sectors > bs->total_sectors ||
+       sector_num > bs->total_sectors - nb_sectors
+       ) && !bs->extendable;
+}
+
+static int bdrv_rw_badreq_bytes(BlockDriverState *bs,
+                                 int64_t offset, int count)
+{
+    int64_t size = bs->total_sectors << SECTOR_BITS;
+    return (
+       count < 0 ||
+       count > size ||
+       offset > size - count
+       ) && !bs->extendable;
+    
+}
 
 static void bdrv_register(BlockDriver *bdrv)
 {
@@ -336,6 +357,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
     bs->is_temporary = 0;
     bs->encrypted = 0;
 
+    if (flags & BDRV_O_EXTENDABLE) {
+       if (!(drv->bdrv_flags & BLOCK_DRIVER_FLAG_EXTENDABLE))
+           return -ENOSYS;
+       bs->extendable = 1;
+    }
+
     if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;
         int64_t total_size;
@@ -379,6 +406,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
     }
     bs->drv = drv;
     bs->opaque = qemu_mallocz(drv->instance_size);
+    bs->total_sectors = 0; /* driver will set if it does not do getlength */
     if (bs->opaque == NULL && drv->instance_size > 0)
         return -1;
     /* Note: for compatibility, we open disk image files as RDWR, and
@@ -444,6 +472,7 @@ void bdrv_close(BlockDriverState *bs)
         bs->drv = NULL;
 
         /* call the change callback */
+       bs->total_sectors = 0;
         bs->media_changed = 1;
         if (bs->change_cb)
             bs->change_cb(bs->change_opaque);
@@ -509,6 +538,8 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
     if (!drv)
         return -ENOMEDIUM;
 
+    if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
+       return -EDOM;
     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
             memcpy(buf, bs->boot_sector_data, 512);
         sector_num++;
@@ -549,6 +580,8 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
         return -ENOMEDIUM;
     if (bs->read_only)
         return -EACCES;
+    if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
+       return -EDOM;
     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
         memcpy(bs->boot_sector_data, buf, 512);
     }
@@ -674,6 +707,8 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
         return -ENOMEDIUM;
     if (!drv->bdrv_pread)
         return bdrv_pread_em(bs, offset, buf1, count1);
+    if (bdrv_rw_badreq_bytes(bs, offset, count1))
+       return -EDOM;
     return drv->bdrv_pread(bs, offset, buf1, count1);
 }
 
@@ -689,6 +724,8 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
         return -ENOMEDIUM;
     if (!drv->bdrv_pwrite)
         return bdrv_pwrite_em(bs, offset, buf1, count1);
+    if (bdrv_rw_badreq_bytes(bs, offset, count1))
+       return -EDOM;
     return drv->bdrv_pwrite(bs, offset, buf1, count1);
 }
 
@@ -957,6 +994,8 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
         return -ENOMEDIUM;
     if (!drv->bdrv_write_compressed)
         return -ENOTSUP;
+    if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
+       return -EDOM;
     return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
 }
 
@@ -1103,6 +1142,8 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
 
     if (!drv)
         return NULL;
+    if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
+       return NULL;
 
     /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
@@ -1134,6 +1175,8 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
         return NULL;
     if (bs->read_only)
         return NULL;
+    if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
+       return NULL;
     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
         memcpy(bs->boot_sector_data, buf, 512);
     }
diff --git a/block.h b/block.h
index 861a65b18036d51330ef77b4e4cb355fc16f91af..2dfabda1b1fc43b9ecd25c9847eca513e252653e 100644 (file)
--- a/block.h
+++ b/block.h
@@ -45,6 +45,8 @@ typedef struct QEMUSnapshotInfo {
                                      it (default for
                                      bdrv_file_open()) */
 #define BDRV_O_DIRECT      0x0020
+#define BDRV_O_EXTENDABLE  0x0080 /* allow writes out of original size range;
+                                    only effective for some drivers */
 
 #ifndef QEMU_IMG
 void bdrv_info(void);
index 796ce294ff9732eeef0d8dfb55096901ec5875c8..c752344c4742a60a01c6b7cba3a8a267abde447c 100644 (file)
@@ -30,6 +30,8 @@
 #define BLOCK_FLAG_COMPRESS    2
 #define BLOCK_FLAG_COMPAT6     4
 
+#define BLOCK_DRIVER_FLAG_EXTENDABLE  0x0001u
+
 struct BlockDriver {
     const char *format_name;
     int instance_size;
@@ -85,6 +87,7 @@ struct BlockDriver {
     /* to control generic scsi devices */
     int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf);
 
+    unsigned bdrv_flags;
     BlockDriverAIOCB *free_aiocb;
     struct BlockDriver *next;
 };
@@ -97,6 +100,7 @@ struct BlockDriverState {
     int locked;    /* if true, the media cannot temporarily be ejected */
     int encrypted; /* if true, the media is encrypted */
     int sg;        /* if true, the device is a /dev/sg* */
+    int extendable;/* if true, we may write out of original range */
     /* event callback when inserting/removing */
     void (*change_cb)(void *opaque);
     void *change_opaque;