Merge remote branch 'kwolf/for-anthony' into staging
This commit is contained in:
commit
129414184e
49
block.c
49
block.c
@ -287,16 +287,18 @@ static BlockDriver *find_protocol(const char *filename)
|
||||
char protocol[128];
|
||||
int len;
|
||||
const char *p;
|
||||
int is_drive;
|
||||
|
||||
/* TODO Drivers without bdrv_file_open must be specified explicitly */
|
||||
|
||||
#ifdef _WIN32
|
||||
if (is_windows_drive(filename) ||
|
||||
is_windows_drive_prefix(filename))
|
||||
return bdrv_find_format("file");
|
||||
is_drive = is_windows_drive(filename) ||
|
||||
is_windows_drive_prefix(filename);
|
||||
#else
|
||||
is_drive = 0;
|
||||
#endif
|
||||
p = strchr(filename, ':');
|
||||
if (!p) {
|
||||
if (!p || is_drive) {
|
||||
drv1 = find_hdev_driver(filename);
|
||||
if (!drv1) {
|
||||
drv1 = bdrv_find_format("file");
|
||||
@ -324,11 +326,6 @@ static BlockDriver *find_image_format(const char *filename)
|
||||
uint8_t buf[2048];
|
||||
BlockDriverState *bs;
|
||||
|
||||
drv = find_protocol(filename);
|
||||
/* no need to test disk image formats for vvfat */
|
||||
if (drv && strcmp(drv->format_name, "vvfat") == 0)
|
||||
return drv;
|
||||
|
||||
ret = bdrv_file_open(&bs, filename, 0);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
@ -699,12 +696,12 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
bdrv_delete(bs->backing_hd);
|
||||
bs->backing_hd = NULL;
|
||||
bs_rw = bdrv_new("");
|
||||
rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, NULL);
|
||||
rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, drv);
|
||||
if (rw_ret < 0) {
|
||||
bdrv_delete(bs_rw);
|
||||
/* try to re-open read-only */
|
||||
bs_ro = bdrv_new("");
|
||||
ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
|
||||
ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
|
||||
if (ret < 0) {
|
||||
bdrv_delete(bs_ro);
|
||||
/* drive not functional anymore */
|
||||
@ -756,7 +753,7 @@ ro_cleanup:
|
||||
bdrv_delete(bs->backing_hd);
|
||||
bs->backing_hd = NULL;
|
||||
bs_ro = bdrv_new("");
|
||||
ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
|
||||
ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
|
||||
if (ret < 0) {
|
||||
bdrv_delete(bs_ro);
|
||||
/* drive not functional anymore */
|
||||
@ -1580,9 +1577,9 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
|
||||
* - "wr_operations": write operations
|
||||
* - "wr_highest_offset": Highest offset of a sector written since the
|
||||
* BlockDriverState has been opened
|
||||
* - "parent": Contains recursively the statistics of the underlying
|
||||
* protocol (e.g. the host file for a qcow2 image). If there is no
|
||||
* underlying protocol, this field is omitted.
|
||||
* - "parent": A QDict recursively holding the statistics of the underlying
|
||||
* protocol (e.g. the host file for a qcow2 image). If there is no
|
||||
* underlying protocol, this field is omitted.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
@ -1591,15 +1588,14 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
|
||||
* "wr_bytes": 0,
|
||||
* "rd_operations": 1,
|
||||
* "wr_operations": 0,
|
||||
* "wr_highest_offset": 0,
|
||||
* "parent": {
|
||||
* "stats": { "rd_bytes": 1024,
|
||||
* "wr_bytes": 0,
|
||||
* "rd_operations": 2,
|
||||
* "wr_operations": 0,
|
||||
* "wr_highest_offset": 0,
|
||||
* }
|
||||
* } } },
|
||||
* "wr_highest_offset": 0 },
|
||||
* "parent": {
|
||||
* "stats": { "rd_bytes": 1024,
|
||||
* "wr_bytes": 0,
|
||||
* "rd_operations": 2,
|
||||
* "wr_operations": 0,
|
||||
* "wr_highest_offset": 0,
|
||||
* } } },
|
||||
* { "device": "ide1-cd0",
|
||||
* "stats": { "rd_bytes": 0,
|
||||
* "wr_bytes": 0,
|
||||
@ -2073,7 +2069,7 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
free(mcb);
|
||||
qemu_free(mcb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -2108,7 +2104,8 @@ typedef struct BlockDriverAIOCBSync {
|
||||
|
||||
static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
|
||||
{
|
||||
BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
|
||||
BlockDriverAIOCBSync *acb =
|
||||
container_of(blockacb, BlockDriverAIOCBSync, common);
|
||||
qemu_bh_delete(acb->bh);
|
||||
acb->bh = NULL;
|
||||
qemu_aio_release(acb);
|
||||
|
2
block.h
2
block.h
@ -38,7 +38,7 @@ typedef struct QEMUSnapshotInfo {
|
||||
|
||||
#define BDRV_SECTOR_BITS 9
|
||||
#define BDRV_SECTOR_SIZE (1 << BDRV_SECTOR_BITS)
|
||||
#define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1);
|
||||
#define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1)
|
||||
|
||||
typedef enum {
|
||||
BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
111
block/dmg.c
111
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(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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
34
block/vdi.c
34
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;
|
||||
|
21
block/vpc.c
21
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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
34
qemu-nbd.c
34
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);
|
||||
|
Loading…
Reference in New Issue
Block a user