Compare commits
19 Commits
factory
...
v0.13.0-rc
Author | SHA1 | Date | |
---|---|---|---|
|
72230c523b | ||
|
a9b56f8289 | ||
|
f891f9f74d | ||
|
271a24e7bf | ||
|
2c1064ed2d | ||
|
55ee7b38e8 | ||
|
6674dc4269 | ||
|
96638e706c | ||
|
08e90b3cad | ||
|
ada70b4522 | ||
|
8f6e28789f | ||
|
e14aad448b | ||
|
7829bc6c9f | ||
|
32b8bb3b3b | ||
|
cc12b5c748 | ||
|
50aa457e1d | ||
|
6546605650 | ||
|
42ccca964c | ||
|
966444248f |
@@ -586,6 +586,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
addr >>= BDRV_SECTOR_BITS;
|
addr >>= BDRV_SECTOR_BITS;
|
||||||
|
|
||||||
if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
|
if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
|
||||||
|
int ret;
|
||||||
/* get device name */
|
/* get device name */
|
||||||
len = qemu_get_byte(f);
|
len = qemu_get_byte(f);
|
||||||
qemu_get_buffer(f, (uint8_t *)device_name, len);
|
qemu_get_buffer(f, (uint8_t *)device_name, len);
|
||||||
@@ -601,9 +602,12 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
buf = qemu_malloc(BLOCK_SIZE);
|
buf = qemu_malloc(BLOCK_SIZE);
|
||||||
|
|
||||||
qemu_get_buffer(f, buf, BLOCK_SIZE);
|
qemu_get_buffer(f, buf, BLOCK_SIZE);
|
||||||
bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK);
|
ret = bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK);
|
||||||
|
|
||||||
qemu_free(buf);
|
qemu_free(buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
} else if (flags & BLK_MIG_FLAG_PROGRESS) {
|
} else if (flags & BLK_MIG_FLAG_PROGRESS) {
|
||||||
if (!banner_printed) {
|
if (!banner_printed) {
|
||||||
printf("Receiving block device images\n");
|
printf("Receiving block device images\n");
|
||||||
|
56
block.c
56
block.c
@@ -330,7 +330,7 @@ BlockDriver *bdrv_find_protocol(const char *filename)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BlockDriver *find_image_format(const char *filename)
|
static int find_image_format(const char *filename, BlockDriver **pdrv)
|
||||||
{
|
{
|
||||||
int ret, score, score_max;
|
int ret, score, score_max;
|
||||||
BlockDriver *drv1, *drv;
|
BlockDriver *drv1, *drv;
|
||||||
@@ -338,19 +338,27 @@ static BlockDriver *find_image_format(const char *filename)
|
|||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
|
||||||
ret = bdrv_file_open(&bs, filename, 0);
|
ret = bdrv_file_open(&bs, filename, 0);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
return NULL;
|
*pdrv = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the raw BlockDriver * to scsi-generic devices or empty drives */
|
/* Return the raw BlockDriver * to scsi-generic devices or empty drives */
|
||||||
if (bs->sg || !bdrv_is_inserted(bs)) {
|
if (bs->sg || !bdrv_is_inserted(bs)) {
|
||||||
bdrv_delete(bs);
|
bdrv_delete(bs);
|
||||||
return bdrv_find_format("raw");
|
drv = bdrv_find_format("raw");
|
||||||
|
if (!drv) {
|
||||||
|
ret = -ENOENT;
|
||||||
|
}
|
||||||
|
*pdrv = drv;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_pread(bs, 0, buf, sizeof(buf));
|
ret = bdrv_pread(bs, 0, buf, sizeof(buf));
|
||||||
bdrv_delete(bs);
|
bdrv_delete(bs);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return NULL;
|
*pdrv = NULL;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
score_max = 0;
|
score_max = 0;
|
||||||
@@ -364,7 +372,11 @@ static BlockDriver *find_image_format(const char *filename)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return drv;
|
if (!drv) {
|
||||||
|
ret = -ENOENT;
|
||||||
|
}
|
||||||
|
*pdrv = drv;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -571,12 +583,11 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
|
|||||||
|
|
||||||
/* Find the right image format driver */
|
/* Find the right image format driver */
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
drv = find_image_format(filename);
|
ret = find_image_format(filename, &drv);
|
||||||
probed = 1;
|
probed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
ret = -ENOENT;
|
|
||||||
goto unlink_and_fail;
|
goto unlink_and_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -732,6 +743,7 @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res)
|
|||||||
int bdrv_commit(BlockDriverState *bs)
|
int bdrv_commit(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
BlockDriver *drv = bs->drv;
|
BlockDriver *drv = bs->drv;
|
||||||
|
BlockDriver *backing_drv;
|
||||||
int64_t i, total_sectors;
|
int64_t i, total_sectors;
|
||||||
int n, j, ro, open_flags;
|
int n, j, ro, open_flags;
|
||||||
int ret = 0, rw_ret = 0;
|
int ret = 0, rw_ret = 0;
|
||||||
@@ -750,6 +762,7 @@ int bdrv_commit(BlockDriverState *bs)
|
|||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backing_drv = bs->backing_hd->drv;
|
||||||
ro = bs->backing_hd->read_only;
|
ro = bs->backing_hd->read_only;
|
||||||
strncpy(filename, bs->backing_hd->filename, sizeof(filename));
|
strncpy(filename, bs->backing_hd->filename, sizeof(filename));
|
||||||
open_flags = bs->backing_hd->open_flags;
|
open_flags = bs->backing_hd->open_flags;
|
||||||
@@ -759,12 +772,14 @@ 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, drv);
|
rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR,
|
||||||
|
backing_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, drv);
|
ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR,
|
||||||
|
backing_drv);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bdrv_delete(bs_ro);
|
bdrv_delete(bs_ro);
|
||||||
/* drive not functional anymore */
|
/* drive not functional anymore */
|
||||||
@@ -816,7 +831,8 @@ 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, drv);
|
ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR,
|
||||||
|
backing_drv);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bdrv_delete(bs_ro);
|
bdrv_delete(bs_ro);
|
||||||
/* drive not functional anymore */
|
/* drive not functional anymore */
|
||||||
@@ -1465,10 +1481,8 @@ int bdrv_has_zero_init(BlockDriverState *bs)
|
|||||||
{
|
{
|
||||||
assert(bs->drv);
|
assert(bs->drv);
|
||||||
|
|
||||||
if (bs->drv->no_zero_init) {
|
if (bs->drv->bdrv_has_zero_init) {
|
||||||
return 0;
|
return bs->drv->bdrv_has_zero_init(bs);
|
||||||
} else if (bs->file) {
|
|
||||||
return bdrv_has_zero_init(bs->file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1800,6 +1814,11 @@ int bdrv_can_snapshot(BlockDriverState *bs)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bdrv_is_snapshot(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
return !!(bs->open_flags & BDRV_O_SNAPSHOT);
|
||||||
|
}
|
||||||
|
|
||||||
BlockDriverState *bdrv_snapshots(void)
|
BlockDriverState *bdrv_snapshots(void)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
@@ -2502,7 +2521,7 @@ int bdrv_is_inserted(BlockDriverState *bs)
|
|||||||
if (!drv)
|
if (!drv)
|
||||||
return 0;
|
return 0;
|
||||||
if (!drv->bdrv_is_inserted)
|
if (!drv->bdrv_is_inserted)
|
||||||
return 1;
|
return !bs->tray_open;
|
||||||
ret = drv->bdrv_is_inserted(bs);
|
ret = drv->bdrv_is_inserted(bs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -2544,10 +2563,11 @@ int bdrv_eject(BlockDriverState *bs, int eject_flag)
|
|||||||
ret = drv->bdrv_eject(bs, eject_flag);
|
ret = drv->bdrv_eject(bs, eject_flag);
|
||||||
}
|
}
|
||||||
if (ret == -ENOTSUP) {
|
if (ret == -ENOTSUP) {
|
||||||
if (eject_flag)
|
|
||||||
bdrv_close(bs);
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
if (ret >= 0) {
|
||||||
|
bs->tray_open = eject_flag;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
1
block.h
1
block.h
@@ -202,6 +202,7 @@ const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
|
|||||||
void bdrv_get_backing_filename(BlockDriverState *bs,
|
void bdrv_get_backing_filename(BlockDriverState *bs,
|
||||||
char *filename, int filename_size);
|
char *filename, int filename_size);
|
||||||
int bdrv_can_snapshot(BlockDriverState *bs);
|
int bdrv_can_snapshot(BlockDriverState *bs);
|
||||||
|
int bdrv_is_snapshot(BlockDriverState *bs);
|
||||||
BlockDriverState *bdrv_snapshots(void);
|
BlockDriverState *bdrv_snapshots(void);
|
||||||
int bdrv_snapshot_create(BlockDriverState *bs,
|
int bdrv_snapshot_create(BlockDriverState *bs,
|
||||||
QEMUSnapshotInfo *sn_info);
|
QEMUSnapshotInfo *sn_info);
|
||||||
|
@@ -993,6 +993,11 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hdev_has_zero_init(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static BlockDriver bdrv_host_device = {
|
static BlockDriver bdrv_host_device = {
|
||||||
.format_name = "host_device",
|
.format_name = "host_device",
|
||||||
.protocol_name = "host_device",
|
.protocol_name = "host_device",
|
||||||
@@ -1002,7 +1007,7 @@ static BlockDriver bdrv_host_device = {
|
|||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_create = hdev_create,
|
.bdrv_create = hdev_create,
|
||||||
.create_options = raw_create_options,
|
.create_options = raw_create_options,
|
||||||
.no_zero_init = 1,
|
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
|
||||||
.bdrv_aio_readv = raw_aio_readv,
|
.bdrv_aio_readv = raw_aio_readv,
|
||||||
@@ -1117,7 +1122,7 @@ static BlockDriver bdrv_host_floppy = {
|
|||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_create = hdev_create,
|
.bdrv_create = hdev_create,
|
||||||
.create_options = raw_create_options,
|
.create_options = raw_create_options,
|
||||||
.no_zero_init = 1,
|
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
|
||||||
.bdrv_aio_readv = raw_aio_readv,
|
.bdrv_aio_readv = raw_aio_readv,
|
||||||
@@ -1217,7 +1222,7 @@ static BlockDriver bdrv_host_cdrom = {
|
|||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_create = hdev_create,
|
.bdrv_create = hdev_create,
|
||||||
.create_options = raw_create_options,
|
.create_options = raw_create_options,
|
||||||
.no_zero_init = 1,
|
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
|
||||||
.bdrv_aio_readv = raw_aio_readv,
|
.bdrv_aio_readv = raw_aio_readv,
|
||||||
@@ -1340,7 +1345,7 @@ static BlockDriver bdrv_host_cdrom = {
|
|||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_create = hdev_create,
|
.bdrv_create = hdev_create,
|
||||||
.create_options = raw_create_options,
|
.create_options = raw_create_options,
|
||||||
.no_zero_init = 1,
|
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
|
||||||
.bdrv_aio_readv = raw_aio_readv,
|
.bdrv_aio_readv = raw_aio_readv,
|
||||||
|
@@ -394,6 +394,11 @@ static int raw_set_locked(BlockDriverState *bs, int locked)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int hdev_has_zero_init(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static BlockDriver bdrv_host_device = {
|
static BlockDriver bdrv_host_device = {
|
||||||
.format_name = "host_device",
|
.format_name = "host_device",
|
||||||
.protocol_name = "host_device",
|
.protocol_name = "host_device",
|
||||||
@@ -402,6 +407,7 @@ static BlockDriver bdrv_host_device = {
|
|||||||
.bdrv_file_open = hdev_open,
|
.bdrv_file_open = hdev_open,
|
||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||||
|
|
||||||
.bdrv_read = raw_read,
|
.bdrv_read = raw_read,
|
||||||
.bdrv_write = raw_write,
|
.bdrv_write = raw_write,
|
||||||
|
@@ -237,6 +237,11 @@ static QEMUOptionParameter raw_create_options[] = {
|
|||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int raw_has_zero_init(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
return bdrv_has_zero_init(bs->file);
|
||||||
|
}
|
||||||
|
|
||||||
static BlockDriver bdrv_raw = {
|
static BlockDriver bdrv_raw = {
|
||||||
.format_name = "raw",
|
.format_name = "raw",
|
||||||
|
|
||||||
@@ -264,6 +269,7 @@ static BlockDriver bdrv_raw = {
|
|||||||
|
|
||||||
.bdrv_create = raw_create,
|
.bdrv_create = raw_create,
|
||||||
.create_options = raw_create_options,
|
.create_options = raw_create_options,
|
||||||
|
.bdrv_has_zero_init = raw_has_zero_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void bdrv_raw_init(void)
|
static void bdrv_raw_init(void)
|
||||||
|
@@ -512,7 +512,7 @@ static inline uint8_t fat_chksum(const direntry_t* entry)
|
|||||||
for(i=0;i<11;i++) {
|
for(i=0;i<11;i++) {
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
|
|
||||||
c = (i <= 8) ? entry->name[i] : entry->extension[i-8];
|
c = (i < 8) ? entry->name[i] : entry->extension[i-8];
|
||||||
chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0)) + c;
|
chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0)) + c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
block_int.h
12
block_int.h
@@ -127,8 +127,11 @@ struct BlockDriver {
|
|||||||
|
|
||||||
void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
|
void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
|
||||||
|
|
||||||
/* Set if newly created images are not guaranteed to contain only zeros */
|
/*
|
||||||
int no_zero_init;
|
* Returns 1 if newly created images are guaranteed to contain only
|
||||||
|
* zeros, 0 otherwise.
|
||||||
|
*/
|
||||||
|
int (*bdrv_has_zero_init)(BlockDriverState *bs);
|
||||||
|
|
||||||
QLIST_ENTRY(BlockDriver) list;
|
QLIST_ENTRY(BlockDriver) list;
|
||||||
};
|
};
|
||||||
@@ -141,6 +144,7 @@ struct BlockDriverState {
|
|||||||
int open_flags; /* flags used to open the file, re-used for re-open */
|
int open_flags; /* flags used to open the file, re-used for re-open */
|
||||||
int removable; /* if true, the media can be removed */
|
int removable; /* if true, the media can be removed */
|
||||||
int locked; /* if true, the media cannot temporarily be ejected */
|
int locked; /* if true, the media cannot temporarily be ejected */
|
||||||
|
int tray_open; /* if true, the virtual tray is open */
|
||||||
int encrypted; /* if true, the media is encrypted */
|
int encrypted; /* if true, the media is encrypted */
|
||||||
int valid_key; /* if true, a valid encryption key has been set */
|
int valid_key; /* if true, a valid encryption key has been set */
|
||||||
int sg; /* if true, the device is a /dev/sg* */
|
int sg; /* if true, the device is a /dev/sg* */
|
||||||
@@ -243,7 +247,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
|
|||||||
_conf.logical_block_size, 512), \
|
_conf.logical_block_size, 512), \
|
||||||
DEFINE_PROP_UINT16("physical_block_size", _state, \
|
DEFINE_PROP_UINT16("physical_block_size", _state, \
|
||||||
_conf.physical_block_size, 512), \
|
_conf.physical_block_size, 512), \
|
||||||
DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 512), \
|
DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \
|
||||||
DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 512)
|
DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0)
|
||||||
|
|
||||||
#endif /* BLOCK_INT_H */
|
#endif /* BLOCK_INT_H */
|
||||||
|
@@ -590,6 +590,7 @@ int do_change_block(Monitor *mon, const char *device,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
|
bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
|
||||||
|
bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0;
|
||||||
if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
|
if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
|
||||||
qerror_report(QERR_OPEN_FILE_FAILED, filename);
|
qerror_report(QERR_OPEN_FILE_FAILED, filename);
|
||||||
return -1;
|
return -1;
|
||||||
|
@@ -629,8 +629,10 @@ extern unsigned long guest_base;
|
|||||||
extern int have_guest_base;
|
extern int have_guest_base;
|
||||||
extern unsigned long reserved_va;
|
extern unsigned long reserved_va;
|
||||||
#define GUEST_BASE guest_base
|
#define GUEST_BASE guest_base
|
||||||
|
#define RESERVED_VA reserved_va
|
||||||
#else
|
#else
|
||||||
#define GUEST_BASE 0ul
|
#define GUEST_BASE 0ul
|
||||||
|
#define RESERVED_VA 0ul
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
|
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
|
||||||
|
@@ -1643,6 +1643,21 @@ static void ide_atapi_cmd(IDEState *s)
|
|||||||
ide_atapi_cmd_reply(s, len, max_len);
|
ide_atapi_cmd_reply(s, len, max_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
|
||||||
|
max_len = ube16_to_cpu(packet + 7);
|
||||||
|
|
||||||
|
if (packet[1] & 0x01) { /* polling */
|
||||||
|
/* We don't support any event class (yet). */
|
||||||
|
cpu_to_ube16(buf, 0x00); /* No event descriptor returned */
|
||||||
|
buf[2] = 0x80; /* No Event Available (NEA) */
|
||||||
|
buf[3] = 0x00; /* Empty supported event classes */
|
||||||
|
ide_atapi_cmd_reply(s, 4, max_len);
|
||||||
|
} else { /* asynchronous mode */
|
||||||
|
/* Only polling is supported, asynchronous mode is not. */
|
||||||
|
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
|
||||||
|
ASC_INV_FIELD_IN_CMD_PACKET);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
|
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
|
||||||
ASC_ILLEGAL_OPCODE);
|
ASC_ILLEGAL_OPCODE);
|
||||||
|
23
hw/ide/pci.c
23
hw/ide/pci.c
@@ -40,8 +40,27 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
|
|||||||
printf("%s: 0x%08x\n", __func__, val);
|
printf("%s: 0x%08x\n", __func__, val);
|
||||||
#endif
|
#endif
|
||||||
if (!(val & BM_CMD_START)) {
|
if (!(val & BM_CMD_START)) {
|
||||||
/* XXX: do it better */
|
/*
|
||||||
ide_dma_cancel(bm);
|
* We can't cancel Scatter Gather DMA in the middle of the
|
||||||
|
* operation or a partial (not full) DMA transfer would reach
|
||||||
|
* the storage so we wait for completion instead (we beahve
|
||||||
|
* like if the DMA was completed by the time the guest trying
|
||||||
|
* to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
|
||||||
|
* set).
|
||||||
|
*
|
||||||
|
* In the future we'll be able to safely cancel the I/O if the
|
||||||
|
* whole DMA operation will be submitted to disk with a single
|
||||||
|
* aio operation with preadv/pwritev.
|
||||||
|
*/
|
||||||
|
if (bm->aiocb) {
|
||||||
|
qemu_aio_flush();
|
||||||
|
#ifdef DEBUG_IDE
|
||||||
|
if (bm->aiocb)
|
||||||
|
printf("ide_dma_cancel: aiocb still pending");
|
||||||
|
if (bm->status & BM_STATUS_DMAING)
|
||||||
|
printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
bm->cmd = val & 0x09;
|
bm->cmd = val & 0x09;
|
||||||
} else {
|
} else {
|
||||||
if (!(bm->status & BM_STATUS_DMAING)) {
|
if (!(bm->status & BM_STATUS_DMAING)) {
|
||||||
|
@@ -28,6 +28,7 @@ typedef struct VirtIOBlock
|
|||||||
BlockConf *conf;
|
BlockConf *conf;
|
||||||
unsigned short sector_mask;
|
unsigned short sector_mask;
|
||||||
char sn[BLOCK_SERIAL_STRLEN];
|
char sn[BLOCK_SERIAL_STRLEN];
|
||||||
|
DeviceState *qdev;
|
||||||
} VirtIOBlock;
|
} VirtIOBlock;
|
||||||
|
|
||||||
static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
|
static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
|
||||||
@@ -479,6 +480,11 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
|
qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
|
||||||
req->next = s->rq;
|
req->next = s->rq;
|
||||||
s->rq = req;
|
s->rq = req;
|
||||||
|
|
||||||
|
virtqueue_map_sg(req->elem.in_sg, req->elem.in_addr,
|
||||||
|
req->elem.in_num, 1);
|
||||||
|
virtqueue_map_sg(req->elem.out_sg, req->elem.out_addr,
|
||||||
|
req->elem.out_num, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -522,9 +528,16 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
|
|||||||
s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
|
s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
|
||||||
|
|
||||||
qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
|
qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
|
||||||
|
s->qdev = dev;
|
||||||
register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
|
register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
|
||||||
virtio_blk_save, virtio_blk_load, s);
|
virtio_blk_save, virtio_blk_load, s);
|
||||||
bdrv_set_removable(s->bs, 0);
|
bdrv_set_removable(s->bs, 0);
|
||||||
|
|
||||||
return &s->vdev;
|
return &s->vdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void virtio_blk_exit(VirtIODevice *vdev)
|
||||||
|
{
|
||||||
|
VirtIOBlock *s = to_virtio_blk(vdev);
|
||||||
|
unregister_savevm(s->qdev, "virtio-blk", s);
|
||||||
|
}
|
||||||
|
@@ -569,6 +569,7 @@ static int virtio_blk_exit_pci(PCIDevice *pci_dev)
|
|||||||
{
|
{
|
||||||
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
|
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
|
||||||
|
|
||||||
|
virtio_blk_exit(proxy->vdev);
|
||||||
blockdev_mark_auto_del(proxy->block.bs);
|
blockdev_mark_auto_del(proxy->block.bs);
|
||||||
return virtio_exit_pci(pci_dev);
|
return virtio_exit_pci(pci_dev);
|
||||||
}
|
}
|
||||||
|
40
hw/virtio.c
40
hw/virtio.c
@@ -360,11 +360,26 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void virtqueue_map_sg(struct iovec *sg, target_phys_addr_t *addr,
|
||||||
|
size_t num_sg, int is_write)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
target_phys_addr_t len;
|
||||||
|
|
||||||
|
for (i = 0; i < num_sg; i++) {
|
||||||
|
len = sg[i].iov_len;
|
||||||
|
sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
|
||||||
|
if (sg[i].iov_base == NULL || len != sg[i].iov_len) {
|
||||||
|
fprintf(stderr, "virtio: trying to map MMIO memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
|
int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
|
||||||
{
|
{
|
||||||
unsigned int i, head, max;
|
unsigned int i, head, max;
|
||||||
target_phys_addr_t desc_pa = vq->vring.desc;
|
target_phys_addr_t desc_pa = vq->vring.desc;
|
||||||
target_phys_addr_t len;
|
|
||||||
|
|
||||||
if (!virtqueue_num_heads(vq, vq->last_avail_idx))
|
if (!virtqueue_num_heads(vq, vq->last_avail_idx))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -388,29 +403,20 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
|
|||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Collect all the descriptors */
|
||||||
do {
|
do {
|
||||||
struct iovec *sg;
|
struct iovec *sg;
|
||||||
int is_write = 0;
|
|
||||||
|
|
||||||
if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
|
if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
|
||||||
elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
|
elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
|
||||||
sg = &elem->in_sg[elem->in_num++];
|
sg = &elem->in_sg[elem->in_num++];
|
||||||
is_write = 1;
|
} else {
|
||||||
} else
|
elem->out_addr[elem->out_num] = vring_desc_addr(desc_pa, i);
|
||||||
sg = &elem->out_sg[elem->out_num++];
|
sg = &elem->out_sg[elem->out_num++];
|
||||||
|
|
||||||
/* Grab the first descriptor, and check it's OK. */
|
|
||||||
sg->iov_len = vring_desc_len(desc_pa, i);
|
|
||||||
len = sg->iov_len;
|
|
||||||
|
|
||||||
sg->iov_base = cpu_physical_memory_map(vring_desc_addr(desc_pa, i),
|
|
||||||
&len, is_write);
|
|
||||||
|
|
||||||
if (sg->iov_base == NULL || len != sg->iov_len) {
|
|
||||||
fprintf(stderr, "virtio: trying to map MMIO memory\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sg->iov_len = vring_desc_len(desc_pa, i);
|
||||||
|
|
||||||
/* If we've got too many, that implies a descriptor loop. */
|
/* If we've got too many, that implies a descriptor loop. */
|
||||||
if ((elem->in_num + elem->out_num) > max) {
|
if ((elem->in_num + elem->out_num) > max) {
|
||||||
fprintf(stderr, "Looped descriptor");
|
fprintf(stderr, "Looped descriptor");
|
||||||
@@ -418,6 +424,10 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
|
|||||||
}
|
}
|
||||||
} while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
|
} while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
|
||||||
|
|
||||||
|
/* Now map what we have collected */
|
||||||
|
virtqueue_map_sg(elem->in_sg, elem->in_addr, elem->in_num, 1);
|
||||||
|
virtqueue_map_sg(elem->out_sg, elem->out_addr, elem->out_num, 0);
|
||||||
|
|
||||||
elem->index = head;
|
elem->index = head;
|
||||||
|
|
||||||
vq->inuse++;
|
vq->inuse++;
|
||||||
|
@@ -81,6 +81,7 @@ typedef struct VirtQueueElement
|
|||||||
unsigned int out_num;
|
unsigned int out_num;
|
||||||
unsigned int in_num;
|
unsigned int in_num;
|
||||||
target_phys_addr_t in_addr[VIRTQUEUE_MAX_SIZE];
|
target_phys_addr_t in_addr[VIRTQUEUE_MAX_SIZE];
|
||||||
|
target_phys_addr_t out_addr[VIRTQUEUE_MAX_SIZE];
|
||||||
struct iovec in_sg[VIRTQUEUE_MAX_SIZE];
|
struct iovec in_sg[VIRTQUEUE_MAX_SIZE];
|
||||||
struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
|
struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
|
||||||
} VirtQueueElement;
|
} VirtQueueElement;
|
||||||
@@ -142,6 +143,8 @@ void virtqueue_flush(VirtQueue *vq, unsigned int count);
|
|||||||
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
||||||
unsigned int len, unsigned int idx);
|
unsigned int len, unsigned int idx);
|
||||||
|
|
||||||
|
void virtqueue_map_sg(struct iovec *sg, target_phys_addr_t *addr,
|
||||||
|
size_t num_sg, int is_write);
|
||||||
int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem);
|
int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem);
|
||||||
int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes);
|
int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes);
|
||||||
|
|
||||||
@@ -194,6 +197,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
|
|||||||
|
|
||||||
|
|
||||||
void virtio_net_exit(VirtIODevice *vdev);
|
void virtio_net_exit(VirtIODevice *vdev);
|
||||||
|
void virtio_blk_exit(VirtIODevice *vdev);
|
||||||
|
|
||||||
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
|
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
|
||||||
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
|
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
|
||||||
|
@@ -225,13 +225,13 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
|
|||||||
int prot;
|
int prot;
|
||||||
int looped = 0;
|
int looped = 0;
|
||||||
|
|
||||||
if (size > reserved_va) {
|
if (size > RESERVED_VA) {
|
||||||
return (abi_ulong)-1;
|
return (abi_ulong)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_addr = start;
|
last_addr = start;
|
||||||
for (addr = start; last_addr + size != addr; addr += qemu_host_page_size) {
|
for (addr = start; last_addr + size != addr; addr += qemu_host_page_size) {
|
||||||
if (last_addr + size >= reserved_va
|
if (last_addr + size >= RESERVED_VA
|
||||||
|| (abi_ulong)(last_addr + size) < last_addr) {
|
|| (abi_ulong)(last_addr + size) < last_addr) {
|
||||||
if (looped) {
|
if (looped) {
|
||||||
return (abi_ulong)-1;
|
return (abi_ulong)-1;
|
||||||
@@ -271,7 +271,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
|
|||||||
|
|
||||||
size = HOST_PAGE_ALIGN(size);
|
size = HOST_PAGE_ALIGN(size);
|
||||||
|
|
||||||
if (reserved_va) {
|
if (RESERVED_VA) {
|
||||||
return mmap_find_vma_reserved(start, size);
|
return mmap_find_vma_reserved(start, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,7 +651,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
/* unmap what we can */
|
/* unmap what we can */
|
||||||
if (real_start < real_end) {
|
if (real_start < real_end) {
|
||||||
if (reserved_va) {
|
if (RESERVED_VA) {
|
||||||
mmap_reserve(real_start, real_end - real_start);
|
mmap_reserve(real_start, real_end - real_start);
|
||||||
} else {
|
} else {
|
||||||
ret = munmap(g2h(real_start), real_end - real_start);
|
ret = munmap(g2h(real_start), real_end - real_start);
|
||||||
@@ -679,7 +679,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
|||||||
flags,
|
flags,
|
||||||
g2h(new_addr));
|
g2h(new_addr));
|
||||||
|
|
||||||
if (reserved_va && host_addr != MAP_FAILED) {
|
if (RESERVED_VA && host_addr != MAP_FAILED) {
|
||||||
/* If new and old addresses overlap then the above mremap will
|
/* If new and old addresses overlap then the above mremap will
|
||||||
already have failed with EINVAL. */
|
already have failed with EINVAL. */
|
||||||
mmap_reserve(old_addr, old_size);
|
mmap_reserve(old_addr, old_size);
|
||||||
@@ -701,7 +701,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int prot = 0;
|
int prot = 0;
|
||||||
if (reserved_va && old_size < new_size) {
|
if (RESERVED_VA && old_size < new_size) {
|
||||||
abi_ulong addr;
|
abi_ulong addr;
|
||||||
for (addr = old_addr + old_size;
|
for (addr = old_addr + old_size;
|
||||||
addr < old_addr + new_size;
|
addr < old_addr + new_size;
|
||||||
@@ -711,7 +711,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
|||||||
}
|
}
|
||||||
if (prot == 0) {
|
if (prot == 0) {
|
||||||
host_addr = mremap(g2h(old_addr), old_size, new_size, flags);
|
host_addr = mremap(g2h(old_addr), old_size, new_size, flags);
|
||||||
if (host_addr != MAP_FAILED && reserved_va && old_size > new_size) {
|
if (host_addr != MAP_FAILED && RESERVED_VA && old_size > new_size) {
|
||||||
mmap_reserve(old_addr + old_size, new_size - old_size);
|
mmap_reserve(old_addr + old_size, new_size - old_size);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -599,6 +599,7 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
|
|||||||
acb->aio_type = QEMU_AIO_IOCTL;
|
acb->aio_type = QEMU_AIO_IOCTL;
|
||||||
acb->aio_fildes = fd;
|
acb->aio_fildes = fd;
|
||||||
acb->ev_signo = SIGUSR2;
|
acb->ev_signo = SIGUSR2;
|
||||||
|
acb->async_context_id = get_async_context_id();
|
||||||
acb->aio_offset = 0;
|
acb->aio_offset = 0;
|
||||||
acb->aio_ioctl_buf = buf;
|
acb->aio_ioctl_buf = buf;
|
||||||
acb->aio_ioctl_cmd = req;
|
acb->aio_ioctl_cmd = req;
|
||||||
|
@@ -1286,7 +1286,7 @@ static int img_rebase(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bs_new_backing = bdrv_new("new_backing");
|
bs_new_backing = bdrv_new("new_backing");
|
||||||
ret = bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS | BDRV_O_RDWR,
|
ret = bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS,
|
||||||
new_backing_drv);
|
new_backing_drv);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
error("Could not open new backing file '%s'", out_baseimg);
|
error("Could not open new backing file '%s'", out_baseimg);
|
||||||
|
@@ -118,7 +118,7 @@ ETEXI
|
|||||||
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
|
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
|
||||||
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
|
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
|
||||||
" [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
|
" [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
|
||||||
" [,cache=writethrough|writeback|unsafe|none][,format=f]\n"
|
" [,cache=writethrough|writeback|none|unsafe][,format=f]\n"
|
||||||
" [,serial=s][,addr=A][,id=name][,aio=threads|native]\n"
|
" [,serial=s][,addr=A][,id=name][,aio=threads|native]\n"
|
||||||
" [,readonly=on|off]\n"
|
" [,readonly=on|off]\n"
|
||||||
" use 'file' as a drive image\n", QEMU_ARCH_ALL)
|
" use 'file' as a drive image\n", QEMU_ARCH_ALL)
|
||||||
|
6
savevm.c
6
savevm.c
@@ -1139,6 +1139,9 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
|
|||||||
QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
|
QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
|
||||||
if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
|
if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
|
||||||
QTAILQ_REMOVE(&savevm_handlers, se, entry);
|
QTAILQ_REMOVE(&savevm_handlers, se, entry);
|
||||||
|
if (se->compat) {
|
||||||
|
qemu_free(se->compat);
|
||||||
|
}
|
||||||
qemu_free(se);
|
qemu_free(se);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1206,6 +1209,9 @@ void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
|
|||||||
QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
|
QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
|
||||||
if (se->vmsd == vmsd && se->opaque == opaque) {
|
if (se->vmsd == vmsd && se->opaque == opaque) {
|
||||||
QTAILQ_REMOVE(&savevm_handlers, se, entry);
|
QTAILQ_REMOVE(&savevm_handlers, se, entry);
|
||||||
|
if (se->compat) {
|
||||||
|
qemu_free(se->compat);
|
||||||
|
}
|
||||||
qemu_free(se);
|
qemu_free(se);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user