diff options
-rw-r--r-- | block.c | 49 | ||||
-rw-r--r-- | block.h | 2 | ||||
-rw-r--r-- | block/blkdebug.c | 4 | ||||
-rw-r--r-- | block/bochs.c | 81 | ||||
-rw-r--r-- | block/cloop.c | 48 | ||||
-rw-r--r-- | block/dmg.c | 109 | ||||
-rw-r--r-- | block/parallels.c | 51 | ||||
-rw-r--r-- | block/qcow.c | 2 | ||||
-rw-r--r-- | block/qcow2.c | 2 | ||||
-rw-r--r-- | block/vdi.c | 34 | ||||
-rw-r--r-- | block/vpc.c | 21 | ||||
-rw-r--r-- | hw/ide/core.c | 8 | ||||
-rw-r--r-- | qemu-nbd.c | 34 |
13 files changed, 213 insertions, 232 deletions
@@ -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); @@ -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); |