summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--block.c49
-rw-r--r--block.h2
-rw-r--r--block/blkdebug.c4
-rw-r--r--block/bochs.c81
-rw-r--r--block/cloop.c48
-rw-r--r--block/dmg.c109
-rw-r--r--block/parallels.c51
-rw-r--r--block/qcow.c2
-rw-r--r--block/qcow2.c2
-rw-r--r--block/vdi.c34
-rw-r--r--block/vpc.c21
-rw-r--r--hw/ide/core.c8
-rw-r--r--qemu-nbd.c34
13 files changed, 213 insertions, 232 deletions
diff --git a/block.c b/block.c
index 48305b7d7c..bfe46e3765 100644
--- a/block.c
+++ b/block.c
@@ -287,16 +287,18 @@ static BlockDriver *find_protocol(const char *filename)
     char protocol[128];
     int len;
     const char *p;
+    int is_drive;
 
     /* TODO Drivers without bdrv_file_open must be specified explicitly */
 
 #ifdef _WIN32
-    if (is_windows_drive(filename) ||
-        is_windows_drive_prefix(filename))
-        return bdrv_find_format("file");
+    is_drive = is_windows_drive(filename) ||
+        is_windows_drive_prefix(filename);
+#else
+    is_drive = 0;
 #endif
     p = strchr(filename, ':');
