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

49
block.c
View File

@ -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);

View File

@ -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

View File

@ -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,

View File

@ -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) {
/* read in bitmap for current extent */
if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
&bitmap_entry, 1) != 1) {
return -1;
}
if (read(s->fd, &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 (!((bitmap_entry >> (extent_offset % 8)) & 1)) {
return -1; /* not allocated */
}
if (lseek(s->fd, block_offset, SEEK_SET) == (off_t)-1) {
return -1;
}
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,
};

View File

@ -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,
};

View File

@ -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(bs, offset);
if (info_begin == 0) {
goto fail;
}
if (read_uint32(bs, info_begin) != 0x100) {
goto fail;
}
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)
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,
};

View File

@ -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,
};

View File

@ -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);

View File

@ -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);

View File

@ -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;

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
// 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

View File

@ -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;
}
}

View File

@ -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);