diff options
| -rw-r--r-- | block.c | 104 | ||||
| -rw-r--r-- | block.h | 63 | ||||
| -rw-r--r-- | block/nbd.c | 1 | ||||
| -rw-r--r-- | block/qcow2-cluster.c | 27 | ||||
| -rw-r--r-- | block/qcow2.c | 14 | ||||
| -rw-r--r-- | block/qcow2.h | 1 | ||||
| -rw-r--r-- | block/raw-posix.c | 8 | ||||
| -rw-r--r-- | block/raw.c | 6 | ||||
| -rw-r--r-- | block/rbd.c | 97 | ||||
| -rw-r--r-- | block_int.h | 40 | ||||
| -rw-r--r-- | blockdev.c | 10 | ||||
| -rw-r--r-- | hw/9pfs/virtio-9p.c | 126 | ||||
| -rw-r--r-- | hw/9pfs/virtio-9p.h | 4 | ||||
| -rw-r--r-- | hw/fdc.c | 4 | ||||
| -rw-r--r-- | hw/ide/ahci.c | 2 | ||||
| -rw-r--r-- | hw/ide/ahci.h | 1 | ||||
| -rw-r--r-- | hw/ide/atapi.c | 58 | ||||
| -rw-r--r-- | hw/ide/cmd646.c | 1 | ||||
| -rw-r--r-- | hw/ide/core.c | 160 | ||||
| -rw-r--r-- | hw/ide/ich.c | 1 | ||||
| -rw-r--r-- | hw/ide/internal.h | 3 | ||||
| -rw-r--r-- | hw/ide/isa.c | 1 | ||||
| -rw-r--r-- | hw/ide/macio.c | 1 | ||||
| -rw-r--r-- | hw/ide/microdrive.c | 1 | ||||
| -rw-r--r-- | hw/ide/mmio.c | 1 | ||||
| -rw-r--r-- | hw/ide/pci.c | 1 | ||||
| -rw-r--r-- | hw/ide/via.c | 1 | ||||
| -rw-r--r-- | hw/lsi53c895a.c | 1 | ||||
| -rw-r--r-- | hw/scsi-bus.c | 10 | ||||
| -rw-r--r-- | hw/scsi-disk.c | 69 | ||||
| -rw-r--r-- | hw/scsi-generic.c | 1 | ||||
| -rw-r--r-- | hw/scsi.h | 5 | ||||
| -rw-r--r-- | hw/sd.c | 2 | ||||
| -rw-r--r-- | hw/virtio-blk.c | 3 | ||||
| -rw-r--r-- | hw/virtio.h | 2 | ||||
| -rw-r--r-- | nbd.c | 1 | ||||
| -rw-r--r-- | nbd.h | 2 | ||||
| -rw-r--r-- | qmp-commands.hx | 2 | ||||
| -rw-r--r-- | trace-events | 2 |
39 files changed, 582 insertions, 255 deletions
diff --git a/block.c b/block.c index a8c789a079..e3fe97f275 100644 --- a/block.c +++ b/block.c @@ -44,7 +44,7 @@ #include <windows.h> #endif -static void bdrv_dev_change_media_cb(BlockDriverState *bs); +static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load); static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); @@ -480,7 +480,6 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename, bs->encrypted = 0; bs->valid_key = 0; bs->open_flags = flags; - /* buffer_alignment defaulted to 512, drivers can change this value */ bs->buffer_alignment = 512; pstrcpy(bs->filename, sizeof(bs->filename), filename); @@ -689,7 +688,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, } if (!bdrv_key_required(bs)) { - bdrv_dev_change_media_cb(bs); + bdrv_dev_change_media_cb(bs, true); } return 0; @@ -725,7 +724,7 @@ void bdrv_close(BlockDriverState *bs) bdrv_close(bs->file); } - bdrv_dev_change_media_cb(bs); + bdrv_dev_change_media_cb(bs, false); } } @@ -789,6 +788,7 @@ void bdrv_detach_dev(BlockDriverState *bs, void *dev) bs->dev = NULL; bs->dev_ops = NULL; bs->dev_opaque = NULL; + bs->buffer_alignment = 512; } /* TODO change to return DeviceState * when all users are qdevified */ @@ -802,13 +802,29 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, { bs->dev_ops = ops; bs->dev_opaque = opaque; + if (bdrv_dev_has_removable_media(bs) && bs == bs_snapshots) { + bs_snapshots = NULL; + } } -static void bdrv_dev_change_media_cb(BlockDriverState *bs) +static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load) { if (bs->dev_ops && bs->dev_ops->change_media_cb) { - bs->dev_ops->change_media_cb(bs->dev_opaque); + bs->dev_ops->change_media_cb(bs->dev_opaque, load); + } +} + +bool bdrv_dev_has_removable_media(BlockDriverState *bs) +{ + return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb); +} + +bool bdrv_dev_is_tray_open(BlockDriverState *bs) +{ + if (bs->dev_ops && bs->dev_ops->is_tray_open) { + return bs->dev_ops->is_tray_open(bs->dev_opaque); } + return false; } static void bdrv_dev_resize_cb(BlockDriverState *bs) @@ -818,6 +834,14 @@ static void bdrv_dev_resize_cb(BlockDriverState *bs) } } +bool bdrv_dev_is_medium_locked(BlockDriverState *bs) +{ + if (bs->dev_ops && bs->dev_ops->is_medium_locked) { + return bs->dev_ops->is_medium_locked(bs->dev_opaque); + } + return false; +} + /* * Run consistency checks on an image * @@ -1321,7 +1345,7 @@ int64_t bdrv_getlength(BlockDriverState *bs) if (!drv) return -ENOMEDIUM; - if (bs->growable || bs->removable) { + if (bs->growable || bdrv_dev_has_removable_media(bs)) { if (drv->bdrv_getlength) { return drv->bdrv_getlength(bs); } @@ -1598,19 +1622,6 @@ BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read) return is_read ? bs->on_read_error : bs->on_write_error; } -void bdrv_set_removable(BlockDriverState *bs, int removable) -{ - bs->removable = removable; - if (removable && bs == bs_snapshots) { - bs_snapshots = NULL; - } -} - -int bdrv_is_removable(BlockDriverState *bs) -{ - return bs->removable; -} - int bdrv_is_read_only(BlockDriverState *bs) { return bs->read_only; @@ -1663,7 +1674,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) } else if (!bs->valid_key) { bs->valid_key = 1; /* call the change callback now, we skipped it on open */ - bdrv_dev_change_media_cb(bs); + bdrv_dev_change_media_cb(bs, true); } return ret; } @@ -1850,8 +1861,9 @@ static void bdrv_print_dict(QObject *obj, void *opaque) if (qdict_get_bool(bs_dict, "removable")) { monitor_printf(mon, " locked=%d", qdict_get_bool(bs_dict, "locked")); + monitor_printf(mon, " tray-open=%d", + qdict_get_bool(bs_dict, "tray-open")); } - if (qdict_haskey(bs_dict, "inserted")) { QDict *qdict = qobject_to_qdict(qdict_get(bs_dict, "inserted")); @@ -1886,15 +1898,21 @@ void bdrv_info(Monitor *mon, QObject **ret_data) QTAILQ_FOREACH(bs, &bdrv_states, list) { QObject *bs_obj; + QDict *bs_dict; bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': 'unknown', " "'removable': %i, 'locked': %i }", - bs->device_name, bs->removable, - bs->locked); - + bs->device_name, + bdrv_dev_has_removable_media(bs), + bdrv_dev_is_medium_locked(bs)); + bs_dict = qobject_to_qdict(bs_obj); + + if (bdrv_dev_has_removable_media(bs)) { + qdict_put(bs_dict, "tray-open", + qbool_from_int(bdrv_dev_is_tray_open(bs))); + } if (bs->drv) { QObject *obj; - QDict *bs_dict = qobject_to_qdict(bs_obj); obj = qobject_from_jsonf("{ 'file': %s, 'ro': %i, 'drv': %s, " "'encrypted': %i }", @@ -3026,13 +3044,12 @@ static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs) int bdrv_is_inserted(BlockDriverState *bs) { BlockDriver *drv = bs->drv; - int ret; + if (!drv) return 0; if (!drv->bdrv_is_inserted) - return !bs->tray_open; - ret = drv->bdrv_is_inserted(bs); - return ret; + return 1; + return drv->bdrv_is_inserted(bs); } /** @@ -3052,39 +3069,27 @@ int bdrv_media_changed(BlockDriverState *bs) /** * If eject_flag is TRUE, eject the media. Otherwise, close the tray */ -int bdrv_eject(BlockDriverState *bs, int eject_flag) +void bdrv_eject(BlockDriverState *bs, int eject_flag) { BlockDriver *drv = bs->drv; - if (eject_flag && bs->locked) { - return -EBUSY; - } - if (drv && drv->bdrv_eject) { drv->bdrv_eject(bs, eject_flag); } - bs->tray_open = eject_flag; - return 0; -} - -int bdrv_is_locked(BlockDriverState *bs) -{ - return bs->locked; } /** * Lock or unlock the media (if it is locked, the user won't be able * to eject it manually). */ -void bdrv_set_locked(BlockDriverState *bs, int locked) +void bdrv_lock_medium(BlockDriverState *bs, bool locked) { BlockDriver *drv = bs->drv; - trace_bdrv_set_locked(bs, locked); + trace_bdrv_lock_medium(bs, locked); - bs->locked = locked; - if (drv && drv->bdrv_set_locked) { - drv->bdrv_set_locked(bs, locked); + if (drv && drv->bdrv_lock_medium) { + drv->bdrv_lock_medium(bs, locked); } } @@ -3110,7 +3115,10 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, return NULL; } - +void bdrv_set_buffer_alignment(BlockDriverState *bs, int align) +{ + bs->buffer_alignment = align; +} void *qemu_blockalign(BlockDriverState *bs, size_t size) { diff --git a/block.h b/block.h index 8ec409fd18..16bfa0a3d6 100644 --- a/block.h +++ b/block.h @@ -32,10 +32,22 @@ typedef struct QEMUSnapshotInfo { typedef struct BlockDevOps { /* * Runs when virtual media changed (monitor commands eject, change) + * Argument load is true on load and false on eject. * Beware: doesn't run when a host device's physical media * changes. Sure would be useful if it did. + * Device models with removable media must implement this callback. */ - void (*change_media_cb)(void *opaque); + void (*change_media_cb)(void *opaque, bool load); + /* + * Is the virtual tray open? + * Device models implement this only when the device has a tray. + */ + bool (*is_tray_open)(void *opaque); + /* + * Is the virtual medium locked into the device? + * Device models implement this only when device has such a lock. + */ + bool (*is_medium_locked)(void *opaque); /* * Runs when the size changed (e.g. monitor command block_resize) */ @@ -94,6 +106,9 @@ void bdrv_detach_dev(BlockDriverState *bs, void *dev); void *bdrv_get_attached_dev(BlockDriverState *bs); void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, void *opaque); +bool bdrv_dev_has_removable_media(BlockDriverState *bs); +bool bdrv_dev_is_tray_open(BlockDriverState *bs); +bool bdrv_dev_is_medium_locked(BlockDriverState *bs); int bdrv_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); int bdrv_write(BlockDriverState *bs, int64_t sector_num, @@ -199,16 +214,13 @@ int bdrv_get_translation_hint(BlockDriverState *bs); void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error, BlockErrorAction on_write_error); BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read); -void bdrv_set_removable(BlockDriverState *bs, int removable); -int bdrv_is_removable(BlockDriverState *bs); int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_sg(BlockDriverState *bs); int bdrv_enable_write_cache(BlockDriverState *bs); int bdrv_is_inserted(BlockDriverState *bs); int bdrv_media_changed(BlockDriverState *bs); -int bdrv_is_locked(BlockDriverState *bs); -void bdrv_set_locked(BlockDriverState *bs, int locked); -int bdrv_eject(BlockDriverState *bs, int eject_flag); +void bdrv_lock_medium(BlockDriverState *bs, bool locked); +void bdrv_eject(BlockDriverState *bs, int eject_flag); void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size); BlockDriverState *bdrv_find(const char *name); BlockDriverState *bdrv_next(BlockDriverState *bs); @@ -258,6 +270,7 @@ int bdrv_img_create(const char *filename, const char *fmt, const char *base_filename, const char *base_fmt, char *options, uint64_t img_size, int flags); +void bdrv_set_buffer_alignment(BlockDriverState *bs, int align); void *qemu_blockalign(BlockDriverState *bs, size_t size); #define BDRV_SECTORS_PER_DIRTY_CHUNK 2048 @@ -339,5 +352,43 @@ typedef enum { #define BLKDBG_EVENT(bs, evt) bdrv_debug_event(bs, evt) void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event); + +/* Convenience for block device models */ + +typedef struct BlockConf { + BlockDriverState *bs; + uint16_t physical_block_size; + uint16_t logical_block_size; + uint16_t min_io_size; + uint32_t opt_io_size; + int32_t bootindex; + uint32_t discard_granularity; +} BlockConf; + +static inline unsigned int get_physical_block_exp(BlockConf *conf) +{ + unsigned int exp = 0, size; + + for (size = conf->physical_block_size; + size > conf->logical_block_size; + size >>= 1) { + exp++; + } + + return exp; +} + +#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ + DEFINE_PROP_DRIVE("drive", _state, _conf.bs), \ + DEFINE_PROP_UINT16("logical_block_size", _state, \ + _conf.logical_block_size, 512), \ + DEFINE_PROP_UINT16("physical_block_size", _state, \ + _conf.physical_block_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, 0), \ + DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1), \ + DEFINE_PROP_UINT32("discard_granularity", _state, \ + _conf.discard_granularity, 0) + #endif diff --git a/block/nbd.c b/block/nbd.c index 55cb2fd8ba..70edd81bd6 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -28,6 +28,7 @@ #include "qemu-common.h" #include "nbd.h" +#include "block_int.h" #include "module.h" #include "qemu_socket.h" diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index e06be64876..2f76311354 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -694,7 +694,7 @@ err: * If the offset is not found, allocate a new cluster. * * If the cluster was already allocated, m->nb_clusters is set to 0, - * m->depends_on is set to NULL and the other fields in m are meaningless. + * other fields in m are meaningless. * * If the cluster is newly allocated, m->nb_clusters is set to the number of * contiguous clusters that have been allocated. In this case, the other @@ -736,7 +736,6 @@ again: cluster_offset &= ~QCOW_OFLAG_COPIED; m->nb_clusters = 0; - m->depends_on = NULL; goto out; } @@ -777,17 +776,17 @@ again: */ QLIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) { - uint64_t end_offset = offset + nb_clusters * s->cluster_size; - uint64_t old_offset = old_alloc->offset; - uint64_t old_end_offset = old_alloc->offset + - old_alloc->nb_clusters * s->cluster_size; + uint64_t start = offset >> s->cluster_bits; + uint64_t end = start + nb_clusters; + uint64_t old_start = old_alloc->offset >> s->cluster_bits; + uint64_t old_end = old_start + old_alloc->nb_clusters; - if (end_offset < old_offset || offset > old_end_offset) { + if (end < old_start || start > old_end) { /* No intersection */ } else { - if (offset < old_offset) { + if (start < old_start) { /* Stop at the start of a running allocation */ - nb_clusters = (old_offset - offset) >> s->cluster_bits; + nb_clusters = old_start - start; } else { nb_clusters = 0; } @@ -807,6 +806,11 @@ again: abort(); } + /* save info needed for meta data update */ + m->offset = offset; + m->n_start = n_start; + m->nb_clusters = nb_clusters; + QLIST_INSERT_HEAD(&s->cluster_allocs, m, next_in_flight); /* allocate a new cluster */ @@ -817,11 +821,6 @@ again: goto fail; } - /* save info needed for meta data update */ - m->offset = offset; - m->n_start = n_start; - m->nb_clusters = nb_clusters; - out: ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); if (ret < 0) { diff --git a/block/qcow2.c b/block/qcow2.c index 8aed31004d..510ff6897f 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -237,7 +237,7 @@ static int qcow2_open(BlockDriverState *bs, int flags) s->cluster_cache = g_malloc(s->cluster_size); /* one more sector for decompressed data alignment */ - s->cluster_data = g_malloc(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size + s->cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size + 512); s->cluster_cache_offset = -1; @@ -296,7 +296,7 @@ static int qcow2_open(BlockDriverState *bs, int flags) qcow2_cache_destroy(bs, s->l2_table_cache); } g_free(s->cluster_cache); - g_free(s->cluster_data); + qemu_vfree(s->cluster_data); return ret; } @@ -456,7 +456,7 @@ static int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num, */ if (!cluster_data) { cluster_data = - g_malloc0(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); + qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); } assert(cur_nr_sectors <= @@ -496,7 +496,7 @@ fail: qemu_co_mutex_unlock(&s->lock); qemu_iovec_destroy(&hd_qiov); - g_free(cluster_data); + qemu_vfree(cluster_data); return ret; } @@ -566,7 +566,7 @@ static int qcow2_co_writev(BlockDriverState *bs, if (s->crypt_method) { if (!cluster_data) { - cluster_data = g_malloc0(QCOW_MAX_CRYPT_CLUSTERS * + cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); } @@ -611,7 +611,7 @@ fail: qemu_co_mutex_unlock(&s->lock); qemu_iovec_destroy(&hd_qiov); - g_free(cluster_data); + qemu_vfree(cluster_data); return ret; } @@ -628,7 +628,7 @@ static void qcow2_close(BlockDriverState *bs) qcow2_cache_destroy(bs, s->refcount_block_cache); g_free(s->cluster_cache); - g_free(s->cluster_data); + qemu_vfree(s->cluster_data); qcow2_refcount_close(bs); } diff --git a/block/qcow2.h b/block/qcow2.h index c8ca3bc574..531af3948b 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -148,7 +148,6 @@ typedef struct QCowL2Meta int n_start; int nb_available; int nb_clusters; - struct QCowL2Meta *depends_on; CoQueue dependent_requests; QLIST_ENTRY(QCowL2Meta) next_in_flight; diff --git a/block/raw-posix.c b/block/raw-posix.c index bcf50b2cf7..a624f56f86 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -1362,7 +1362,7 @@ static void cdrom_eject(BlockDriverState *bs, int eject_flag) } } -static void cdrom_set_locked(BlockDriverState *bs, int locked) +static void cdrom_lock_medium(BlockDriverState *bs, bool locked) { BDRVRawState *s = bs->opaque; @@ -1400,7 +1400,7 @@ static BlockDriver bdrv_host_cdrom = { /* removable device support */ .bdrv_is_inserted = cdrom_is_inserted, .bdrv_eject = cdrom_eject, - .bdrv_set_locked = cdrom_set_locked, + .bdrv_lock_medium = cdrom_lock_medium, /* generic scsi device */ .bdrv_ioctl = hdev_ioctl, @@ -1481,7 +1481,7 @@ static void cdrom_eject(BlockDriverState *bs, int eject_flag) cdrom_reopen(bs); } -static void cdrom_set_locked(BlockDriverState *bs, int locked) +static void cdrom_lock_medium(BlockDriverState *bs, bool locked) { BDRVRawState *s = bs->opaque; @@ -1521,7 +1521,7 @@ static BlockDriver bdrv_host_cdrom = { /* removable device support */ .bdrv_is_inserted = cdrom_is_inserted, .bdrv_eject = cdrom_eject, - .bdrv_set_locked = cdrom_set_locked, + .bdrv_lock_medium = cdrom_lock_medium, }; #endif /* __FreeBSD__ */ diff --git a/block/raw.c b/block/raw.c index f197479645..63cf2d3bf3 100644 --- a/block/raw.c +++ b/block/raw.c @@ -85,9 +85,9 @@ static void raw_eject(BlockDriverState *bs, int eject_flag) bdrv_eject(bs->file, eject_flag); } -static void raw_set_locked(BlockDriverState *bs, int locked) +static void raw_lock_medium(BlockDriverState *bs, bool locked) { - bdrv_set_locked(bs->file, locked); + bdrv_lock_medium(bs->file, locked); } static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) @@ -144,7 +144,7 @@ static BlockDriver bdrv_raw = { .bdrv_is_inserted = raw_is_inserted, .bdrv_media_changed = raw_media_changed, .bdrv_eject = raw_eject, - .bdrv_set_locked = raw_set_locked, + .bdrv_lock_medium = raw_lock_medium, .bdrv_ioctl = raw_ioctl, .bdrv_aio_ioctl = raw_aio_ioctl, diff --git a/block/rbd.c b/block/rbd.c index ce0f6ef6ee..1b78d51398 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -169,6 +169,34 @@ done: return ret; } +static char *qemu_rbd_parse_clientname(const char *conf, char *clientname) +{ + const char *p = conf; + + while (*p) { + int len; + const char *end = strchr(p, ':'); + + if (end) { + len = end - p; + } else { + len = strlen(p); + } + + if (strncmp(p, "id=", 3) == 0) { + len -= 3; + strncpy(clientname, p + 3, len); + clientname[len] = '\0'; + return clientname; + } + if (end == NULL) { + break; + } + p = end + 1; + } + return NULL; +} + static int qemu_rbd_set_conf(rados_t cluster, const char *conf) { char *p, *buf; @@ -198,17 +226,19 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf) break; } - if (strcmp(name, "conf")) { - ret = rados_conf_set(cluster, name, value); + if (strcmp(name, "conf") == 0) { + ret = rados_conf_read_file(cluster, value); if (ret < 0) { - error_report("invalid conf option %s", name); - ret = -EINVAL; + error_report("error reading conf file %s", value); break; } + } else if (strcmp(name, "id") == 0) { + /* ignore, this is parsed by qemu_rbd_parse_clientname() */ } else { - ret = rados_conf_read_file(cluster, value); + ret = rados_conf_set(cluster, name, value); if (ret < 0) { - error_report("error reading conf file %s", value); + error_report("invalid conf option %s", name); + ret = -EINVAL; break; } } @@ -227,6 +257,8 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) char name[RBD_MAX_IMAGE_NAME_SIZE]; char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; char conf[RBD_MAX_CONF_SIZE]; + char clientname_buf[RBD_MAX_CONF_SIZE]; + char *clientname; rados_t cluster; rados_ioctx_t io_ctx; int ret; @@ -259,7 +291,8 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) options++; } - if (rados_create(&cluster, NULL) < 0) { + clientname = qemu_rbd_parse_clientname(conf, clientname_buf); + if (rados_create(&cluster, clientname) < 0) { error_report("error initializing"); return -EIO; } @@ -358,15 +391,14 @@ static void qemu_rbd_aio_event_reader(void *opaque) char *p = (char *)&s->event_rcb; /* now read the rcb pointer that was sent from a non qemu thread */ - if ((ret = read(s->fds[RBD_FD_READ], p + s->event_reader_pos, - sizeof(s->event_rcb) - s->event_reader_pos)) > 0) { - if (ret > 0) { - s->event_reader_pos += ret; - if (s->event_reader_pos == sizeof(s->event_rcb)) { - s->event_reader_pos = 0; - qemu_rbd_complete_aio(s->event_rcb); - s->qemu_aio_count--; - } + ret = read(s->fds[RBD_FD_READ], p + s->event_reader_pos, + sizeof(s->event_rcb) - s->event_reader_pos); + if (ret > 0) { + s->event_reader_pos += ret; + if (s->event_reader_pos == sizeof(s->event_rcb)) { + s->event_reader_pos = 0; + qemu_rbd_complete_aio(s->event_rcb); + s->qemu_aio_count--; } } } while (ret < 0 && errno == EINTR); @@ -385,6 +417,8 @@ static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) char pool[RBD_MAX_POOL_NAME_SIZE]; char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; char conf[RBD_MAX_CONF_SIZE]; + char clientname_buf[RBD_MAX_CONF_SIZE]; + char *clientname; int r; if (qemu_rbd_parsename(filename, pool, sizeof(pool), @@ -393,23 +427,24 @@ static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) conf, sizeof(conf)) < 0) { return -EINVAL; } - s->snap = NULL; - if (snap_buf[0] != '\0') { - s->snap = g_strdup(snap_buf); - } - r = rados_create(&s->cluster, NULL); + clientname = qemu_rbd_parse_clientname(conf, clientname_buf); + r = rados_create(&s->cluster, clientname); if (r < 0) { error_report("error initializing"); return r; } + s->snap = NULL; + if (snap_buf[0] != '\0') { + s->snap = g_strdup(snap_buf); + } + if (strstr(conf, "conf=") == NULL) { r = rados_conf_read_file(s->cluster, NULL); if (r < 0) { error_report("error reading config file"); - rados_shutdown(s->cluster); - return r; + goto failed_shutdown; } } @@ -417,31 +452,26 @@ static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) r = qemu_rbd_set_conf(s->cluster, conf); if (r < 0) { error_report("error setting config options"); - rados_shutdown(s->cluster); - return r; + goto failed_shutdown; } } r = rados_connect(s->cluster); if (r < 0) { error_report("error connecting"); - rados_shutdown(s->cluster); - return r; + goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_report("error opening pool %s", pool); - rados_shutdown(s->cluster); - return r; + goto failed_shutdown; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { error_report("error reading header from %s", s->name); - rados_ioctx_destroy(s->io_ctx); - rados_shutdown(s->cluster); - return r; + goto failed_open; } bs->read_only = (s->snap != NULL); @@ -462,8 +492,11 @@ static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) failed: rbd_close(s->image); +failed_open: rados_ioctx_destroy(s->io_ctx); +failed_shutdown: rados_shutdown(s->cluster); + g_free(s->snap); return r; } diff --git a/block_int.h b/block_int.h index 5dc0074bfc..8c3b86373c 100644 --- a/block_int.h +++ b/block_int.h @@ -120,7 +120,7 @@ struct BlockDriver { int (*bdrv_is_inserted)(BlockDriverState *bs); int (*bdrv_media_changed)(BlockDriverState *bs); void (*bdrv_eject)(BlockDriverState *bs, int eject_flag); - void (*bdrv_set_locked)(BlockDriverState *bs, int locked); + void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked); /* to control generic scsi devices */ int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf); @@ -155,9 +155,6 @@ struct BlockDriverState { int read_only; /* if true, the media is read only */ int keep_read_only; /* if true, the media was requested to stay read only */ int open_flags; /* flags used to open the file, re-used for re-open */ - int removable; /* if true, the media can be removed */ - 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 valid_key; /* if true, a valid encryption key has been set */ int sg; /* if true, the device is a /dev/sg* */ @@ -228,39 +225,4 @@ void qemu_aio_release(void *p); int is_windows_drive(const char *filename); #endif -typedef struct BlockConf { - BlockDriverState *bs; - uint16_t physical_block_size; - uint16_t logical_block_size; - uint16_t min_io_size; - uint32_t opt_io_size; - int32_t bootindex; - uint32_t discard_granularity; -} BlockConf; - -static inline unsigned int get_physical_block_exp(BlockConf *conf) -{ - unsigned int exp = 0, size; - - for (size = conf->physical_block_size; - size > conf->logical_block_size; - size >>= 1) { - exp++; - } - - return exp; -} - -#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ - DEFINE_PROP_DRIVE("drive", _state, _conf.bs), \ - DEFINE_PROP_UINT16("logical_block_size", _state, \ - _conf.logical_block_size, 512), \ - DEFINE_PROP_UINT16("physical_block_size", _state, \ - _conf.physical_block_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, 0), \ - DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1), \ - DEFINE_PROP_UINT32("discard_granularity", _state, \ - _conf.discard_granularity, 0) - #endif /* BLOCK_INT_H */ diff --git a/blockdev.c b/blockdev.c index 049dda5549..0827bf7743 100644 --- a/blockdev.c +++ b/blockdev.c @@ -473,17 +473,12 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) } break; case MEDIA_CDROM: - bdrv_set_removable(dinfo->bdrv, 1); dinfo->media_cd = 1; break; } break; case IF_SD: - /* FIXME: This isn't really a floppy, but it's a reasonable - approximation. */ case IF_FLOPPY: - bdrv_set_removable(dinfo->bdrv, 1); - break; case IF_PFLASH: case IF_MTD: break; @@ -636,11 +631,12 @@ out: static int eject_device(Monitor *mon, BlockDriverState *bs, int force) { - if (!bdrv_is_removable(bs)) { + if (!bdrv_dev_has_removable_media(bs)) { qerror_report(QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs)); return -1; } - if (!force && bdrv_is_locked(bs)) { + if (!force && !bdrv_dev_is_tray_open(bs) + && bdrv_dev_is_medium_locked(bs)) { qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs)); return -1; } diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 94b7090e7d..d28edb799a 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -543,6 +543,7 @@ static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp) { size_t size; + memset(&qidp->path, 0, sizeof(qidp->path)); size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path)); memcpy(&qidp->path, &stbuf->st_ino, size); qidp->version = stbuf->st_mtime ^ (stbuf->st_size << 8); @@ -2106,6 +2107,7 @@ static void v9fs_create(void *opaque) if (err < 0) { goto out; } + v9fs_string_copy(&fidp->path, &fullname); err = v9fs_co_opendir(pdu->s, fidp); if (err < 0) { goto out; @@ -2336,6 +2338,45 @@ out_nofid: complete_pdu(pdu->s, pdu, err); } +static void v9fs_unlinkat(void *opaque) +{ + int err = 0; + V9fsString name; + int32_t dfid, flags; + size_t offset = 7; + V9fsFidState *dfidp; + V9fsPDU *pdu = opaque; + V9fsString full_name; + + pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags); + + dfidp = get_fid(pdu->s, dfid); + if (dfidp == NULL) { + err = -EINVAL; + goto out_nofid; + } + v9fs_string_init(&full_name); + v9fs_string_sprintf(&full_name, "%s/%s", dfidp->path.data, name.data); + /* + * IF the file is unlinked, we cannot reopen + * the file later. So don't reclaim fd + */ + err = v9fs_mark_fids_unreclaim(pdu->s, &full_name); + if (err < 0) { + goto out_err; + } + err = v9fs_co_remove(pdu->s, &full_name); + if (!err) { + err = offset; + } +out_err: + put_fid(pdu->s, dfidp); + v9fs_string_free(&full_name); +out_nofid: + complete_pdu(pdu->s, pdu, err); + v9fs_string_free(&name); +} + static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp, int32_t newdirfid, V9fsString *name) { @@ -2438,6 +2479,87 @@ out_nofid: v9fs_string_free(&name); } +static int v9fs_complete_renameat(V9fsState *s, int32_t olddirfid, + V9fsString *old_name, int32_t newdirfid, + V9fsString *new_name) +{ + int err = 0; + V9fsString old_full_name, new_full_name; + V9fsFidState *newdirfidp = NULL, *olddirfidp = NULL; + + olddirfidp = get_fid(s, olddirfid); + if (olddirfidp == NULL) { + err = -ENOENT; + goto out; + } + v9fs_string_init(&old_full_name); + v9fs_string_init(&new_full_name); + + v9fs_string_sprintf(&old_full_name, "%s/%s", + olddirfidp->path.data, old_name->data); + if (newdirfid != -1) { + newdirfidp = get_fid(s, newdirfid); + if (newdirfidp == NULL) { + err = -ENOENT; + goto out; + } + v9fs_string_sprintf(&new_full_name, "%s/%s", + newdirfidp->path.data, new_name->data); + } else { + v9fs_string_sprintf(&new_full_name, "%s/%s", + olddirfidp->path.data, new_name->data); + } + + if (strcmp(old_full_name.data, new_full_name.data) != 0) { + V9fsFidState *tfidp; + err = v9fs_co_rename(s, &old_full_name, &new_full_name); + if (err < 0) { + goto out; + } + /* + * Fixup fid's pointing to the old name to + * start pointing to the new name + */ + for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) { + if (v9fs_path_is_ancestor(&old_full_name, &tfidp->path)) { + /* replace the name */ + v9fs_fix_path(&tfidp->path, &new_full_name, old_full_name.size); + } + } + } +out: + if (olddirfidp) { + put_fid(s, olddirfidp); + } + if (newdirfidp) { + put_fid(s, newdirfidp); + } + v9fs_string_free(&old_full_name); + v9fs_string_free(&new_full_name); + return err; +} + +static void v9fs_renameat(void *opaque) +{ + ssize_t err = 0; + size_t offset = 7; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; + int32_t olddirfid, newdirfid; + V9fsString old_name, new_name; + + pdu_unmarshal(pdu, offset, "dsds", &olddirfid, + &old_name, &newdirfid, &new_name); + + err = v9fs_complete_renameat(s, olddirfid, &old_name, newdirfid, &new_name); + if (!err) { + err = offset; + } + complete_pdu(s, pdu, err); + v9fs_string_free(&old_name); + v9fs_string_free(&new_name); +} + static void v9fs_wstat(void *opaque) { int32_t fid; @@ -2694,6 +2816,7 @@ out_nofid: err = offset; err += pdu_marshal(pdu, offset, "b", status); complete_pdu(s, pdu, err); + v9fs_string_free(&flock->client_id); g_free(flock); } @@ -2734,6 +2857,7 @@ out: put_fid(s, fidp); out_nofid: complete_pdu(s, pdu, err); + v9fs_string_free(&glock->client_id); g_free(glock); } @@ -2953,7 +3077,9 @@ static CoroutineEntry *pdu_co_handlers[] = { [P9_TRENAME] = v9fs_rename, [P9_TLOCK] = v9fs_lock, [P9_TGETLOCK] = v9fs_getlock, + [P9_TRENAMEAT] = v9fs_renameat, [P9_TREADLINK] = v9fs_readlink, + [P9_TUNLINKAT] = v9fs_unlinkat, [P9_TMKDIR] = v9fs_mkdir, [P9_TVERSION] = v9fs_version, [P9_TLOPEN] = v9fs_open, diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 9d1b508e16..17d44b41ca 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -50,6 +50,10 @@ enum { P9_RLINK, P9_TMKDIR = 72, P9_RMKDIR, + P9_TRENAMEAT = 74, + P9_RRENAMEAT, + P9_TUNLINKAT = 76, + P9_RUNLINKAT, P9_TVERSION = 100, P9_RVERSION, P9_TAUTH = 102, diff --git a/hw/fdc.c b/hw/fdc.c index 1d44bbd1e3..433af73ad7 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -36,7 +36,6 @@ #include "qdev-addr.h" #include "blockdev.h" #include "sysemu.h" -#include "block_int.h" /********************************************************/ /* debug Floppy devices */ @@ -1778,7 +1777,7 @@ static void fdctrl_result_timer(void *opaque) fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); } -static void fdctrl_change_cb(void *opaque) +static void fdctrl_change_cb(void *opaque, bool load) { FDrive *drive = opaque; @@ -1813,7 +1812,6 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl) fd_revalidate(drive); if (drive->bs) { drive->media_changed = 1; - bdrv_set_removable(drive->bs, 1); bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive); } } diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index f4fa1545bd..a8659cf8b9 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -754,7 +754,6 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, case READ_FPDMA_QUEUED: DPRINTF(port, "NCQ reading %d sectors from LBA %ld, tag %d\n", ncq_tfs->sector_count-1, ncq_tfs->lba, ncq_tfs->tag); - ncq_tfs->is_read = 1; DPRINTF(port, "tag %d aio read %ld\n", ncq_tfs->tag, ncq_tfs->lba); @@ -768,7 +767,6 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, case WRITE_FPDMA_QUEUED: DPRINTF(port, "NCQ writing %d sectors to LBA %ld, tag %d\n", ncq_tfs->sector_count-1, ncq_tfs->lba, ncq_tfs->tag); - ncq_tfs->is_read = 0; DPRINTF(port, "tag %d aio write %ld\n", ncq_tfs->tag, ncq_tfs->lba); diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index 3c29d93b47..5de986c90f 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -259,7 +259,6 @@ typedef struct NCQTransferState { BlockDriverAIOCB *aiocb; QEMUSGList sglist; BlockAcctCookie acct; - int is_read; uint16_t sector_count; uint64_t lba; uint8_t tag; diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index f38d2896ae..3f909c3a99 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -73,7 +73,7 @@ static void lba_to_msf(uint8_t *buf, int lba) static inline int media_present(IDEState *s) { - return (s->nb_sectors > 0); + return !s->tray_open && s->nb_sectors > 0; } /* XXX: DVDs that could fit on a CD will be reported as a CD */ @@ -521,7 +521,7 @@ static unsigned int event_status_media(IDEState *s, uint8_t event_code, media_status; media_status = 0; - if (s->bs->tray_open) { + if (s->tray_open) { media_status = MS_TRAY_OPEN; } else if (bdrv_is_inserted(s->bs)) { media_status = MS_MEDIA_PRESENT; @@ -788,8 +788,9 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf) buf[12] = 0x71; buf[13] = 3 << 5; buf[14] = (1 << 0) | (1 << 3) | (1 << 5); - if (bdrv_is_locked(s->bs)) + if (s->tray_locked) { buf[6] |= 1 << 1; + } buf[15] = 0x00; cpu_to_ube16(&buf[16], 706); buf[18] = 0; @@ -831,7 +832,8 @@ static void cmd_test_unit_ready(IDEState *s, uint8_t *buf) static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf) { - bdrv_set_locked(s->bs, buf[4] & 1); + s->tray_locked = buf[4] & 1; + bdrv_lock_medium(s->bs, buf[4] & 1); ide_atapi_cmd_ok(s); } @@ -903,29 +905,22 @@ static void cmd_seek(IDEState *s, uint8_t* buf) static void cmd_start_stop_unit(IDEState *s, uint8_t* buf) { - int start, eject, sense, err = 0; - start = buf[4] & 1; - eject = (buf[4] >> 1) & 1; - - if (eject) { - err = bdrv_eject(s->bs, !start); - } - - switch (err) { - case 0: - ide_atapi_cmd_ok(s); - break; - case -EBUSY: - sense = SENSE_NOT_READY; - if (bdrv_is_inserted(s->bs)) { - sense = SENSE_ILLEGAL_REQUEST; + int sense; + bool start = buf[4] & 1; + bool loej = buf[4] & 2; /* load on start, eject on !start */ + + if (loej) { + if (!start && !s->tray_open && s->tray_locked) { + sense = bdrv_is_inserted(s->bs) + ? SENSE_NOT_READY : SENSE_ILLEGAL_REQUEST; + ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED); + return; } - ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED); - break; - default: - ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - break; + bdrv_eject(s->bs, !start); + s->tray_open = !start; } + + ide_atapi_cmd_ok(s); } static void cmd_mechanism_status(IDEState *s, uint8_t* buf) @@ -1073,20 +1068,21 @@ static const struct { [ 0x03 ] = { cmd_request_sense, ALLOW_UA }, [ 0x12 ] = { cmd_inquiry, ALLOW_UA }, [ 0x1a ] = { cmd_mode_sense, /* (6) */ 0 }, - [ 0x1b ] = { cmd_start_stop_unit, 0 }, + [ 0x1b ] = { cmd_start_stop_unit, 0 }, /* [1] */ [ 0x1e ] = { cmd_prevent_allow_medium_removal, 0 }, [ 0x25 ] = { cmd_read_cdvd_capacity, CHECK_READY }, - [ 0x28 ] = { cmd_read, /* (10) */ 0 }, + [ 0x28 ] = { cmd_read, /* (10) */ CHECK_READY }, [ 0x2b ] = { cmd_seek, CHECK_READY }, [ 0x43 ] = { cmd_read_toc_pma_atip, CHECK_READY }, [ 0x46 ] = { cmd_get_configuration, ALLOW_UA }, [ 0x4a ] = { cmd_get_event_status_notification, ALLOW_UA }, [ 0x5a ] = { cmd_mode_sense, /* (10) */ 0 }, - [ 0xa8 ] = { cmd_read, /* (12) */ 0 }, - [ 0xad ] = { cmd_read_dvd_structure, 0 }, + [ 0xa8 ] = { cmd_read, /* (12) */ CHECK_READY }, + [ 0xad ] = { cmd_read_dvd_structure, CHECK_READY }, [ 0xbb ] = { cmd_set_speed, 0 }, [ 0xbd ] = { cmd_mechanism_status, 0 }, - [ 0xbe ] = { cmd_read_cd, 0 }, + [ 0xbe ] = { cmd_read_cd, CHECK_READY }, + /* [1] handler detects and reports not ready condition itself */ }; void ide_atapi_cmd(IDEState *s) @@ -1122,7 +1118,7 @@ void ide_atapi_cmd(IDEState *s) * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close * states rely on this behavior. */ - if (bdrv_is_inserted(s->bs) && s->cdrom_changed) { + if (!s->tray_open && bdrv_is_inserted(s->bs) && s->cdrom_changed) { ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); s->cdrom_changed = 0; diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 4d91e2c642..5fe98b1bb3 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -27,7 +27,6 @@ #include <hw/pci.h> #include <hw/isa.h> #include "block.h" -#include "block_int.h" #include "sysemu.h" #include "dma.h" diff --git a/hw/ide/core.c b/hw/ide/core.c index 1806e008bc..9297b9e657 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -30,6 +30,7 @@ #include "sysemu.h" #include "dma.h" #include "blockdev.h" +#include "block_int.h" #include <hw/ide/internal.h> @@ -783,11 +784,12 @@ static void ide_cfata_metadata_write(IDEState *s) } /* called when the inserted state of the media has changed */ -static void ide_cd_change_cb(void *opaque) +static void ide_cd_change_cb(void *opaque, bool load) { IDEState *s = opaque; uint64_t nb_sectors; + s->tray_open = !load; bdrv_get_geometry(s->bs, &nb_sectors); s->nb_sectors = nb_sectors; @@ -901,6 +903,78 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) } } +#define HD_OK (1u << IDE_HD) +#define CD_OK (1u << IDE_CD) +#define CFA_OK (1u << IDE_CFATA) +#define HD_CFA_OK (HD_OK | CFA_OK) +#define ALL_OK (HD_OK | CD_OK | CFA_OK) + +/* See ACS-2 T13/2015-D Table B.2 Command codes */ +static const uint8_t ide_cmd_table[0x100] = { + /* NOP not implemented, mandatory for CD */ + [CFA_REQ_EXT_ERROR_CODE] = CFA_OK, + [WIN_DSM] = ALL_OK, + [WIN_DEVICE_RESET] = CD_OK, + [WIN_RECAL] = HD_CFA_OK, + [WIN_READ] = ALL_OK, + [WIN_READ_ONCE] = ALL_OK, + [WIN_READ_EXT] = HD_CFA_OK, + [WIN_READDMA_EXT] = HD_CFA_OK, + [WIN_READ_NATIVE_MAX_EXT] = HD_CFA_OK, + [WIN_MULTREAD_EXT] = HD_CFA_OK, + [WIN_WRITE] = HD_CFA_OK, + [WIN_WRITE_ONCE] = HD_CFA_OK, + [WIN_WRITE_EXT] = HD_CFA_OK, + [WIN_WRITEDMA_EXT] = HD_CFA_OK, + [CFA_WRITE_SECT_WO_ERASE] = CFA_OK, + [WIN_MULTWRITE_EXT] = HD_CFA_OK, + [WIN_WRITE_VERIFY] = HD_CFA_OK, + [WIN_VERIFY] = HD_CFA_OK, + [WIN_VERIFY_ONCE] = HD_CFA_OK, + [WIN_VERIFY_EXT] = HD_CFA_OK, + [WIN_SEEK] = HD_CFA_OK, + [CFA_TRANSLATE_SECTOR] = CFA_OK, + [WIN_DIAGNOSE] = ALL_OK, + [WIN_SPECIFY] = HD_CFA_OK, + [WIN_STANDBYNOW2] = ALL_OK, + [WIN_IDLEIMMEDIATE2] = ALL_OK, + [WIN_STANDBY2] = ALL_OK, + [WIN_SETIDLE2] = ALL_OK, + [WIN_CHECKPOWERMODE2] = ALL_OK, + [WIN_SLEEPNOW2] = ALL_OK, + [WIN_PACKETCMD] = CD_OK, + [WIN_PIDENTIFY] = CD_OK, + [WIN_SMART] = HD_CFA_OK, + [CFA_ACCESS_METADATA_STORAGE] = CFA_OK, + [CFA_ERASE_SECTORS] = CFA_OK, + [WIN_MULTREAD] = HD_CFA_OK, + [WIN_MULTWRITE] = HD_CFA_OK, + [WIN_SETMULT] = HD_CFA_OK, + [WIN_READDMA] = HD_CFA_OK, + [WIN_READDMA_ONCE] = HD_CFA_OK, + [WIN_WRITEDMA] = HD_CFA_OK, + [WIN_WRITEDMA_ONCE] = HD_CFA_OK, + [CFA_WRITE_MULTI_WO_ERASE] = CFA_OK, + [WIN_STANDBYNOW1] = ALL_OK, + [WIN_IDLEIMMEDIATE] = ALL_OK, + [WIN_STANDBY] = ALL_OK, + [WIN_SETIDLE1] = ALL_OK, + [WIN_CHECKPOWERMODE1] = ALL_OK, + [WIN_SLEEPNOW1] = ALL_OK, + [WIN_FLUSH_CACHE] = ALL_OK, + [WIN_FLUSH_CACHE_EXT] = HD_CFA_OK, + [WIN_IDENTIFY] = ALL_OK, + [WIN_SETFEATURES] = ALL_OK, + [IBM_SENSE_CONDITION] = CFA_OK, + [CFA_WEAR_LEVEL] = CFA_OK, + [WIN_READ_NATIVE_MAX] = ALL_OK, +}; + +static bool ide_cmd_permitted(IDEState *s, uint32_t cmd) +{ + return cmd < ARRAY_SIZE(ide_cmd_table) + && (ide_cmd_table[cmd] & (1u << s->drive_kind)); +} void ide_exec_cmd(IDEBus *bus, uint32_t val) { @@ -920,6 +994,10 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) if ((s->status & (BUSY_STAT|DRQ_STAT)) && val != WIN_DEVICE_RESET) return; + if (!ide_cmd_permitted(s, val)) { + goto abort_cmd; + } + switch(val) { case WIN_DSM: switch (s->feature) { @@ -983,8 +1061,10 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) lba48 = 1; case WIN_READ: case WIN_READ_ONCE: - if (!s->bs) + if (s->drive_kind == IDE_CD) { + ide_set_signature(s); /* odd, but ATA4 8.27.5.2 requires it */ goto abort_cmd; + } ide_cmd_lba48_transform(s, lba48); s->req_nb_sectors = 1; ide_sector_read(s); @@ -1138,21 +1218,15 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) ide_set_irq(s->bus); break; case WIN_SEEK: - if(s->drive_kind == IDE_CD) - goto abort_cmd; /* XXX: Check that seek is within bounds */ s->status = READY_STAT | SEEK_STAT; ide_set_irq(s->bus); break; /* ATAPI commands */ case WIN_PIDENTIFY: - if (s->drive_kind == IDE_CD) { - ide_atapi_identify(s); - s->status = READY_STAT | SEEK_STAT; - ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); - } else { - ide_abort_command(s); - } + ide_atapi_identify(s); + s->status = READY_STAT | SEEK_STAT; + ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); ide_set_irq(s->bus); break; case WIN_DIAGNOSE: @@ -1169,15 +1243,11 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) ide_set_irq(s->bus); break; case WIN_DEVICE_RESET: - if (s->drive_kind != IDE_CD) - goto abort_cmd; ide_set_signature(s); s->status = 0x00; /* NOTE: READY is _not_ set */ s->error = 0x01; break; case WIN_PACKETCMD: - if (s->drive_kind != IDE_CD) - goto abort_cmd; /* overlapping commands not supported */ if (s->feature & 0x02) goto abort_cmd; @@ -1189,16 +1259,12 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) break; /* CF-ATA commands */ case CFA_REQ_EXT_ERROR_CODE: - if (s->drive_kind != IDE_CFATA) - goto abort_cmd; s->error = 0x09; /* miscellaneous error */ s->status = READY_STAT | SEEK_STAT; ide_set_irq(s->bus); break; case CFA_ERASE_SECTORS: case CFA_WEAR_LEVEL: - if (s->drive_kind != IDE_CFATA) - goto abort_cmd; if (val == CFA_WEAR_LEVEL) s->nsector = 0; if (val == CFA_ERASE_SECTORS) @@ -1208,8 +1274,6 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) ide_set_irq(s->bus); break; case CFA_TRANSLATE_SECTOR: - if (s->drive_kind != IDE_CFATA) - goto abort_cmd; s->error = 0x00; s->status = READY_STAT | SEEK_STAT; memset(s->io_buffer, 0, 0x200); @@ -1228,8 +1292,6 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) ide_set_irq(s->bus); break; case CFA_ACCESS_METADATA_STORAGE: - if (s->drive_kind != IDE_CFATA) - goto abort_cmd; switch (s->feature) { case 0x02: /* Inquiry Metadata Storage */ ide_cfata_metadata_inquiry(s); @@ -1248,8 +1310,6 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) ide_set_irq(s->bus); break; case IBM_SENSE_CONDITION: - if (s->drive_kind != IDE_CFATA) - goto abort_cmd; switch (s->feature) { case 0x01: /* sense temperature in device */ s->nsector = 0x50; /* +20 C */ @@ -1262,8 +1322,6 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) break; case WIN_SMART: - if (s->drive_kind == IDE_CD) - goto abort_cmd; if (s->hcyl != 0xc2 || s->lcyl != 0x4f) goto abort_cmd; if (!s->smart_enabled && s->feature != SMART_ENABLE) @@ -1418,6 +1476,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) } break; default: + /* should not be reachable */ abort_cmd: ide_abort_command(s); ide_set_irq(s->bus); @@ -1738,8 +1797,20 @@ void ide_bus_reset(IDEBus *bus) bus->dma->ops->reset(bus->dma); } +static bool ide_cd_is_tray_open(void *opaque) +{ + return ((IDEState *)opaque)->tray_open; +} + +static bool ide_cd_is_medium_locked(void *opaque) +{ + return ((IDEState *)opaque)->tray_locked; +} + static const BlockDevOps ide_cd_block_ops = { .change_media_cb = ide_cd_change_cb, + .is_tray_open = ide_cd_is_tray_open, + .is_medium_locked = ide_cd_is_medium_locked, }; int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, @@ -1777,7 +1848,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, s->smart_selftest_count = 0; if (kind == IDE_CD) { bdrv_set_dev_ops(bs, &ide_cd_block_ops, s); - bs->buffer_alignment = 2048; + bdrv_set_buffer_alignment(bs, 2048); } else { if (!bdrv_is_inserted(s->bs)) { error_report("Device needs media, but drive is empty"); @@ -1801,7 +1872,6 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, } ide_reset(s); - bdrv_set_removable(bs, s->drive_kind == IDE_CD); return 0; } @@ -1995,6 +2065,22 @@ static bool ide_drive_pio_state_needed(void *opaque) || (s->bus->error_status & BM_STATUS_PIO_RETRY); } +static int ide_tray_state_post_load(void *opaque, int version_id) +{ + IDEState *s = opaque; + + bdrv_eject(s->bs, s->tray_open); + bdrv_lock_medium(s->bs, s->tray_locked); + return 0; +} + +static bool ide_tray_state_needed(void *opaque) +{ + IDEState *s = opaque; + + return s->tray_open || s->tray_locked; +} + static bool ide_atapi_gesn_needed(void *opaque) { IDEState *s = opaque; @@ -2022,6 +2108,19 @@ static const VMStateDescription vmstate_ide_atapi_gesn_state = { } }; +static const VMStateDescription vmstate_ide_tray_state = { + .name = "ide_drive/tray_state", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .post_load = ide_tray_state_post_load, + .fields = (VMStateField[]) { + VMSTATE_BOOL(tray_open, IDEState), + VMSTATE_BOOL(tray_locked, IDEState), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_ide_drive_pio_state = { .name = "ide_drive/pio_state", .version_id = 1, @@ -2076,6 +2175,9 @@ const VMStateDescription vmstate_ide_drive = { .vmsd = &vmstate_ide_drive_pio_state, .needed = ide_drive_pio_state_needed, }, { + .vmsd = &vmstate_ide_tray_state, + .needed = ide_tray_state_needed, + }, { .vmsd = &vmstate_ide_atapi_gesn_state, .needed = ide_atapi_gesn_needed, }, { diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 5278bc4d6c..0327d0ee72 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -66,7 +66,6 @@ #include <hw/pci.h> #include <hw/isa.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/pci.h> diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 111785294d..233915ce0d 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -7,7 +7,6 @@ * non-internal declarations are in hw/ide.h */ #include <hw/ide.h> -#include "block_int.h" #include "iorange.h" #include "dma.h" @@ -442,6 +441,8 @@ struct IDEState { struct unreported_events events; uint8_t sense_key; uint8_t asc; + bool tray_open; + bool tray_locked; uint8_t cdrom_changed; int packet_transfer_size; int elementary_transfer_size; diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 4ac745324c..28b69d2cc3 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -26,7 +26,6 @@ #include <hw/pc.h> #include <hw/isa.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/macio.c b/hw/ide/macio.c index fdf5d75082..c1844cb738 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -26,7 +26,6 @@ #include <hw/ppc_mac.h> #include <hw/mac_dbdma.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 91c0e3c89d..9eee5b50ba 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -26,7 +26,6 @@ #include <hw/pc.h> #include <hw/pcmcia.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index 132b7517ba..2ec21b0163 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -24,7 +24,6 @@ */ #include <hw/hw.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/pci.c b/hw/ide/pci.c index d1a14d7cc1..9fded02954 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -27,7 +27,6 @@ #include <hw/pci.h> #include <hw/isa.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/pci.h> diff --git a/hw/ide/via.c b/hw/ide/via.c index c0b9d43827..dab8a39f57 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -28,7 +28,6 @@ #include <hw/pci.h> #include <hw/isa.h> #include "block.h" -#include "block_int.h" #include "sysemu.h" #include "dma.h" diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index ac284e9609..dbb3bdf2ce 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -15,7 +15,6 @@ #include "hw.h" #include "pci.h" #include "scsi.h" -#include "block_int.h" //#define DEBUG_LSI //#define DEBUG_LSI_REG diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 59d6adafa0..02482947ca 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -772,6 +772,11 @@ const struct SCSISense sense_code_NO_MEDIUM = { .key = NOT_READY, .asc = 0x3a, .ascq = 0x00 }; +/* LUN not ready, medium removal prevented */ +const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED = { + .key = NOT_READY, .asc = 0x53, .ascq = 0x00 +}; + /* Hardware error, internal target failure */ const struct SCSISense sense_code_TARGET_FAILURE = { .key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00 @@ -807,6 +812,11 @@ const struct SCSISense sense_code_INCOMPATIBLE_MEDIUM = { .key = ILLEGAL_REQUEST, .asc = 0x30, .ascq = 0x00 }; +/* Illegal request, medium removal prevented */ +const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = { + .key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x00 +}; + /* Command aborted, I/O process terminated */ const struct SCSISense sense_code_IO_ERROR = { .key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06 diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 9724d0fe9a..4a60820b18 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -37,6 +37,7 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #include "scsi-defs.h" #include "sysemu.h" #include "blockdev.h" +#include "block_int.h" #define SCSI_DMA_BUF_SIZE 131072 #define SCSI_MAX_INQUIRY_LEN 256 @@ -72,6 +73,8 @@ struct SCSIDiskState QEMUBH *bh; char *version; char *serial; + bool tray_open; + bool tray_locked; }; static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type); @@ -182,6 +185,9 @@ static void scsi_read_data(SCSIRequest *req) if (n > SCSI_DMA_BUF_SIZE / 512) n = SCSI_DMA_BUF_SIZE / 512; + if (s->tray_open) { + scsi_read_complete(r, -ENOMEDIUM); + } r->iov.iov_len = n * 512; qemu_iovec_init_external(&r->qiov, &r->iov, 1); @@ -280,6 +286,9 @@ static void scsi_write_data(SCSIRequest *req) n = r->iov.iov_len / 512; if (n) { + if (s->tray_open) { + scsi_write_complete(r, -ENOMEDIUM); + } qemu_iovec_init_external(&r->qiov, &r->iov, 1); bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE); @@ -664,7 +673,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf, p[5] = 0xff; /* CD DA, DA accurate, RW supported, RW corrected, C2 errors, ISRC, UPC, Bar code */ - p[6] = 0x2d | (bdrv_is_locked(s->bs)? 2 : 0); + p[6] = 0x2d | (s->tray_locked ? 2 : 0); /* Locking supported, jumper present, eject, tray */ p[7] = 0; /* no volume & mute control, no changer */ @@ -814,6 +823,27 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf) return toclen; } +static int scsi_disk_emulate_start_stop(SCSIDiskReq *r) +{ + SCSIRequest *req = &r->req; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); + bool start = req->cmd.buf[4] & 1; + bool loej = req->cmd.buf[4] & 2; /* load on start, eject on !start */ + + if (s->qdev.type == TYPE_ROM && loej) { + if (!start && !s->tray_open && s->tray_locked) { + scsi_check_condition(r, + bdrv_is_inserted(s->bs) + ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED) + : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED)); + return -1; + } + bdrv_eject(s->bs, !start); + s->tray_open = !start; + } + return 0; +} + static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) { SCSIRequest *req = &r->req; @@ -823,7 +853,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) switch (req->cmd.buf[0]) { case TEST_UNIT_READY: - if (!bdrv_is_inserted(s->bs)) + if (s->tray_open || !bdrv_is_inserted(s->bs)) goto not_ready; break; case INQUIRY: @@ -859,13 +889,13 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) goto illegal_request; break; case START_STOP: - if (s->qdev.type == TYPE_ROM && (req->cmd.buf[4] & 2)) { - /* load/eject medium */ - bdrv_eject(s->bs, !(req->cmd.buf[4] & 1)); + if (scsi_disk_emulate_start_stop(r) < 0) { + return -1; } break; case ALLOW_MEDIUM_REMOVAL: - bdrv_set_locked(s->bs, req->cmd.buf[4] & 1); + s->tray_locked = req->cmd.buf[4] & 1; + bdrv_lock_medium(s->bs, req->cmd.buf[4] & 1); break; case READ_CAPACITY_10: /* The normal LEN field for this command is zero. */ @@ -946,7 +976,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) return buflen; not_ready: - if (!bdrv_is_inserted(s->bs)) { + if (s->tray_open || !bdrv_is_inserted(s->bs)) { scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); } else { scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY)); @@ -1143,6 +1173,27 @@ static void scsi_destroy(SCSIDevice *dev) blockdev_mark_auto_del(s->qdev.conf.bs); } +static void scsi_cd_change_media_cb(void *opaque, bool load) +{ + ((SCSIDiskState *)opaque)->tray_open = !load; +} + +static bool scsi_cd_is_tray_open(void *opaque) +{ + return ((SCSIDiskState *)opaque)->tray_open; +} + +static bool scsi_cd_is_medium_locked(void *opaque) +{ + return ((SCSIDiskState *)opaque)->tray_locked; +} + +static const BlockDevOps scsi_cd_block_ops = { + .change_media_cb = scsi_cd_change_media_cb, + .is_tray_open = scsi_cd_is_tray_open, + .is_medium_locked = scsi_cd_is_medium_locked, +}; + static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); @@ -1177,6 +1228,7 @@ static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type) } if (scsi_type == TYPE_ROM) { + bdrv_set_dev_ops(s->bs, &scsi_cd_block_ops, s); s->qdev.blocksize = 2048; } else if (scsi_type == TYPE_DISK) { s->qdev.blocksize = s->qdev.conf.logical_block_size; @@ -1185,11 +1237,10 @@ static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type) return -1; } s->cluster_size = s->qdev.blocksize / 512; - s->bs->buffer_alignment = s->qdev.blocksize; + bdrv_set_buffer_alignment(s->bs, s->qdev.blocksize); s->qdev.type = scsi_type; qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s); - bdrv_set_removable(s->bs, scsi_type == TYPE_ROM); add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0"); return 0; } diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index cb5d4f125d..5ce01afdce 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -450,7 +450,6 @@ static int scsi_generic_initfn(SCSIDevice *dev) } } DPRINTF("block size %d\n", s->qdev.blocksize); - bdrv_set_removable(s->bs, 0); return 0; } diff --git a/hw/scsi.h b/hw/scsi.h index 98fd689859..e8dcabfa28 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -3,7 +3,6 @@ #include "qdev.h" #include "block.h" -#include "block_int.h" #define MAX_SCSI_DEVS 255 @@ -136,6 +135,8 @@ extern const struct SCSISense sense_code_NO_SENSE; extern const struct SCSISense sense_code_LUN_NOT_READY; /* LUN not ready, Medium not present */ extern const struct SCSISense sense_code_NO_MEDIUM; +/* LUN not ready, medium removal prevented */ +extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED; /* Hardware error, internal target failure */ extern const struct SCSISense sense_code_TARGET_FAILURE; /* Illegal request, invalid command operation code */ @@ -150,6 +151,8 @@ extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED; extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED; /* Illegal request, Incompatible format */ extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT; +/* Illegal request, medium removal prevented */ +extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED; /* Command aborted, I/O process terminated */ extern const struct SCSISense sense_code_IO_ERROR; /* Command aborted, I_T Nexus loss occurred */ diff --git a/hw/sd.c b/hw/sd.c index 1af62b23c6..10e26ade58 100644 --- a/hw/sd.c +++ b/hw/sd.c @@ -419,7 +419,7 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv) sd->pwd_len = 0; } -static void sd_cardchange(void *opaque) +static void sd_cardchange(void *opaque, bool load) { SDState *sd = opaque; diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index d5d4757f62..c2ee0001eb 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -599,9 +599,8 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf, s->qdev = dev; register_savevm(dev, "virtio-blk", virtio_blk_id++, 2, virtio_blk_save, virtio_blk_load, s); - bdrv_set_removable(s->bs, 0); bdrv_set_dev_ops(s->bs, &virtio_block_ops, s); - s->bs->buffer_alignment = conf->logical_block_size; + bdrv_set_buffer_alignment(s->bs, conf->logical_block_size); add_boot_device_path(conf->bootindex, dev, "/disk@0,0"); diff --git a/hw/virtio.h b/hw/virtio.h index c1292647fe..4d20d9b8f4 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -18,7 +18,7 @@ #include "net.h" #include "qdev.h" #include "sysemu.h" -#include "block_int.h" +#include "block.h" #include "event_notifier.h" #ifdef CONFIG_LINUX #include "9p.h" diff --git a/nbd.c b/nbd.c index e7a585dcb0..6d81cfbcd0 100644 --- a/nbd.c +++ b/nbd.c @@ -17,6 +17,7 @@ */ #include "nbd.h" +#include "block.h" #include <errno.h> #include <string.h> diff --git a/nbd.h b/nbd.h index 273cfa1af4..df7b7af7c0 100644 --- a/nbd.h +++ b/nbd.h @@ -23,8 +23,6 @@ #include "qemu-common.h" -#include "block_int.h" - struct nbd_request { uint32_t magic; uint32_t type; diff --git a/qmp-commands.hx b/qmp-commands.hx index 27cc66ebc9..d1c2c5905d 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1131,6 +1131,8 @@ Each json-object contain the following: - Possible values: "unknown" - "removable": true if the device is removable, false otherwise (json-bool) - "locked": true if the device is locked, false otherwise (json-bool) +- "tray-open": only present if removable, true if the device has a tray, + and it is open (json-bool) - "inserted": only present if the device is inserted, it is a json-object containing the following: - "file": device file name (json-string) diff --git a/trace-events b/trace-events index a8e76841a4..8bed3bea7a 100644 --- a/trace-events +++ b/trace-events @@ -62,7 +62,7 @@ bdrv_aio_multiwrite_latefail(void *mcb, int i) "mcb %p i %d" bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p" bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" -bdrv_set_locked(void *bs, int locked) "bs %p locked %d" +bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d" bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" bdrv_co_io(int is_write, void *acb) "is_write %d acb %p" |