-    if (!p) {
+    if (!p || is_drive) {
         drv1 = find_hdev_driver(filename);
         if (!drv1) {
             drv1 = bdrv_find_format("file");
@@ -324,11 +326,6 @@ static BlockDriver *find_image_format(const char *filename)
     uint8_t buf[2048];
     BlockDriverState *bs;
 
-    drv = find_protocol(filename);
-    /* no need to test disk image formats for vvfat */
-    if (drv && strcmp(drv->format_name, "vvfat") == 0)
-        return drv;
-
     ret = bdrv_file_open(&bs, filename, 0);
     if (ret < 0)
         return NULL;
@@ -699,12 +696,12 @@ int bdrv_commit(BlockDriverState *bs)
         bdrv_delete(bs->backing_hd);
         bs->backing_hd = NULL;
         bs_rw = bdrv_new("");
-        rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, NULL);
+        rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, drv);
         if (rw_ret < 0) {
             bdrv_delete(bs_rw);
             /* try to re-open read-only */
             bs_ro = bdrv_new("");
-            ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
+            ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
             if (ret < 0) {
                 bdrv_delete(bs_ro);
                 /* drive not functional anymore */
@@ -756,7 +753,7 @@ ro_cleanup:
         bdrv_delete(bs->backing_hd);
         bs->backing_hd = NULL;
         bs_ro = bdrv_new("");
-        ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
+        ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
         if (ret < 0) {
             bdrv_delete(bs_ro);
             /* drive not functional anymore */
@@ -1580,9 +1577,9 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
  *     - "wr_operations": write operations
  *     - "wr_highest_offset": Highest offset of a sector written since the
  *       BlockDriverState has been opened
- *     - "parent": Contains recursively the statistics of the underlying
- *       protocol (e.g. the host file for a qcow2 image). If there is no
- *       underlying protocol, this field is omitted.
+ * - "parent": A QDict recursively holding the statistics of the underlying
+ *    protocol (e.g. the host file for a qcow2 image). If there is no
+ *    underlying protocol, this field is omitted.
  *
  * Example:
  *
@@ -1591,15 +1588,14 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
  *                          "wr_bytes": 0,
  *                          "rd_operations": 1,
  *                          "wr_operations": 0,
- *                          "wr_highest_offset": 0,
- *                          "parent": {
- *                              "stats": { "rd_bytes": 1024,
- *                                         "wr_bytes": 0,
- *                                         "rd_operations": 2,
- *                                         "wr_operations": 0,
- *                                         "wr_highest_offset": 0,
- *                              }
- *                          } } },
+ *                          "wr_highest_offset": 0 },
+ *               "parent": {
+ *                      "stats": { "rd_bytes": 1024,
+ *                                 "wr_bytes": 0,
+ *                                 "rd_operations": 2,
+ *                                 "wr_operations": 0,
+ *                                 "wr_highest_offset": 0,
+ *                      } } },
  *   { "device": "ide1-cd0",
  *               "stats": { "rd_bytes": 0,
  *                          "wr_bytes": 0,
@@ -2073,7 +2069,7 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
     return 0;
 
 fail:
-    free(mcb);
+    qemu_free(mcb);
     return -1;
 }
 
@@ -2108,7 +2104,8 @@ typedef struct BlockDriverAIOCBSync {
 
 static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
 {
-    BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
+    BlockDriverAIOCBSync *acb =
+        container_of(blockacb, BlockDriverAIOCBSync, common);
     qemu_bh_delete(acb->bh);
     acb->bh = NULL;
     qemu_aio_release(acb);
diff --git a/block.h b/block.h
index f87d24e5c8..278259c2ba 100644
--- a/block.h
+++ b/block.h
@@ -38,7 +38,7 @@ typedef struct QEMUSnapshotInfo {
 
 #define BDRV_SECTOR_BITS   9
 #define BDRV_SECTOR_SIZE   (1 << BDRV_SECTOR_BITS)
-#define BDRV_SECTOR_MASK   ~(BDRV_SECTOR_SIZE - 1);
+#define BDRV_SECTOR_MASK   ~(BDRV_SECTOR_SIZE - 1)
 
 typedef enum {
     BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP
diff --git a/block/blkdebug.c b/block/blkdebug.c
index bb4a91abc7..8325f75f80 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -320,7 +320,7 @@ static void error_callback_bh(void *opaque)
 
 static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    BlkdebugAIOCB *acb = (BlkdebugAIOCB*) blockacb;
+    BlkdebugAIOCB *acb = container_of(blockacb, BlkdebugAIOCB, common);
     qemu_aio_release(acb);
 }
 
@@ -347,7 +347,7 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
     acb->bh = bh;
     qemu_bh_schedule(bh);
 
-    return (BlockDriverAIOCB*) acb;
+    return &acb->common;
 }
 
 static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
diff --git a/block/bochs.c b/block/bochs.c
index e952670cd1..5fe2fa3580 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -80,8 +80,6 @@ struct bochs_header {
 };
 
 typedef struct BDRVBochsState {
-    int fd;
-
     uint32_t *catalog_bitmap;
     int catalog_size;
 
@@ -109,23 +107,16 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
+static int bochs_open(BlockDriverState *bs, int flags)
 {
     BDRVBochsState *s = bs->opaque;
-    int fd, i;
+    int i;
     struct bochs_header bochs;
     struct bochs_header_v1 header_v1;
 
-    fd = open(filename, O_RDONLY | O_BINARY);
-    if (fd < 0) {
-        return -1;
-    }
-
     bs->read_only = 1; // no write support yet
 
-    s->fd = fd;
-
-    if (read(fd, &bochs, sizeof(bochs)) != sizeof(bochs)) {
+    if (bdrv_pread(bs->file, 0, &bochs, sizeof(bochs)) != sizeof(bochs)) {
         goto fail;
     }
 
@@ -144,14 +135,10 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
       bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
     }
 
-    if (lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET) == (off_t)-1) {
-        goto fail;
-    }
-
     s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
     s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
-    if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
-	s->catalog_size * 4)
+    if (bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
+                   s->catalog_size * 4) != s->catalog_size * 4)
 	goto fail;
     for (i = 0; i < s->catalog_size; i++)
 	le32_to_cpus(&s->catalog_bitmap[i]);
@@ -165,74 +152,53 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
 
     return 0;
  fail:
-    close(fd);
     return -1;
 }
 
-static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
+static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
 {
     BDRVBochsState *s = bs->opaque;
     int64_t offset = sector_num * 512;
-    int64_t extent_index, extent_offset, bitmap_offset, block_offset;
+    int64_t extent_index, extent_offset, bitmap_offset;
     char bitmap_entry;
 
     // seek to sector
     extent_index = offset / s->extent_size;
     extent_offset = (offset % s->extent_size) / 512;
 
-    if (s->catalog_bitmap[extent_index] == 0xffffffff)
-    {
-//	fprintf(stderr, "page not allocated [%x - %x:%x]\n",
-//	    sector_num, extent_index, extent_offset);
-	return -1; // not allocated
+    if (s->catalog_bitmap[extent_index] == 0xffffffff) {
+	return -1; /* not allocated */
     }
 
     bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *
 	(s->extent_blocks + s->bitmap_blocks));
-    block_offset = bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
 
-//    fprintf(stderr, "sect: %x [ext i: %x o: %x] -> %x bitmap: %x block: %x\n",
-//	sector_num, extent_index, extent_offset,
-//	le32_to_cpu(s->catalog_bitmap[extent_index]),
-//	bitmap_offset, block_offset);
-
-    // read in bitmap for current extent
-    if (lseek(s->fd, bitmap_offset + (extent_offset / 8), SEEK_SET) ==
-        (off_t)-1) {
-        return -1;
-    }
-
-    if (read(s->fd, &bitmap_entry, 1) != 1)
+    /* read in bitmap for current extent */
+    if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
+                   &bitmap_entry, 1) != 1) {
         return -1;
-
-    if (!((bitmap_entry >> (extent_offset % 8)) & 1))
-    {
-//	fprintf(stderr, "sector (%x) in bitmap not allocated\n",
-//	    sector_num);
-	return -1; // not allocated
     }
 
-    if (lseek(s->fd, block_offset, SEEK_SET) == (off_t)-1) {
-        return -1;
+    if (!((bitmap_entry >> (extent_offset % 8)) & 1)) {
+	return -1; /* not allocated */
     }
 
-    return 0;
+    return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
 }
 
 static int bochs_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
-    BDRVBochsState *s = bs->opaque;
     int ret;
 
     while (nb_sectors > 0) {
-	if (!seek_to_sector(bs, sector_num))
-	{
-	    ret = read(s->fd, buf, 512);
-	    if (ret != 512)
-		return -1;
-	}
-	else
+        int64_t block_offset = seek_to_sector(bs, sector_num);
+        if (block_offset >= 0) {
+            ret = bdrv_pread(bs->file, block_offset, buf, 512);
+            if (ret != 512) {
+                return -1;
+            }
+        } else
             memset(buf, 0, 512);
         nb_sectors--;
         sector_num++;
@@ -245,14 +211,13 @@ static void bochs_close(BlockDriverState *bs)
 {
     BDRVBochsState *s = bs->opaque;
     qemu_free(s->catalog_bitmap);
-    close(s->fd);
 }
 
 static BlockDriver bdrv_bochs = {
     .format_name	= "bochs",
     .instance_size	= sizeof(BDRVBochsState),
     .bdrv_probe		= bochs_probe,
-    .bdrv_file_open	= bochs_open,
+    .bdrv_open		= bochs_open,
     .bdrv_read		= bochs_read,
     .bdrv_close		= bochs_close,
 };
diff --git a/block/cloop.c b/block/cloop.c
index e4f995b5d6..fe015c4255 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -27,7 +27,6 @@
 #include <zlib.h>
 
 typedef struct BDRVCloopState {
-    int fd;
     uint32_t block_size;
     uint32_t n_blocks;
     uint64_t* offsets;
@@ -51,34 +50,31 @@ static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
+static int cloop_open(BlockDriverState *bs, int flags)
 {
     BDRVCloopState *s = bs->opaque;
     uint32_t offsets_size,max_compressed_block_size=1,i;
 
-    s->fd = open(filename, O_RDONLY | O_BINARY);
-    if (s->fd < 0)
-        return -errno;
     bs->read_only = 1;
 
     /* read header */
-    if(lseek(s->fd,128,SEEK_SET)<0) {
-cloop_close:
-	close(s->fd);
-	return -1;
+    if (bdrv_pread(bs->file, 128, &s->block_size, 4) < 4) {
+        goto cloop_close;
     }
-    if(read(s->fd,&s->block_size,4)<4)
-	goto cloop_close;
-    s->block_size=be32_to_cpu(s->block_size);
-    if(read(s->fd,&s->n_blocks,4)<4)
-	goto cloop_close;
-    s->n_blocks=be32_to_cpu(s->n_blocks);
+    s->block_size = be32_to_cpu(s->block_size);
+
+    if (bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4) < 4) {
+        goto cloop_close;
+    }
+    s->n_blocks = be32_to_cpu(s->n_blocks);
 
     /* read offsets */
-    offsets_size=s->n_blocks*sizeof(uint64_t);
-    s->offsets=(uint64_t*)qemu_malloc(offsets_size);
-    if(read(s->fd,s->offsets,offsets_size)<offsets_size)
+    offsets_size = s->n_blocks * sizeof(uint64_t);
+    s->offsets = qemu_malloc(offsets_size);
+    if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) <
+            offsets_size) {
 	goto cloop_close;
+    }
     for(i=0;i<s->n_blocks;i++) {
 	s->offsets[i]=be64_to_cpu(s->offsets[i]);
 	if(i>0) {
@@ -98,16 +94,21 @@ cloop_close:
     s->sectors_per_block = s->block_size/512;
     bs->total_sectors = s->n_blocks*s->sectors_per_block;
     return 0;
+
+cloop_close:
+    return -1;
 }
 
-static inline int cloop_read_block(BDRVCloopState *s,int block_num)
+static inline int cloop_read_block(BlockDriverState *bs, int block_num)
 {
+    BDRVCloopState *s = bs->opaque;
+
     if(s->current_block != block_num) {
 	int ret;
         uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
 
-	lseek(s->fd, s->offsets[block_num], SEEK_SET);
-        ret = read(s->fd, s->compressed_block, bytes);
+        ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
+                         bytes);
         if (ret != bytes)
             return -1;
 
@@ -136,7 +137,7 @@ static int cloop_read(BlockDriverState *bs, int64_t sector_num,
     for(i=0;i<nb_sectors;i++) {
 	uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
 	    block_num=(sector_num+i)/s->sectors_per_block;
-	if(cloop_read_block(s, block_num) != 0)
+	if(cloop_read_block(bs, block_num) != 0)
 	    return -1;
 	memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
     }
@@ -146,7 +147,6 @@ static int cloop_read(BlockDriverState *bs, int64_t sector_num,
 static void cloop_close(BlockDriverState *bs)
 {
     BDRVCloopState *s = bs->opaque;
-    close(s->fd);
     if(s->n_blocks>0)
 	free(s->offsets);
     free(s->compressed_block);
@@ -158,7 +158,7 @@ static BlockDriver bdrv_cloop = {
     .format_name	= "cloop",
     .instance_size	= sizeof(BDRVCloopState),
     .bdrv_probe		= cloop_probe,
-    .bdrv_file_open	= cloop_open,
+    .bdrv_open		= cloop_open,
     .bdrv_read		= cloop_read,
     .bdrv_close		= cloop_close,
 };
diff --git a/block/dmg.c b/block/dmg.c
index d5c1a687e4..a3c815b862 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -28,8 +28,6 @@
 #include <zlib.h>
 
 typedef struct BDRVDMGState {
-    int fd;
-
     /* each chunk contains a certain number of sectors,
      * offsets[i] is the offset in the .dmg file,
      * lengths[i] is the length of the compressed chunk,
@@ -58,69 +56,75 @@ static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static off_t read_off(int fd)
+static off_t read_off(BlockDriverState *bs, int64_t offset)
 {
 	uint64_t buffer;
-	if(read(fd,&buffer,8)<8)
+	if (bdrv_pread(bs->file, offset, &buffer, 8) < 8)
 		return 0;
 	return be64_to_cpu(buffer);
 }
 
-static off_t read_uint32(int fd)
+static off_t read_uint32(BlockDriverState *bs, int64_t offset)
 {
 	uint32_t buffer;
-	if(read(fd,&buffer,4)<4)
+	if (bdrv_pread(bs->file, offset, &buffer, 4) < 4)
 		return 0;
 	return be32_to_cpu(buffer);
 }
 
-static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
+static int dmg_open(BlockDriverState *bs, int flags)
 {
     BDRVDMGState *s = bs->opaque;
     off_t info_begin,info_end,last_in_offset,last_out_offset;
     uint32_t count;
     uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
+    int64_t offset;
 
-    s->fd = open(filename, O_RDONLY | O_BINARY);
-    if (s->fd < 0)
-        return -errno;
     bs->read_only = 1;
     s->n_chunks = 0;
     s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
 
     /* read offset of info blocks */
-    if(lseek(s->fd,-0x1d8,SEEK_END)<0) {
+    offset = bdrv_getlength(bs->file);
+    if (offset < 0) {
         goto fail;
     }
+    offset -= 0x1d8;
 
-    info_begin=read_off(s->fd);
-    if(info_begin==0)
-	goto fail;
-    if(lseek(s->fd,info_begin,SEEK_SET)<0)
-	goto fail;
-    if(read_uint32(s->fd)!=0x100)
-	goto fail;
-    if((count = read_uint32(s->fd))==0)
-	goto fail;
-    info_end = info_begin+count;
-    if(lseek(s->fd,0xf8,SEEK_CUR)<0)
+    info_begin = read_off(bs, offset);
+    if (info_begin == 0) {
 	goto fail;
+    }
+
+    if (read_uint32(bs, info_begin) != 0x100) {
+        goto fail;
+    }
+
+    count = read_uint32(bs, info_begin + 4);
+    if (count == 0) {
+        goto fail;
+    }
+    info_end = info_begin + count;
+
+    offset = info_begin + 0x100;
 
     /* read offsets */
     last_in_offset = last_out_offset = 0;
-    while(lseek(s->fd,0,SEEK_CUR)<info_end) {
+    while (offset < info_end) {
         uint32_t type;
 
-	count = read_uint32(s->fd);
+	count = read_uint32(bs, offset);
 	if(count==0)
 	    goto fail;
-	type = read_uint32(s->fd);
-	if(type!=0x6d697368 || count<244)
-	    lseek(s->fd,count-4,SEEK_CUR);
-	else {
+        offset += 4;
+
+	type = read_uint32(bs, offset);
+	if (type == 0x6d697368 && count >= 244) {
 	    int new_size, chunk_count;
-	    if(lseek(s->fd,200,SEEK_CUR)<0)
-	        goto fail;
+
+            offset += 4;
+            offset += 200;
+
 	    chunk_count = (count-204)/40;
 	    new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
 	    s->types = qemu_realloc(s->types, new_size/2);
@@ -130,7 +134,8 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
 	    s->sectorcounts = qemu_realloc(s->sectorcounts, new_size);
 
 	    for(i=s->n_chunks;i<s->n_chunks+chunk_count;i++) {
-		s->types[i] = read_uint32(s->fd);
+		s->types[i] = read_uint32(bs, offset);
+		offset += 4;
 		if(s->types[i]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) {
 		    if(s->types[i]==0xffffffff) {
 			last_in_offset = s->offsets[i-1]+s->lengths[i-1];
@@ -138,15 +143,23 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
 		    }
 		    chunk_count--;
 		    i--;
-		    if(lseek(s->fd,36,SEEK_CUR)<0)
-			goto fail;
+		    offset += 36;
 		    continue;
 		}
-		read_uint32(s->fd);
-		s->sectors[i] = last_out_offset+read_off(s->fd);
-		s->sectorcounts[i] = read_off(s->fd);
-		s->offsets[i] = last_in_offset+read_off(s->fd);
-		s->lengths[i] = read_off(s->fd);
+		offset += 4;
+
+		s->sectors[i] = last_out_offset+read_off(bs, offset);
+		offset += 8;
+
+		s->sectorcounts[i] = read_off(bs, offset);
+		offset += 8;
+
+		s->offsets[i] = last_in_offset+read_off(bs, offset);
+		offset += 8;
+
+		s->lengths[i] = read_off(bs, offset);
+		offset += 8;
+
 		if(s->lengths[i]>max_compressed_size)
 		    max_compressed_size = s->lengths[i];
 		if(s->sectorcounts[i]>max_sectors_per_chunk)
@@ -166,7 +179,6 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
 
     return 0;
 fail:
-    close(s->fd);
     return -1;
 }
 
@@ -196,8 +208,10 @@ static inline uint32_t search_chunk(BDRVDMGState* s,int sector_num)
     return s->n_chunks; /* error */
 }
 
-static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
+static inline int dmg_read_chunk(BlockDriverState *bs, int sector_num)
 {
+    BDRVDMGState *s = bs->opaque;
+
     if(!is_sector_in_chunk(s,s->current_chunk,sector_num)) {
 	int ret;
 	uint32_t chunk = search_chunk(s,sector_num);
@@ -210,15 +224,12 @@ static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
 	case 0x80000005: { /* zlib compressed */
 	    int i;
 
-	    ret = lseek(s->fd, s->offsets[chunk], SEEK_SET);
-	    if(ret<0)
-		return -1;
-
 	    /* we need to buffer, because only the chunk as whole can be
 	     * inflated. */
 	    i=0;
 	    do {
-		ret = read(s->fd, s->compressed_chunk+i, s->lengths[chunk]-i);
+                ret = bdrv_pread(bs->file, s->offsets[chunk] + i,
+                                 s->compressed_chunk+i, s->lengths[chunk]-i);
 		if(ret<0 && errno==EINTR)
 		    ret=0;
 		i+=ret;
@@ -239,7 +250,8 @@ static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
 		return -1;
 	    break; }
 	case 1: /* copy */
-	    ret = read(s->fd, s->uncompressed_chunk, s->lengths[chunk]);
+	    ret = bdrv_pread(bs->file, s->offsets[chunk],
+                             s->uncompressed_chunk, s->lengths[chunk]);
 	    if (ret != s->lengths[chunk])
 		return -1;
 	    break;
@@ -260,7 +272,7 @@ static int dmg_read(BlockDriverState *bs, int64_t sector_num,
 
     for(i=0;i<nb_sectors;i++) {
 	uint32_t sector_offset_in_chunk;
-	if(dmg_read_chunk(s, sector_num+i) != 0)
+	if(dmg_read_chunk(bs, sector_num+i) != 0)
 	    return -1;
 	sector_offset_in_chunk = sector_num+i-s->sectors[s->current_chunk];
 	memcpy(buf+i*512,s->uncompressed_chunk+sector_offset_in_chunk*512,512);
@@ -271,7 +283,6 @@ static int dmg_read(BlockDriverState *bs, int64_t sector_num,
 static void dmg_close(BlockDriverState *bs)
 {
     BDRVDMGState *s = bs->opaque;
-    close(s->fd);
     if(s->n_chunks>0) {
 	free(s->types);
 	free(s->offsets);
@@ -288,7 +299,7 @@ static BlockDriver bdrv_dmg = {
     .format_name	= "dmg",
     .instance_size	= sizeof(BDRVDMGState),
     .bdrv_probe		= dmg_probe,
-    .bdrv_file_open	= dmg_open,
+    .bdrv_open		= dmg_open,
     .bdrv_read		= dmg_read,
     .bdrv_close		= dmg_close,
 };
diff --git a/block/parallels.c b/block/parallels.c
index b2171016f1..35a14aa422 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -46,7 +46,6 @@ struct parallels_header {
 } __attribute__((packed));
 
 typedef struct BDRVParallelsState {
-    int fd;
 
     uint32_t *catalog_bitmap;
     int catalog_size;
@@ -68,22 +67,15 @@ static int parallels_probe(const uint8_t *buf, int buf_size, const char *filenam
     return 0;
 }
 
-static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
+static int parallels_open(BlockDriverState *bs, int flags)
 {
     BDRVParallelsState *s = bs->opaque;
-    int fd, i;
+    int i;
     struct parallels_header ph;
 
-    fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
-    if (fd < 0) {
-        return -1;
-    }
-
     bs->read_only = 1; // no write support yet
 
-    s->fd = fd;
-
-    if (read(fd, &ph, sizeof(ph)) != sizeof(ph))
+    if (bdrv_pread(bs->file, 0, &ph, sizeof(ph)) != sizeof(ph))
         goto fail;
 
     if (memcmp(ph.magic, HEADER_MAGIC, 16) ||
@@ -93,14 +85,11 @@ static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
 
     bs->total_sectors = le32_to_cpu(ph.nb_sectors);
 
-    if (lseek(s->fd, 64, SEEK_SET) != 64)
-	goto fail;
-
     s->tracks = le32_to_cpu(ph.tracks);
 
     s->catalog_size = le32_to_cpu(ph.catalog_entries);
     s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
-    if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
+    if (bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4) !=
 	s->catalog_size * 4)
 	goto fail;
     for (i = 0; i < s->catalog_size; i++)
@@ -110,45 +99,34 @@ static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
 fail:
     if (s->catalog_bitmap)
 	qemu_free(s->catalog_bitmap);
-    close(fd);
     return -1;
 }
 
-static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
+static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
 {
     BDRVParallelsState *s = bs->opaque;
     uint32_t index, offset;
-    uint64_t position;
 
     index = sector_num / s->tracks;
     offset = sector_num % s->tracks;
 
-    // not allocated
+    /* not allocated */
     if ((index > s->catalog_size) || (s->catalog_bitmap[index] == 0))
 	return -1;
-
-    position = (uint64_t)(s->catalog_bitmap[index] + offset) * 512;
-
-//    fprintf(stderr, "sector: %llx index=%x offset=%x pointer=%x position=%x\n",
-//	sector_num, index, offset, s->catalog_bitmap[index], position);
-
-    if (lseek(s->fd, position, SEEK_SET) != position)
-	return -1;
-
-    return 0;
+    return (uint64_t)(s->catalog_bitmap[index] + offset) * 512;
 }
 
 static int parallels_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
-    BDRVParallelsState *s = bs->opaque;
-
     while (nb_sectors > 0) {
-	if (!seek_to_sector(bs, sector_num)) {
-	    if (read(s->fd, buf, 512) != 512)
-		return -1;
-	} else
+        int64_t position = seek_to_sector(bs, sector_num);
+        if (position >= 0) {
+            if (bdrv_pread(bs->file, position, buf, 512) != 512)
+                return -1;
+        } else {
             memset(buf, 0, 512);
+        }
         nb_sectors--;
         sector_num++;
         buf += 512;
@@ -160,14 +138,13 @@ static void parallels_close(BlockDriverState *bs)
 {
     BDRVParallelsState *s = bs->opaque;
     qemu_free(s->catalog_bitmap);
-    close(s->fd);
 }
 
 static BlockDriver bdrv_parallels = {
     .format_name	= "parallels",
     .instance_size	= sizeof(BDRVParallelsState),
     .bdrv_probe		= parallels_probe,
-    .bdrv_file_open	= parallels_open,
+    .bdrv_open		= parallels_open,
     .bdrv_read		= parallels_read,
     .bdrv_close		= parallels_close,
 };
diff --git a/block/qcow.c b/block/qcow.c
index 2883c40f87..449858fa47 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -502,7 +502,7 @@ typedef struct QCowAIOCB {
 
 static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    QCowAIOCB *acb = (QCowAIOCB *)blockacb;
+    QCowAIOCB *acb = container_of(blockacb, QCowAIOCB, common);
     if (acb->hd_aiocb)
         bdrv_aio_cancel(acb->hd_aiocb);
     qemu_aio_release(acb);
diff --git a/block/qcow2.c b/block/qcow2.c
index ebad4e10ae..0ce71507e9 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -338,7 +338,7 @@ typedef struct QCowAIOCB {
 
 static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    QCowAIOCB *acb = (QCowAIOCB *)blockacb;
+    QCowAIOCB *acb = container_of(blockacb, QCowAIOCB, common);
     if (acb->hd_aiocb)
         bdrv_aio_cancel(acb->hd_aiocb);
     qemu_aio_release(acb);
diff --git a/block/vdi.c b/block/vdi.c
index 1d257b4838..ee8cc7b1aa 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -393,6 +393,15 @@ static int vdi_open(BlockDriverState *bs, int flags)
     vdi_header_print(&header);
 #endif
 
+    if (header.disk_size % SECTOR_SIZE != 0) {
+        /* 'VBoxManage convertfromraw' can create images with odd disk sizes.
+           We accept them but round the disk size to the next multiple of
+           SECTOR_SIZE. */
+        logout("odd disk size %" PRIu64 " B, round up\n", header.disk_size);
+        header.disk_size += SECTOR_SIZE - 1;
+        header.disk_size &= ~(SECTOR_SIZE - 1);
+    }
+
     if (header.version != VDI_VERSION_1_1) {
         logout("unsupported version %u.%u\n",
                header.version >> 16, header.version & 0xffff);
@@ -405,18 +414,15 @@ static int vdi_open(BlockDriverState *bs, int flags)
         /* We only support data blocks which start on a sector boundary. */
         logout("unsupported data offset 0x%x B\n", header.offset_data);
         goto fail;
-    } else if (header.disk_size % SECTOR_SIZE != 0) {
-        logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);
-        goto fail;
     } else if (header.sector_size != SECTOR_SIZE) {
         logout("unsupported sector size %u B\n", header.sector_size);
         goto fail;
     } else if (header.block_size != 1 * MiB) {
         logout("unsupported block size %u B\n", header.block_size);
         goto fail;
-    } else if ((header.disk_size + header.block_size - 1) / header.block_size !=
-               (uint64_t)header.blocks_in_image) {
-        logout("unexpected block number %u B\n", header.blocks_in_image);
+    } else if (header.disk_size >
+               (uint64_t)header.blocks_in_image * header.block_size) {
+        logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);
         goto fail;
     } else if (!uuid_is_null(header.uuid_link)) {
         logout("link uuid != 0, unsupported\n");
@@ -435,7 +441,9 @@ static int vdi_open(BlockDriverState *bs, int flags)
 
     bmap_size = header.blocks_in_image * sizeof(uint32_t);
     bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
-    s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE);
+    if (bmap_size > 0) {
+        s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE);
+    }
     if (bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) {
         goto fail_free_bmap;
     }
@@ -469,7 +477,7 @@ static int vdi_is_allocated(BlockDriverState *bs, int64_t sector_num,
 static void vdi_aio_cancel(BlockDriverAIOCB *blockacb)
 {
     /* TODO: This code is untested. How can I get it executed? */
-    VdiAIOCB *acb = (VdiAIOCB *)blockacb;
+    VdiAIOCB *acb = container_of(blockacb, VdiAIOCB, common);
     logout("\n");
     if (acb->hd_aiocb) {
         bdrv_aio_cancel(acb->hd_aiocb);
@@ -827,7 +835,10 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
         return -errno;
     }
 
-    blocks = bytes / block_size;
+    /* We need enough blocks to store the given disk size,
+       so always round up. */
+    blocks = (bytes + block_size - 1) / block_size;
+
     bmap_size = blocks * sizeof(uint32_t);
     bmap_size = ((bmap_size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE -1));
 
@@ -857,7 +868,10 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
         result = -errno;
     }
 
-    bmap = (uint32_t *)qemu_mallocz(bmap_size);
+    bmap = NULL;
+    if (bmap_size > 0) {
+        bmap = (uint32_t *)qemu_mallocz(bmap_size);
+    }
     for (i = 0; i < blocks; i++) {
         if (image_type == VDI_TYPE_STATIC) {
             bmap[i] = i;
diff --git a/block/vpc.c b/block/vpc.c
index f94e4698b7..214e9d121f 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -463,9 +463,7 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
         }
     }
 
-    // Note: Rounding up deviates from the Virtual PC behaviour
-    // However, we need this to avoid truncating images in qemu-img convert
-    *cyls = (cyls_times_heads + *heads - 1) / *heads;
+    *cyls = cyls_times_heads / *heads;
 
     return 0;
 }
@@ -477,9 +475,9 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
     struct vhd_dyndisk_header* dyndisk_header =
         (struct vhd_dyndisk_header*) buf;
     int fd, i;
-    uint16_t cyls;
-    uint8_t heads;
-    uint8_t secs_per_cyl;
+    uint16_t cyls = 0;
+    uint8_t heads = 0;
+    uint8_t secs_per_cyl = 0;
     size_t block_size, num_bat_entries;
     int64_t total_sectors = 0;
 
@@ -496,9 +494,14 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
     if (fd < 0)
         return -EIO;
 
-    // Calculate matching total_size and geometry
-    if (calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl))
-        return -EFBIG;
+    /* Calculate matching total_size and geometry. Increase the number of
+       sectors requested until we get enough (or fail). */
+    for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
+        if (calculate_geometry(total_sectors + i,
+                               &cyls, &heads, &secs_per_cyl)) {
+            return -EFBIG;
+        }
+    }
     total_sectors = (int64_t) cyls * heads * secs_per_cyl;
 
     // Prepare the Hard Disk Footer
diff --git a/hw/ide/core.c b/hw/ide/core.c
index b0165bcc02..066fecb0c0 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2838,10 +2838,6 @@ static void ide_dma_restart(IDEState *s, int is_read)
 void ide_dma_cancel(BMDMAState *bm)
 {
     if (bm->status & BM_STATUS_DMAING) {
-        bm->status &= ~BM_STATUS_DMAING;
-        /* cancel DMA request */
-        bm->unit = -1;
-        bm->dma_cb = NULL;
         if (bm->aiocb) {
 #ifdef DEBUG_AIO
             printf("aio_cancel\n");
@@ -2849,6 +2845,10 @@ void ide_dma_cancel(BMDMAState *bm)
             bdrv_aio_cancel(bm->aiocb);
             bm->aiocb = NULL;
         }
+        bm->status &= ~BM_STATUS_DMAING;
+        /* cancel DMA request */
+        bm->unit = -1;
+        bm->dma_cb = NULL;
     }
 }
 
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 25aa913408..4e607cfb61 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -112,9 +112,12 @@ static int find_partition(BlockDriverState *bs, int partition,
     uint8_t data[512];
     int i;
     int ext_partnum = 4;
+    int ret;
 
-    if (bdrv_read(bs, 0, data, 1))
-        errx(EXIT_FAILURE, "error while reading");
+    if ((ret = bdrv_read(bs, 0, data, 1)) < 0) {
+        errno = -ret;
+        err(EXIT_FAILURE, "error while reading");
+    }
 
     if (data[510] != 0x55 || data[511] != 0xaa) {
         errno = -EINVAL;
@@ -132,8 +135,10 @@ static int find_partition(BlockDriverState *bs, int partition,
             uint8_t data1[512];
             int j;
 
-            if (bdrv_read(bs, mbr[i].start_sector_abs, data1, 1))
-                errx(EXIT_FAILURE, "error while reading");
+            if ((ret = bdrv_read(bs, mbr[i].start_sector_abs, data1, 1)) < 0) {
+                errno = -ret;
+                err(EXIT_FAILURE, "error while reading");
+            }
 
             for (j = 0; j < 4; j++) {
                 read_partition(&data1[446 + 16 * j], &ext[j]);
@@ -316,7 +321,7 @@ int main(int argc, char **argv)
     if (disconnect) {
         fd = open(argv[optind], O_RDWR);
         if (fd == -1)
-            errx(EXIT_FAILURE, "Cannot open %s", argv[optind]);
+            err(EXIT_FAILURE, "Cannot open %s", argv[optind]);
 
         nbd_disconnect(fd);
 
@@ -333,23 +338,30 @@ int main(int argc, char **argv)
     if (bs == NULL)
         return 1;
 
-    if (bdrv_open(bs, argv[optind], flags, NULL) < 0)
-        return 1;
+    if ((ret = bdrv_open(bs, argv[optind], flags, NULL)) < 0) {
+        errno = -ret;
+        err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]);
+    }
 
     fd_size = bs->total_sectors * 512;
 
     if (partition != -1 &&
         find_partition(bs, partition, &dev_offset, &fd_size))
-        errx(EXIT_FAILURE, "Could not find partition %d", partition);
+        err(EXIT_FAILURE, "Could not find partition %d", partition);
 
     if (device) {
         pid_t pid;
         int sock;
 
+        /* want to fail before daemonizing */
+        if (access(device, R_OK|W_OK) == -1) {
+            err(EXIT_FAILURE, "Could not access '%s'", device);
+        }
+
         if (!verbose) {
             /* detach client and server */
             if (daemon(0, 0) == -1) {
-                errx(EXIT_FAILURE, "Failed to daemonize");
+                err(EXIT_FAILURE, "Failed to daemonize");
             }
         }
 
@@ -372,8 +384,10 @@ int main(int argc, char **argv)
             do {
                 sock = unix_socket_outgoing(socket);
                 if (sock == -1) {
-                    if (errno != ENOENT && errno != ECONNREFUSED)
+                    if (errno != ENOENT && errno != ECONNREFUSED) {
+                        ret = 1;
                         goto out;
+                    }
                     sleep(1);	/* wait children */
                 }
             } while (sock == -1);