Merge remote branch 'kwolf/for-anthony' into staging

This commit is contained in:
Anthony Liguori 2010-05-17 13:17:34 -05:00
commit 129414184e
13 changed files with 214 additions and 233 deletions

31
block.c
View File

@ -287,16 +287,18 @@ static BlockDriver *find_protocol(const char *filename)
char protocol[128]; char protocol[128];
int len; int len;
const char *p; const char *p;
int is_drive;
/* TODO Drivers without bdrv_file_open must be specified explicitly */ /* TODO Drivers without bdrv_file_open must be specified explicitly */
#ifdef _WIN32 #ifdef _WIN32
if (is_windows_drive(filename) || is_drive = is_windows_drive(filename) ||
is_windows_drive_prefix(filename)) is_windows_drive_prefix(filename);
return bdrv_find_format("file"); #else
is_drive = 0;
#endif #endif
p = strchr(filename, ':'); p = strchr(filename, ':');
if (!p) { if (!p || is_drive) {
drv1 = find_hdev_driver(filename); drv1 = find_hdev_driver(filename);
if (!drv1) { if (!drv1) {
drv1 = bdrv_find_format("file"); drv1 = bdrv_find_format("file");
@ -324,11 +326,6 @@ static BlockDriver *find_image_format(const char *filename)
uint8_t buf[2048]; uint8_t buf[2048];
BlockDriverState *bs; 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); ret = bdrv_file_open(&bs, filename, 0);
if (ret < 0) if (ret < 0)
return NULL; return NULL;
@ -699,12 +696,12 @@ int bdrv_commit(BlockDriverState *bs)
bdrv_delete(bs->backing_hd); bdrv_delete(bs->backing_hd);
bs->backing_hd = NULL; bs->backing_hd = NULL;
bs_rw = bdrv_new(""); 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) { if (rw_ret < 0) {
bdrv_delete(bs_rw); bdrv_delete(bs_rw);
/* try to re-open read-only */ /* try to re-open read-only */
bs_ro = bdrv_new(""); 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) { if (ret < 0) {
bdrv_delete(bs_ro); bdrv_delete(bs_ro);
/* drive not functional anymore */ /* drive not functional anymore */
@ -756,7 +753,7 @@ ro_cleanup:
bdrv_delete(bs->backing_hd); bdrv_delete(bs->backing_hd);
bs->backing_hd = NULL; bs->backing_hd = NULL;
bs_ro = bdrv_new(""); 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) { if (ret < 0) {
bdrv_delete(bs_ro); bdrv_delete(bs_ro);
/* drive not functional anymore */ /* drive not functional anymore */
@ -1580,7 +1577,7 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
* - "wr_operations": write operations * - "wr_operations": write operations
* - "wr_highest_offset": Highest offset of a sector written since the * - "wr_highest_offset": Highest offset of a sector written since the
* BlockDriverState has been opened * BlockDriverState has been opened
* - "parent": Contains recursively the statistics of the underlying * - "parent": A QDict recursively holding the statistics of the underlying
* protocol (e.g. the host file for a qcow2 image). If there is no * protocol (e.g. the host file for a qcow2 image). If there is no
* underlying protocol, this field is omitted. * underlying protocol, this field is omitted.
* *
@ -1591,14 +1588,13 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
* "wr_bytes": 0, * "wr_bytes": 0,
* "rd_operations": 1, * "rd_operations": 1,
* "wr_operations": 0, * "wr_operations": 0,
* "wr_highest_offset": 0, * "wr_highest_offset": 0 },
* "parent": { * "parent": {
* "stats": { "rd_bytes": 1024, * "stats": { "rd_bytes": 1024,
* "wr_bytes": 0, * "wr_bytes": 0,
* "rd_operations": 2, * "rd_operations": 2,
* "wr_operations": 0, * "wr_operations": 0,
* "wr_highest_offset": 0, * "wr_highest_offset": 0,
* }
* } } }, * } } },
* { "device": "ide1-cd0", * { "device": "ide1-cd0",
* "stats": { "rd_bytes": 0, * "stats": { "rd_bytes": 0,
@ -2073,7 +2069,7 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
return 0; return 0;
fail: fail:
free(mcb); qemu_free(mcb);
return -1; return -1;
} }
@ -2108,7 +2104,8 @@ typedef struct BlockDriverAIOCBSync {
static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb) static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
{ {
BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb; BlockDriverAIOCBSync *acb =
container_of(blockacb, BlockDriverAIOCBSync, common);
qemu_bh_delete(acb->bh); qemu_bh_delete(acb->bh);
acb->bh = NULL; acb->bh = NULL;
qemu_aio_release(acb); qemu_aio_release(acb);

View File

@ -38,7 +38,7 @@ typedef struct QEMUSnapshotInfo {
#define BDRV_SECTOR_BITS 9 #define BDRV_SECTOR_BITS 9
#define BDRV_SECTOR_SIZE (1 << BDRV_SECTOR_BITS) #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 { typedef enum {
BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP

View File

@ -320,7 +320,7 @@ static void error_callback_bh(void *opaque)
static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb) static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
{ {
BlkdebugAIOCB *acb = (BlkdebugAIOCB*) blockacb; BlkdebugAIOCB *acb = container_of(blockacb, BlkdebugAIOCB, common);
qemu_aio_release(acb); qemu_aio_release(acb);
} }
@ -347,7 +347,7 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
acb->bh = bh; acb->bh = bh;
qemu_bh_schedule(bh); qemu_bh_schedule(bh);
return (BlockDriverAIOCB*) acb; return &acb->common;
} }
static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs, static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,

View File

@ -80,8 +80,6 @@ struct bochs_header {
}; };
typedef struct BDRVBochsState { typedef struct BDRVBochsState {
int fd;
uint32_t *catalog_bitmap; uint32_t *catalog_bitmap;
int catalog_size; int catalog_size;
@ -109,23 +107,16 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
return 0; 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; BDRVBochsState *s = bs->opaque;
int fd, i; int i;
struct bochs_header bochs; struct bochs_header bochs;
struct bochs_header_v1 header_v1; 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 bs->read_only = 1; // no write support yet
s->fd = fd; if (bdrv_pread(bs->file, 0, &bochs, sizeof(bochs)) != sizeof(bochs)) {
if (read(fd, &bochs, sizeof(bochs)) != sizeof(bochs)) {
goto fail; 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; 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_size = le32_to_cpu(bochs.extra.redolog.catalog);
s->catalog_bitmap = qemu_malloc(s->catalog_size * 4); 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, le32_to_cpu(bochs.header), s->catalog_bitmap,
s->catalog_size * 4) s->catalog_size * 4) != s->catalog_size * 4)
goto fail; goto fail;
for (i = 0; i < s->catalog_size; i++) for (i = 0; i < s->catalog_size; i++)
le32_to_cpus(&s->catalog_bitmap[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; return 0;
fail: fail:
close(fd);
return -1; 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; BDRVBochsState *s = bs->opaque;
int64_t offset = sector_num * 512; 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; char bitmap_entry;
// seek to sector // seek to sector
extent_index = offset / s->extent_size; extent_index = offset / s->extent_size;
extent_offset = (offset % s->extent_size) / 512; extent_offset = (offset % s->extent_size) / 512;
if (s->catalog_bitmap[extent_index] == 0xffffffff) if (s->catalog_bitmap[extent_index] == 0xffffffff) {
{ return -1; /* not allocated */
// fprintf(stderr, "page not allocated [%x - %x:%x]\n",
// sector_num, extent_index, extent_offset);
return -1; // not allocated
} }
bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] * bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *
(s->extent_blocks + s->bitmap_blocks)); (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", /* read in bitmap for current extent */
// sector_num, extent_index, extent_offset, if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
// le32_to_cpu(s->catalog_bitmap[extent_index]), &bitmap_entry, 1) != 1) {
// 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; return -1;
} }
if (read(s->fd, &bitmap_entry, 1) != 1) if (!((bitmap_entry >> (extent_offset % 8)) & 1)) {
return -1; return -1; /* not allocated */
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 bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
return -1;
}
return 0;
} }
static int bochs_read(BlockDriverState *bs, int64_t sector_num, static int bochs_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors) uint8_t *buf, int nb_sectors)
{ {
BDRVBochsState *s = bs->opaque;
int ret; int ret;
while (nb_sectors > 0) { while (nb_sectors > 0) {
if (!seek_to_sector(bs, sector_num)) int64_t block_offset = seek_to_sector(bs, sector_num);
{ if (block_offset >= 0) {
ret = read(s->fd, buf, 512); ret = bdrv_pread(bs->file, block_offset, buf, 512);
if (ret != 512) if (ret != 512) {
return -1; return -1;
} }
else } else
memset(buf, 0, 512); memset(buf, 0, 512);
nb_sectors--; nb_sectors--;
sector_num++; sector_num++;
@ -245,14 +211,13 @@ static void bochs_close(BlockDriverState *bs)
{ {
BDRVBochsState *s = bs->opaque; BDRVBochsState *s = bs->opaque;
qemu_free(s->catalog_bitmap); qemu_free(s->catalog_bitmap);
close(s->fd);
} }
static BlockDriver bdrv_bochs = { static BlockDriver bdrv_bochs = {
.format_name = "bochs", .format_name = "bochs",
.instance_size = sizeof(BDRVBochsState), .instance_size = sizeof(BDRVBochsState),
.bdrv_probe = bochs_probe, .bdrv_probe = bochs_probe,
.bdrv_file_open = bochs_open, .bdrv_open = bochs_open,
.bdrv_read = bochs_read, .bdrv_read = bochs_read,
.bdrv_close = bochs_close, .bdrv_close = bochs_close,
}; };

View File

@ -27,7 +27,6 @@
#include <zlib.h> #include <zlib.h>
typedef struct BDRVCloopState { typedef struct BDRVCloopState {
int fd;
uint32_t block_size; uint32_t block_size;
uint32_t n_blocks; uint32_t n_blocks;
uint64_t* offsets; uint64_t* offsets;
@ -51,34 +50,31 @@ static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
return 0; 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; BDRVCloopState *s = bs->opaque;
uint32_t offsets_size,max_compressed_block_size=1,i; 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; bs->read_only = 1;
/* read header */ /* read header */
if(lseek(s->fd,128,SEEK_SET)<0) { if (bdrv_pread(bs->file, 128, &s->block_size, 4) < 4) {
cloop_close: goto cloop_close;
close(s->fd);
return -1;
} }
if(read(s->fd,&s->block_size,4)<4)
goto cloop_close;
s->block_size = be32_to_cpu(s->block_size); s->block_size = be32_to_cpu(s->block_size);
if(read(s->fd,&s->n_blocks,4)<4)
if (bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4) < 4) {
goto cloop_close; goto cloop_close;
}
s->n_blocks = be32_to_cpu(s->n_blocks); s->n_blocks = be32_to_cpu(s->n_blocks);
/* read offsets */ /* read offsets */
offsets_size = s->n_blocks * sizeof(uint64_t); offsets_size = s->n_blocks * sizeof(uint64_t);
s->offsets=(uint64_t*)qemu_malloc(offsets_size); s->offsets = qemu_malloc(offsets_size);
if(read(s->fd,s->offsets,offsets_size)<offsets_size) if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) <
offsets_size) {
goto cloop_close; goto cloop_close;
}
for(i=0;i<s->n_blocks;i++) { for(i=0;i<s->n_blocks;i++) {
s->offsets[i]=be64_to_cpu(s->offsets[i]); s->offsets[i]=be64_to_cpu(s->offsets[i]);
if(i>0) { if(i>0) {
@ -98,16 +94,21 @@ cloop_close:
s->sectors_per_block = s->block_size/512; s->sectors_per_block = s->block_size/512;
bs->total_sectors = s->n_blocks*s->sectors_per_block; bs->total_sectors = s->n_blocks*s->sectors_per_block;
return 0; 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) { if(s->current_block != block_num) {
int ret; int ret;
uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num]; uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
lseek(s->fd, s->offsets[block_num], SEEK_SET); ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
ret = read(s->fd, s->compressed_block, bytes); bytes);
if (ret != bytes) if (ret != bytes)
return -1; return -1;
@ -136,7 +137,7 @@ static int cloop_read(BlockDriverState *bs, int64_t sector_num,
for(i=0;i<nb_sectors;i++) { for(i=0;i<nb_sectors;i++) {
uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block), uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
block_num=(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; return -1;
memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512); 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) static void cloop_close(BlockDriverState *bs)
{ {
BDRVCloopState *s = bs->opaque; BDRVCloopState *s = bs->opaque;
close(s->fd);
if(s->n_blocks>0) if(s->n_blocks>0)
free(s->offsets); free(s->offsets);
free(s->compressed_block); free(s->compressed_block);
@ -158,7 +158,7 @@ static BlockDriver bdrv_cloop = {
.format_name = "cloop", .format_name = "cloop",
.instance_size = sizeof(BDRVCloopState), .instance_size = sizeof(BDRVCloopState),
.bdrv_probe = cloop_probe, .bdrv_probe = cloop_probe,
.bdrv_file_open = cloop_open, .bdrv_open = cloop_open,
.bdrv_read = cloop_read, .bdrv_read = cloop_read,
.bdrv_close = cloop_close, .bdrv_close = cloop_close,
}; };

View File

@ -28,8 +28,6 @@
#include <zlib.h> #include <zlib.h>
typedef struct BDRVDMGState { typedef struct BDRVDMGState {
int fd;
/* each chunk contains a certain number of sectors, /* each chunk contains a certain number of sectors,
* offsets[i] is the offset in the .dmg file, * offsets[i] is the offset in the .dmg file,
* lengths[i] is the length of the compressed chunk, * 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; return 0;
} }
static off_t read_off(int fd) static off_t read_off(BlockDriverState *bs, int64_t offset)
{ {
uint64_t buffer; uint64_t buffer;
if(read(fd,&buffer,8)<8) if (bdrv_pread(bs->file, offset, &buffer, 8) < 8)
return 0; return 0;
return be64_to_cpu(buffer); 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; uint32_t buffer;
if(read(fd,&buffer,4)<4) if (bdrv_pread(bs->file, offset, &buffer, 4) < 4)
return 0; return 0;
return be32_to_cpu(buffer); 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; BDRVDMGState *s = bs->opaque;
off_t info_begin,info_end,last_in_offset,last_out_offset; off_t info_begin,info_end,last_in_offset,last_out_offset;
uint32_t count; uint32_t count;
uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i; 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; bs->read_only = 1;
s->n_chunks = 0; s->n_chunks = 0;
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL; s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
/* read offset of info blocks */ /* 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(bs, offset);
if (info_begin == 0) {
goto fail; goto fail;
} }
info_begin=read_off(s->fd); if (read_uint32(bs, info_begin) != 0x100) {
if(info_begin==0)
goto fail; goto fail;
if(lseek(s->fd,info_begin,SEEK_SET)<0) }
goto fail;
if(read_uint32(s->fd)!=0x100) count = read_uint32(bs, info_begin + 4);
goto fail; if (count == 0) {
if((count = read_uint32(s->fd))==0)
goto fail; goto fail;
}
info_end = info_begin + count; info_end = info_begin + count;
if(lseek(s->fd,0xf8,SEEK_CUR)<0)
goto fail; offset = info_begin + 0x100;
/* read offsets */ /* read offsets */
last_in_offset = last_out_offset = 0; last_in_offset = last_out_offset = 0;
while(lseek(s->fd,0,SEEK_CUR)<info_end) { while (offset < info_end) {
uint32_t type; uint32_t type;
count = read_uint32(s->fd); count = read_uint32(bs, offset);
if(count==0) if(count==0)
goto fail; goto fail;
type = read_uint32(s->fd); offset += 4;
if(type!=0x6d697368 || count<244)
lseek(s->fd,count-4,SEEK_CUR); type = read_uint32(bs, offset);
else { if (type == 0x6d697368 && count >= 244) {
int new_size, chunk_count; int new_size, chunk_count;
if(lseek(s->fd,200,SEEK_CUR)<0)
goto fail; offset += 4;
offset += 200;
chunk_count = (count-204)/40; chunk_count = (count-204)/40;
new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count); new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
s->types = qemu_realloc(s->types, new_size/2); 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); s->sectorcounts = qemu_realloc(s->sectorcounts, new_size);
for(i=s->n_chunks;i<s->n_chunks+chunk_count;i++) { 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]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) {
if(s->types[i]==0xffffffff) { if(s->types[i]==0xffffffff) {
last_in_offset = s->offsets[i-1]+s->lengths[i-1]; 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--; chunk_count--;
i--; i--;
if(lseek(s->fd,36,SEEK_CUR)<0) offset += 36;
goto fail;
continue; continue;
} }
read_uint32(s->fd); offset += 4;
s->sectors[i] = last_out_offset+read_off(s->fd);
s->sectorcounts[i] = read_off(s->fd); s->sectors[i] = last_out_offset+read_off(bs, offset);
s->offsets[i] = last_in_offset+read_off(s->fd); offset += 8;
s->lengths[i] = read_off(s->fd);
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) if(s->lengths[i]>max_compressed_size)
max_compressed_size = s->lengths[i]; max_compressed_size = s->lengths[i];
if(s->sectorcounts[i]>max_sectors_per_chunk) 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; return 0;
fail: fail:
close(s->fd);
return -1; return -1;
} }
@ -196,8 +208,10 @@ static inline uint32_t search_chunk(BDRVDMGState* s,int sector_num)
return s->n_chunks; /* error */ 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)) { if(!is_sector_in_chunk(s,s->current_chunk,sector_num)) {
int ret; int ret;
uint32_t chunk = search_chunk(s,sector_num); 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 */ case 0x80000005: { /* zlib compressed */
int i; 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 /* we need to buffer, because only the chunk as whole can be
* inflated. */ * inflated. */
i=0; i=0;
do { 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) if(ret<0 && errno==EINTR)
ret=0; ret=0;
i+=ret; i+=ret;
@ -239,7 +250,8 @@ static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
return -1; return -1;
break; } break; }
case 1: /* copy */ 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]) if (ret != s->lengths[chunk])
return -1; return -1;
break; break;
@ -260,7 +272,7 @@ static int dmg_read(BlockDriverState *bs, int64_t sector_num,
for(i=0;i<nb_sectors;i++) { for(i=0;i<nb_sectors;i++) {
uint32_t sector_offset_in_chunk; 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; return -1;
sector_offset_in_chunk = sector_num+i-s->sectors[s->current_chunk]; 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); 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) static void dmg_close(BlockDriverState *bs)
{ {
BDRVDMGState *s = bs->opaque; BDRVDMGState *s = bs->opaque;
close(s->fd);
if(s->n_chunks>0) { if(s->n_chunks>0) {
free(s->types); free(s->types);
free(s->offsets); free(s->offsets);
@ -288,7 +299,7 @@ static BlockDriver bdrv_dmg = {
.format_name = "dmg", .format_name = "dmg",
.instance_size = sizeof(BDRVDMGState), .instance_size = sizeof(BDRVDMGState),
.bdrv_probe = dmg_probe, .bdrv_probe = dmg_probe,
.bdrv_file_open = dmg_open, .bdrv_open = dmg_open,
.bdrv_read = dmg_read, .bdrv_read = dmg_read,
.bdrv_close = dmg_close, .bdrv_close = dmg_close,
}; };

View File

@ -46,7 +46,6 @@ struct parallels_header {
} __attribute__((packed)); } __attribute__((packed));
typedef struct BDRVParallelsState { typedef struct BDRVParallelsState {
int fd;
uint32_t *catalog_bitmap; uint32_t *catalog_bitmap;
int catalog_size; int catalog_size;
@ -68,22 +67,15 @@ static int parallels_probe(const uint8_t *buf, int buf_size, const char *filenam
return 0; 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; BDRVParallelsState *s = bs->opaque;
int fd, i; int i;
struct parallels_header ph; 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 bs->read_only = 1; // no write support yet
s->fd = fd; if (bdrv_pread(bs->file, 0, &ph, sizeof(ph)) != sizeof(ph))
if (read(fd, &ph, sizeof(ph)) != sizeof(ph))
goto fail; goto fail;
if (memcmp(ph.magic, HEADER_MAGIC, 16) || 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); 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->tracks = le32_to_cpu(ph.tracks);
s->catalog_size = le32_to_cpu(ph.catalog_entries); s->catalog_size = le32_to_cpu(ph.catalog_entries);
s->catalog_bitmap = qemu_malloc(s->catalog_size * 4); 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) s->catalog_size * 4)
goto fail; goto fail;
for (i = 0; i < s->catalog_size; i++) for (i = 0; i < s->catalog_size; i++)
@ -110,45 +99,34 @@ static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
fail: fail:
if (s->catalog_bitmap) if (s->catalog_bitmap)
qemu_free(s->catalog_bitmap); qemu_free(s->catalog_bitmap);
close(fd);
return -1; 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; BDRVParallelsState *s = bs->opaque;
uint32_t index, offset; uint32_t index, offset;
uint64_t position;
index = sector_num / s->tracks; index = sector_num / s->tracks;
offset = sector_num % s->tracks; offset = sector_num % s->tracks;
// not allocated /* not allocated */
if ((index > s->catalog_size) || (s->catalog_bitmap[index] == 0)) if ((index > s->catalog_size) || (s->catalog_bitmap[index] == 0))
return -1; return -1;
return (uint64_t)(s->catalog_bitmap[index] + offset) * 512;
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;
} }
static int parallels_read(BlockDriverState *bs, int64_t sector_num, static int parallels_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors) uint8_t *buf, int nb_sectors)
{ {
BDRVParallelsState *s = bs->opaque;
while (nb_sectors > 0) { while (nb_sectors > 0) {
if (!seek_to_sector(bs, sector_num)) { int64_t position = seek_to_sector(bs, sector_num);
if (read(s->fd, buf, 512) != 512) if (position >= 0) {
if (bdrv_pread(bs->file, position, buf, 512) != 512)
return -1; return -1;
} else } else {
memset(buf, 0, 512); memset(buf, 0, 512);
}
nb_sectors--; nb_sectors--;
sector_num++; sector_num++;
buf += 512; buf += 512;
@ -160,14 +138,13 @@ static void parallels_close(BlockDriverState *bs)
{ {
BDRVParallelsState *s = bs->opaque; BDRVParallelsState *s = bs->opaque;
qemu_free(s->catalog_bitmap); qemu_free(s->catalog_bitmap);
close(s->fd);
} }
static BlockDriver bdrv_parallels = { static BlockDriver bdrv_parallels = {
.format_name = "parallels", .format_name = "parallels",
.instance_size = sizeof(BDRVParallelsState), .instance_size = sizeof(BDRVParallelsState),
.bdrv_probe = parallels_probe, .bdrv_probe = parallels_probe,
.bdrv_file_open = parallels_open, .bdrv_open = parallels_open,
.bdrv_read = parallels_read, .bdrv_read = parallels_read,
.bdrv_close = parallels_close, .bdrv_close = parallels_close,
}; };

View File

@ -502,7 +502,7 @@ typedef struct QCowAIOCB {
static void qcow_aio_cancel(BlockDriverAIOCB *blockacb) static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
{ {
QCowAIOCB *acb = (QCowAIOCB *)blockacb; QCowAIOCB *acb = container_of(blockacb, QCowAIOCB, common);
if (acb->hd_aiocb) if (acb->hd_aiocb)
bdrv_aio_cancel(acb->hd_aiocb); bdrv_aio_cancel(acb->hd_aiocb);
qemu_aio_release(acb); qemu_aio_release(acb);

View File

@ -338,7 +338,7 @@ typedef struct QCowAIOCB {
static void qcow_aio_cancel(BlockDriverAIOCB *blockacb) static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
{ {
QCowAIOCB *acb = (QCowAIOCB *)blockacb; QCowAIOCB *acb = container_of(blockacb, QCowAIOCB, common);
if (acb->hd_aiocb) if (acb->hd_aiocb)
bdrv_aio_cancel(acb->hd_aiocb); bdrv_aio_cancel(acb->hd_aiocb);
qemu_aio_release(acb); qemu_aio_release(acb);

View File

@ -393,6 +393,15 @@ static int vdi_open(BlockDriverState *bs, int flags)
vdi_header_print(&header); vdi_header_print(&header);
#endif #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) { if (header.version != VDI_VERSION_1_1) {
logout("unsupported version %u.%u\n", logout("unsupported version %u.%u\n",
header.version >> 16, header.version & 0xffff); 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. */ /* We only support data blocks which start on a sector boundary. */
logout("unsupported data offset 0x%x B\n", header.offset_data); logout("unsupported data offset 0x%x B\n", header.offset_data);
goto fail; 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) { } else if (header.sector_size != SECTOR_SIZE) {
logout("unsupported sector size %u B\n", header.sector_size); logout("unsupported sector size %u B\n", header.sector_size);
goto fail; goto fail;
} else if (header.block_size != 1 * MiB) { } else if (header.block_size != 1 * MiB) {
logout("unsupported block size %u B\n", header.block_size); logout("unsupported block size %u B\n", header.block_size);
goto fail; goto fail;
} else if ((header.disk_size + header.block_size - 1) / header.block_size != } else if (header.disk_size >
(uint64_t)header.blocks_in_image) { (uint64_t)header.blocks_in_image * header.block_size) {
logout("unexpected block number %u B\n", header.blocks_in_image); logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);
goto fail; goto fail;
} else if (!uuid_is_null(header.uuid_link)) { } else if (!uuid_is_null(header.uuid_link)) {
logout("link uuid != 0, unsupported\n"); 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 = header.blocks_in_image * sizeof(uint32_t);
bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE; bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
if (bmap_size > 0) {
s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE); s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE);
}
if (bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) { if (bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) {
goto fail_free_bmap; 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) static void vdi_aio_cancel(BlockDriverAIOCB *blockacb)
{ {
/* TODO: This code is untested. How can I get it executed? */ /* TODO: This code is untested. How can I get it executed? */
VdiAIOCB *acb = (VdiAIOCB *)blockacb; VdiAIOCB *acb = container_of(blockacb, VdiAIOCB, common);
logout("\n"); logout("\n");
if (acb->hd_aiocb) { if (acb->hd_aiocb) {
bdrv_aio_cancel(acb->hd_aiocb); bdrv_aio_cancel(acb->hd_aiocb);
@ -827,7 +835,10 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
return -errno; 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 = blocks * sizeof(uint32_t);
bmap_size = ((bmap_size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE -1)); 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; result = -errno;
} }
bmap = NULL;
if (bmap_size > 0) {
bmap = (uint32_t *)qemu_mallocz(bmap_size); bmap = (uint32_t *)qemu_mallocz(bmap_size);
}
for (i = 0; i < blocks; i++) { for (i = 0; i < blocks; i++) {
if (image_type == VDI_TYPE_STATIC) { if (image_type == VDI_TYPE_STATIC) {
bmap[i] = i; bmap[i] = i;

View File

@ -463,9 +463,7 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
} }
} }
// Note: Rounding up deviates from the Virtual PC behaviour *cyls = cyls_times_heads / *heads;
// However, we need this to avoid truncating images in qemu-img convert
*cyls = (cyls_times_heads + *heads - 1) / *heads;
return 0; 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* dyndisk_header =
(struct vhd_dyndisk_header*) buf; (struct vhd_dyndisk_header*) buf;
int fd, i; int fd, i;
uint16_t cyls; uint16_t cyls = 0;
uint8_t heads; uint8_t heads = 0;
uint8_t secs_per_cyl; uint8_t secs_per_cyl = 0;
size_t block_size, num_bat_entries; size_t block_size, num_bat_entries;
int64_t total_sectors = 0; int64_t total_sectors = 0;
@ -496,9 +494,14 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
if (fd < 0) if (fd < 0)
return -EIO; return -EIO;
// Calculate matching total_size and geometry /* Calculate matching total_size and geometry. Increase the number of
if (calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl)) 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; return -EFBIG;
}
}
total_sectors = (int64_t) cyls * heads * secs_per_cyl; total_sectors = (int64_t) cyls * heads * secs_per_cyl;
// Prepare the Hard Disk Footer // Prepare the Hard Disk Footer

View File

@ -2838,10 +2838,6 @@ static void ide_dma_restart(IDEState *s, int is_read)
void ide_dma_cancel(BMDMAState *bm) void ide_dma_cancel(BMDMAState *bm)
{ {
if (bm->status & BM_STATUS_DMAING) { if (bm->status & BM_STATUS_DMAING) {
bm->status &= ~BM_STATUS_DMAING;
/* cancel DMA request */
bm->unit = -1;
bm->dma_cb = NULL;
if (bm->aiocb) { if (bm->aiocb) {
#ifdef DEBUG_AIO #ifdef DEBUG_AIO
printf("aio_cancel\n"); printf("aio_cancel\n");
@ -2849,6 +2845,10 @@ void ide_dma_cancel(BMDMAState *bm)
bdrv_aio_cancel(bm->aiocb); bdrv_aio_cancel(bm->aiocb);
bm->aiocb = NULL; bm->aiocb = NULL;
} }
bm->status &= ~BM_STATUS_DMAING;
/* cancel DMA request */
bm->unit = -1;
bm->dma_cb = NULL;
} }
} }

View File

@ -112,9 +112,12 @@ static int find_partition(BlockDriverState *bs, int partition,
uint8_t data[512]; uint8_t data[512];
int i; int i;
int ext_partnum = 4; int ext_partnum = 4;
int ret;
if (bdrv_read(bs, 0, data, 1)) if ((ret = bdrv_read(bs, 0, data, 1)) < 0) {
errx(EXIT_FAILURE, "error while reading"); errno = -ret;
err(EXIT_FAILURE, "error while reading");
}
if (data[510] != 0x55 || data[511] != 0xaa) { if (data[510] != 0x55 || data[511] != 0xaa) {
errno = -EINVAL; errno = -EINVAL;
@ -132,8 +135,10 @@ static int find_partition(BlockDriverState *bs, int partition,
uint8_t data1[512]; uint8_t data1[512];
int j; int j;
if (bdrv_read(bs, mbr[i].start_sector_abs, data1, 1)) if ((ret = bdrv_read(bs, mbr[i].start_sector_abs, data1, 1)) < 0) {
errx(EXIT_FAILURE, "error while reading"); errno = -ret;
err(EXIT_FAILURE, "error while reading");
}
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++) {
read_partition(&data1[446 + 16 * j], &ext[j]); read_partition(&data1[446 + 16 * j], &ext[j]);
@ -316,7 +321,7 @@ int main(int argc, char **argv)
if (disconnect) { if (disconnect) {
fd = open(argv[optind], O_RDWR); fd = open(argv[optind], O_RDWR);
if (fd == -1) if (fd == -1)
errx(EXIT_FAILURE, "Cannot open %s", argv[optind]); err(EXIT_FAILURE, "Cannot open %s", argv[optind]);
nbd_disconnect(fd); nbd_disconnect(fd);
@ -333,23 +338,30 @@ int main(int argc, char **argv)
if (bs == NULL) if (bs == NULL)
return 1; return 1;
if (bdrv_open(bs, argv[optind], flags, NULL) < 0) if ((ret = bdrv_open(bs, argv[optind], flags, NULL)) < 0) {
return 1; errno = -ret;
err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]);
}
fd_size = bs->total_sectors * 512; fd_size = bs->total_sectors * 512;
if (partition != -1 && if (partition != -1 &&
find_partition(bs, partition, &dev_offset, &fd_size)) 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) { if (device) {
pid_t pid; pid_t pid;
int sock; 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) { if (!verbose) {
/* detach client and server */ /* detach client and server */
if (daemon(0, 0) == -1) { 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 { do {
sock = unix_socket_outgoing(socket); sock = unix_socket_outgoing(socket);
if (sock == -1) { if (sock == -1) {
if (errno != ENOENT && errno != ECONNREFUSED) if (errno != ENOENT && errno != ECONNREFUSED) {
ret = 1;
goto out; goto out;
}
sleep(1); /* wait children */ sleep(1); /* wait children */
} }
} while (sock == -1); } while (sock == -1);