Message ID | 1410891148-28849-23-git-send-email-armbru@redhat.com |
---|---|
State | New |
Headers | show |
On Tue, Sep 16, 2014 at 08:12:27PM +0200, Markus Armbruster wrote: > Move device model attachment / detachment and the BlockDevOps device > model callbacks and their wrappers from BlockDriverState to > BlockBackend. > > Signed-off-by: Markus Armbruster <armbru@redhat.com> > --- > block.c | 126 ++++------------------------------ > block/block-backend.c | 151 ++++++++++++++++++++++++++++++++++++++--- > block/qapi.c | 8 +-- > blockdev.c | 8 +-- > include/block/block.h | 45 ------------ > include/block/block_int.h | 12 ++-- > include/sysemu/block-backend.h | 35 ++++++++++ > 7 files changed, 203 insertions(+), 182 deletions(-) > > diff --git a/block.c b/block.c > index 1d9a680..fac1211 100644 > --- a/block.c > +++ b/block.c > @@ -58,9 +58,6 @@ struct BdrvDirtyBitmap { > > #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */ > > -#define COROUTINE_POOL_RESERVATION 64 /* number of coroutines to reserve */ > - > -static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load); > static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, > int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, > BlockCompletionFunc *cb, void *opaque); > @@ -1527,7 +1524,9 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, > } > > if (!bdrv_key_required(bs)) { > - bdrv_dev_change_media_cb(bs, true); > + if (bs->blk) { > + blk_dev_change_media_cb(bs->blk, true); > + } > } else if (!runstate_check(RUN_STATE_PRELAUNCH) > && !runstate_check(RUN_STATE_INMIGRATE) > && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */ > @@ -1852,7 +1851,9 @@ void bdrv_close(BlockDriverState *bs) > } > } > > - bdrv_dev_change_media_cb(bs, false); > + if (bs->blk) { > + blk_dev_change_media_cb(bs->blk, false); > + } > > /*throttling disk I/O limits*/ > if (bs->io_limits_enabled) { > @@ -1971,9 +1972,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, > /* move some fields that need to stay attached to the device */ > > /* dev info */ > - bs_dest->dev_ops = bs_src->dev_ops; > - bs_dest->dev_opaque = bs_src->dev_opaque; > - bs_dest->dev = bs_src->dev; > bs_dest->guest_block_size = bs_src->guest_block_size; > bs_dest->copy_on_read = bs_src->copy_on_read; > > @@ -2041,7 +2039,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) > assert(!bs_new->blk); > assert(QLIST_EMPTY(&bs_new->dirty_bitmaps)); > assert(bs_new->job == NULL); > - assert(bs_new->dev == NULL); > assert(bs_new->io_limits_enabled == false); > assert(!throttle_have_timer(&bs_new->throttle_state)); > > @@ -2058,7 +2055,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) > assert(!bs_new->blk); > > /* Check a few fields that should remain attached to the device */ > - assert(bs_new->dev == NULL); > assert(bs_new->job == NULL); > assert(bs_new->io_limits_enabled == false); > assert(!throttle_have_timer(&bs_new->throttle_state)); > @@ -2097,7 +2093,6 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top) > > static void bdrv_delete(BlockDriverState *bs) > { > - assert(!bs->dev); > assert(!bs->job); > assert(bdrv_op_blocker_is_empty(bs)); > assert(!bs->refcnt); > @@ -2111,105 +2106,6 @@ static void bdrv_delete(BlockDriverState *bs) > g_free(bs); > } > > -int bdrv_attach_dev(BlockDriverState *bs, void *dev) > -/* TODO change to DeviceState *dev when all users are qdevified */ > -{ > - if (bs->dev) { > - return -EBUSY; > - } > - bs->dev = dev; > - bdrv_iostatus_reset(bs); > - > - /* We're expecting I/O from the device so bump up coroutine pool size */ > - qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION); > - return 0; > -} > - > -/* TODO qdevified devices don't use this, remove when devices are qdevified */ > -void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev) > -{ > - if (bdrv_attach_dev(bs, dev) < 0) { > - abort(); > - } > -} > - > -void bdrv_detach_dev(BlockDriverState *bs, void *dev) > -/* TODO change to DeviceState *dev when all users are qdevified */ > -{ > - assert(bs->dev == dev); > - bs->dev = NULL; > - bs->dev_ops = NULL; > - bs->dev_opaque = NULL; > - bs->guest_block_size = 512; > - qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION); > -} > - > -/* TODO change to return DeviceState * when all users are qdevified */ > -void *bdrv_get_attached_dev(BlockDriverState *bs) > -{ > - return bs->dev; > -} > - > -void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, > - void *opaque) > -{ > - bs->dev_ops = ops; > - bs->dev_opaque = opaque; > -} > - > -static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load) > -{ > - if (bs->dev_ops && bs->dev_ops->change_media_cb) { > - bool tray_was_closed = !bdrv_dev_is_tray_open(bs); > - bs->dev_ops->change_media_cb(bs->dev_opaque, load); > - if (tray_was_closed) { > - /* tray open */ > - qapi_event_send_device_tray_moved(bdrv_get_device_name(bs), > - true, &error_abort); > - } > - if (load) { > - /* tray close */ > - qapi_event_send_device_tray_moved(bdrv_get_device_name(bs), > - false, &error_abort); > - } > - } > -} > - > -bool bdrv_dev_has_removable_media(BlockDriverState *bs) > -{ > - return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb); > -} > - > -void bdrv_dev_eject_request(BlockDriverState *bs, bool force) > -{ > - if (bs->dev_ops && bs->dev_ops->eject_request_cb) { > - bs->dev_ops->eject_request_cb(bs->dev_opaque, force); > - } > -} > - > -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) > -{ > - if (bs->dev_ops && bs->dev_ops->resize_cb) { > - bs->dev_ops->resize_cb(bs->dev_opaque); > - } > -} > - > -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 > * > @@ -3543,7 +3439,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset) > ret = drv->bdrv_truncate(bs, offset); > if (ret == 0) { > ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); > - bdrv_dev_resize_cb(bs); > + if (bs->blk) { > + blk_dev_resize_cb(bs->blk); > + } > } > return ret; > } > @@ -3744,8 +3642,10 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) > bs->valid_key = 0; > } 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, true); > + if (bs->blk) { > + /* call the change callback now, we skipped it on open */ > + blk_dev_change_media_cb(bs->blk, true); > + } > } > return ret; > } > diff --git a/block/block-backend.c b/block/block-backend.c > index b55f0b4..d49c988 100644 > --- a/block/block-backend.c > +++ b/block/block-backend.c > @@ -13,6 +13,10 @@ > #include "sysemu/block-backend.h" > #include "block/block_int.h" > #include "sysemu/blockdev.h" > +#include "qapi-event.h" > + > +/* Number of coroutines to reserve per attached device model */ > +#define COROUTINE_POOL_RESERVATION 64 > > struct BlockBackend { > char *name; > @@ -20,6 +24,11 @@ struct BlockBackend { > BlockDriverState *bs; > DriveInfo *legacy_dinfo; > QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */ > + > + void *dev; /* attached device model, if any */ > + /* TODO change to DeviceState when all users are qdevified */ > + const BlockDevOps *dev_ops; > + void *dev_opaque; > }; > > static void drive_info_del(DriveInfo *dinfo); > @@ -81,6 +90,7 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp) > static void blk_delete(BlockBackend *blk) > { > assert(!blk->refcnt); > + assert(!blk->dev); > if (blk->bs) { > assert(blk->bs->blk == blk); > blk->bs->blk = NULL; > @@ -233,34 +243,153 @@ void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk) > } > } > > -void blk_iostatus_enable(BlockBackend *blk) > -{ > - bdrv_iostatus_enable(blk->bs); > -} > - > +/* > + * Attach device model @dev to @blk. > + * Return 0 on success, -EBUSY when a device model is attached already. > + */ > int blk_attach_dev(BlockBackend *blk, void *dev) > +/* TODO change to DeviceState *dev when all users are qdevified */ > { > - return bdrv_attach_dev(blk->bs, dev); > + if (blk->dev) { > + return -EBUSY; > + } > + blk->dev = dev; > + bdrv_iostatus_reset(blk->bs); > + > + /* We're expecting I/O from the device so bump up coroutine pool size */ > + qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION); > + return 0; > } > > +/* > + * Attach device model @dev to @blk. > + * @blk must not have a device model attached already. > + * TODO qdevified devices don't use this, remove when devices are qdevified > + */ > void blk_attach_dev_nofail(BlockBackend *blk, void *dev) > { > - bdrv_attach_dev_nofail(blk->bs, dev); > + if (blk_attach_dev(blk, dev) < 0) { > + abort(); > + } > } > > +/* > + * Detach device model @dev from @blk. > + * @dev must be currently attached to @blk. > + */ > void blk_detach_dev(BlockBackend *blk, void *dev) > +/* TODO change to DeviceState *dev when all users are qdevified */ > { > - bdrv_detach_dev(blk->bs, dev); > + assert(blk->dev == dev); > + blk->dev = NULL; > + blk->dev_ops = NULL; > + blk->dev_opaque = NULL; > + bdrv_set_guest_block_size(blk->bs, 512); > + qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION); > } > > +/* > + * Return the device model attached to @blk if any, else null. > + */ > void *blk_get_attached_dev(BlockBackend *blk) > +/* TODO change to return DeviceState * when all users are qdevified */ > { > - return bdrv_get_attached_dev(blk->bs); > + return blk->dev; > } > > -void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque) > +/* > + * Set @blk's device model callbacks to @ops. > + * @opaque is the opaque argument to pass to the callbacks. > + * This is for use by device models. > + */ > +void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, > + void *opaque) > { > - bdrv_set_dev_ops(blk->bs, ops, opaque); > + blk->dev_ops = ops; > + blk->dev_opaque = opaque; > +} > + > +/* > + * Notify @blk's attached device model of media change. > + * If @load is true, notify of media load. > + * Else, notify of media eject. > + * Also send DEVICE_TRAY_MOVED events as appropriate. > + */ > +void blk_dev_change_media_cb(BlockBackend *blk, bool load) > +{ > + if (blk->dev_ops && blk->dev_ops->change_media_cb) { > + bool tray_was_closed = !blk_dev_is_tray_open(blk); > + > + blk->dev_ops->change_media_cb(blk->dev_opaque, load); > + if (tray_was_closed) { > + /* tray open */ > + qapi_event_send_device_tray_moved(blk_name(blk), > + true, &error_abort); > + } > + if (load) { > + /* tray close */ > + qapi_event_send_device_tray_moved(blk_name(blk), > + false, &error_abort); > + } > + } > +} > + > +/* > + * Does @blk's attached device model have removable media? > + * %true if no device model is attached. > + */ > +bool blk_dev_has_removable_media(BlockBackend *blk) > +{ > + return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb); > +} > + > +/* > + * Notify @blk's attached device model of a media eject request. > + * If @force is true, the medium is about to be yanked out forcefully. > + */ > +void blk_dev_eject_request(BlockBackend *blk, bool force) > +{ > + if (blk->dev_ops && blk->dev_ops->eject_request_cb) { > + blk->dev_ops->eject_request_cb(blk->dev_opaque, force); > + } > +} > + > +/* > + * Does @blk's attached device model have a tray, and is it open? > + */ > +bool blk_dev_is_tray_open(BlockBackend *blk) > +{ > + if (blk->dev_ops && blk->dev_ops->is_tray_open) { > + return blk->dev_ops->is_tray_open(blk->dev_opaque); > + } > + return false; > +} > + > +/* > + * Does @blk's attached device model have the medium locked? > + * %false if the device model has no such lock. > + */ > +bool blk_dev_is_medium_locked(BlockBackend *blk) > +{ > + if (blk->dev_ops && blk->dev_ops->is_medium_locked) { > + return blk->dev_ops->is_medium_locked(blk->dev_opaque); > + } > + return false; > +} > + > +/* > + * Notify @blk's attached device model of a backend size change. > + */ > +void blk_dev_resize_cb(BlockBackend *blk) > +{ > + if (blk->dev_ops && blk->dev_ops->resize_cb) { > + blk->dev_ops->resize_cb(blk->dev_opaque); > + } > +} > + > +void blk_iostatus_enable(BlockBackend *blk) > +{ > + bdrv_iostatus_enable(blk->bs); > } > > int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, > diff --git a/block/qapi.c b/block/qapi.c > index fca981d..1301144 100644 > --- a/block/qapi.c > +++ b/block/qapi.c > @@ -275,12 +275,12 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, > Error *local_err = NULL; > info->device = g_strdup(blk_name(blk)); > info->type = g_strdup("unknown"); > - info->locked = bdrv_dev_is_medium_locked(bs); > - info->removable = bdrv_dev_has_removable_media(bs); > + info->locked = blk_dev_is_medium_locked(blk); > + info->removable = blk_dev_has_removable_media(blk); > > - if (bdrv_dev_has_removable_media(bs)) { > + if (blk_dev_has_removable_media(blk)) { > info->has_tray_open = true; > - info->tray_open = bdrv_dev_is_tray_open(bs); > + info->tray_open = blk_dev_is_tray_open(blk); > } > > if (bdrv_iostatus_is_enabled(bs)) { > diff --git a/blockdev.c b/blockdev.c > index e115bde..d3dccb9 100644 > --- a/blockdev.c > +++ b/blockdev.c > @@ -1509,14 +1509,14 @@ static void eject_device(BlockBackend *blk, int force, Error **errp) > if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { > return; > } > - if (!bdrv_dev_has_removable_media(bs)) { > + if (!blk_dev_has_removable_media(blk)) { > error_setg(errp, "Device '%s' is not removable", > bdrv_get_device_name(bs)); > return; > } > > - if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) { > - bdrv_dev_eject_request(bs, force); > + if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) { > + blk_dev_eject_request(blk, force); > if (!force) { > error_setg(errp, "Device '%s' is locked", > bdrv_get_device_name(bs)); > @@ -1753,7 +1753,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) > * can be removed. If this is a drive with no device backing > * then we can just get rid of the block driver state right here. > */ > - if (bdrv_get_attached_dev(bs)) { > + if (blk_get_attached_dev(blk)) { > blk_hide_on_behalf_of_do_drive_del(blk); > /* Further I/O must not pause the guest */ > bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT, > diff --git a/include/block/block.h b/include/block/block.h > index 5b45743..bc9ec50 100644 > --- a/include/block/block.h > +++ b/include/block/block.h > @@ -48,41 +48,6 @@ typedef struct BlockFragInfo { > uint64_t compressed_clusters; > } BlockFragInfo; > > -/* Callbacks for block device models */ > -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, bool load); > - /* > - * Runs when an eject request is issued from the monitor, the tray > - * is closed, and the medium is locked. > - * Device models that do not implement is_medium_locked will not need > - * this callback. Device models that can lock the medium or tray might > - * want to implement the callback and unlock the tray when "force" is > - * true, even if they do not support eject requests. > - */ > - void (*eject_request_cb)(void *opaque, bool force); > - /* > - * 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) > - */ > - void (*resize_cb)(void *opaque); > -} BlockDevOps; > - > typedef enum { > BDRV_REQ_COPY_ON_READ = 0x1, > BDRV_REQ_ZERO_WRITE = 0x2, > @@ -230,16 +195,6 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state); > void bdrv_reopen_abort(BDRVReopenState *reopen_state); > void bdrv_close(BlockDriverState *bs); > void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify); > -int bdrv_attach_dev(BlockDriverState *bs, void *dev); > -void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev); > -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); > -void bdrv_dev_eject_request(BlockDriverState *bs, bool force); > -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_read_unthrottled(BlockDriverState *bs, int64_t sector_num, > diff --git a/include/block/block_int.h b/include/block/block_int.h > index e8e33a8..8898c6c 100644 > --- a/include/block/block_int.h > +++ b/include/block/block_int.h > @@ -326,11 +326,6 @@ struct BlockDriverState { > > BlockBackend *blk; /* owning backend, if any */ > > - void *dev; /* attached device model, if any */ > - /* TODO change to DeviceState when all users are qdevified */ > - const BlockDevOps *dev_ops; > - void *dev_opaque; > - > AioContext *aio_context; /* event loop used for fd handlers, timers, etc */ > /* long-running tasks intended to always use the same AioContext as this > * BDS may register themselves in this list to be notified of changes > @@ -587,4 +582,11 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, > BlockCompletionFunc *cb, void *opaque, > Error **errp); > > +void blk_dev_change_media_cb(BlockBackend *blk, bool load); > +bool blk_dev_has_removable_media(BlockBackend *blk); > +void blk_dev_eject_request(BlockBackend *blk, bool force); > +bool blk_dev_is_tray_open(BlockBackend *blk); > +bool blk_dev_is_medium_locked(BlockBackend *blk); > +void blk_dev_resize_cb(BlockBackend *blk); > + > #endif /* BLOCK_INT_H */ > diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h > index e4bfea5..02305a1 100644 > --- a/include/sysemu/block-backend.h > +++ b/include/sysemu/block-backend.h > @@ -25,6 +25,41 @@ > */ > #include "block/block.h" > > +/* Callbacks for block device models */ > +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, bool load); > + /* > + * Runs when an eject request is issued from the monitor, the tray > + * is closed, and the medium is locked. > + * Device models that do not implement is_medium_locked will not need > + * this callback. Device models that can lock the medium or tray might > + * want to implement the callback and unlock the tray when "force" is > + * true, even if they do not support eject requests. > + */ > + void (*eject_request_cb)(void *opaque, bool force); > + /* > + * 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) > + */ > + void (*resize_cb)(void *opaque); > +} BlockDevOps; > + > BlockBackend *blk_new(const char *name, Error **errp); > BlockBackend *blk_new_with_bs(const char *name, Error **errp); > void blk_ref(BlockBackend *blk); > -- > 1.9.3 > This one is difficult to review. Could it be splitted in multiple baby steps ? Best regards Benoît
Benoît Canet <benoit.canet@nodalink.com> writes: > On Tue, Sep 16, 2014 at 08:12:27PM +0200, Markus Armbruster wrote: >> Move device model attachment / detachment and the BlockDevOps device >> model callbacks and their wrappers from BlockDriverState to >> BlockBackend. >> >> Signed-off-by: Markus Armbruster <armbru@redhat.com> >> --- >> block.c | 126 ++++------------------------------ >> block/block-backend.c | 151 ++++++++++++++++++++++++++++++++++++++--- >> block/qapi.c | 8 +-- >> blockdev.c | 8 +-- >> include/block/block.h | 45 ------------ >> include/block/block_int.h | 12 ++-- >> include/sysemu/block-backend.h | 35 ++++++++++ >> 7 files changed, 203 insertions(+), 182 deletions(-) >> >> diff --git a/block.c b/block.c >> index 1d9a680..fac1211 100644 >> --- a/block.c >> +++ b/block.c >> @@ -58,9 +58,6 @@ struct BdrvDirtyBitmap { >> >> #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */ >> >> -#define COROUTINE_POOL_RESERVATION 64 /* number of coroutines to reserve */ >> - >> -static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load); >> static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, >> int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, >> BlockCompletionFunc *cb, void *opaque); >> @@ -1527,7 +1524,9 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, >> } >> >> if (!bdrv_key_required(bs)) { >> - bdrv_dev_change_media_cb(bs, true); >> + if (bs->blk) { >> + blk_dev_change_media_cb(bs->blk, true); >> + } >> } else if (!runstate_check(RUN_STATE_PRELAUNCH) >> && !runstate_check(RUN_STATE_INMIGRATE) >> && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */ >> @@ -1852,7 +1851,9 @@ void bdrv_close(BlockDriverState *bs) >> } >> } >> >> - bdrv_dev_change_media_cb(bs, false); >> + if (bs->blk) { >> + blk_dev_change_media_cb(bs->blk, false); >> + } >> >> /*throttling disk I/O limits*/ >> if (bs->io_limits_enabled) { >> @@ -1971,9 +1972,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, >> /* move some fields that need to stay attached to the device */ >> >> /* dev info */ >> - bs_dest->dev_ops = bs_src->dev_ops; >> - bs_dest->dev_opaque = bs_src->dev_opaque; >> - bs_dest->dev = bs_src->dev; >> bs_dest->guest_block_size = bs_src->guest_block_size; >> bs_dest->copy_on_read = bs_src->copy_on_read; >> >> @@ -2041,7 +2039,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) >> assert(!bs_new->blk); >> assert(QLIST_EMPTY(&bs_new->dirty_bitmaps)); >> assert(bs_new->job == NULL); >> - assert(bs_new->dev == NULL); >> assert(bs_new->io_limits_enabled == false); >> assert(!throttle_have_timer(&bs_new->throttle_state)); >> >> @@ -2058,7 +2055,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) >> assert(!bs_new->blk); >> >> /* Check a few fields that should remain attached to the device */ >> - assert(bs_new->dev == NULL); >> assert(bs_new->job == NULL); >> assert(bs_new->io_limits_enabled == false); >> assert(!throttle_have_timer(&bs_new->throttle_state)); >> @@ -2097,7 +2093,6 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top) >> >> static void bdrv_delete(BlockDriverState *bs) >> { >> - assert(!bs->dev); >> assert(!bs->job); >> assert(bdrv_op_blocker_is_empty(bs)); >> assert(!bs->refcnt); >> @@ -2111,105 +2106,6 @@ static void bdrv_delete(BlockDriverState *bs) >> g_free(bs); >> } >> >> -int bdrv_attach_dev(BlockDriverState *bs, void *dev) >> -/* TODO change to DeviceState *dev when all users are qdevified */ >> -{ >> - if (bs->dev) { >> - return -EBUSY; >> - } >> - bs->dev = dev; >> - bdrv_iostatus_reset(bs); >> - >> - /* We're expecting I/O from the device so bump up coroutine pool size */ >> - qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION); >> - return 0; >> -} >> - >> -/* TODO qdevified devices don't use this, remove when devices are qdevified */ >> -void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev) >> -{ >> - if (bdrv_attach_dev(bs, dev) < 0) { >> - abort(); >> - } >> -} >> - >> -void bdrv_detach_dev(BlockDriverState *bs, void *dev) >> -/* TODO change to DeviceState *dev when all users are qdevified */ >> -{ >> - assert(bs->dev == dev); >> - bs->dev = NULL; >> - bs->dev_ops = NULL; >> - bs->dev_opaque = NULL; >> - bs->guest_block_size = 512; >> - qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION); >> -} >> - >> -/* TODO change to return DeviceState * when all users are qdevified */ >> -void *bdrv_get_attached_dev(BlockDriverState *bs) >> -{ >> - return bs->dev; >> -} >> - >> -void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, >> - void *opaque) >> -{ >> - bs->dev_ops = ops; >> - bs->dev_opaque = opaque; >> -} >> - >> -static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load) >> -{ >> - if (bs->dev_ops && bs->dev_ops->change_media_cb) { >> - bool tray_was_closed = !bdrv_dev_is_tray_open(bs); >> - bs->dev_ops->change_media_cb(bs->dev_opaque, load); >> - if (tray_was_closed) { >> - /* tray open */ >> - qapi_event_send_device_tray_moved(bdrv_get_device_name(bs), >> - true, &error_abort); >> - } >> - if (load) { >> - /* tray close */ >> - qapi_event_send_device_tray_moved(bdrv_get_device_name(bs), >> - false, &error_abort); >> - } >> - } >> -} >> - >> -bool bdrv_dev_has_removable_media(BlockDriverState *bs) >> -{ >> - return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb); >> -} >> - >> -void bdrv_dev_eject_request(BlockDriverState *bs, bool force) >> -{ >> - if (bs->dev_ops && bs->dev_ops->eject_request_cb) { >> - bs->dev_ops->eject_request_cb(bs->dev_opaque, force); >> - } >> -} >> - >> -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) >> -{ >> - if (bs->dev_ops && bs->dev_ops->resize_cb) { >> - bs->dev_ops->resize_cb(bs->dev_opaque); >> - } >> -} >> - >> -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 >> * >> @@ -3543,7 +3439,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset) >> ret = drv->bdrv_truncate(bs, offset); >> if (ret == 0) { >> ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); >> - bdrv_dev_resize_cb(bs); >> + if (bs->blk) { >> + blk_dev_resize_cb(bs->blk); >> + } >> } >> return ret; >> } >> @@ -3744,8 +3642,10 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) >> bs->valid_key = 0; >> } 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, true); >> + if (bs->blk) { >> + /* call the change callback now, we skipped it on open */ >> + blk_dev_change_media_cb(bs->blk, true); >> + } >> } >> return ret; >> } >> diff --git a/block/block-backend.c b/block/block-backend.c >> index b55f0b4..d49c988 100644 >> --- a/block/block-backend.c >> +++ b/block/block-backend.c >> @@ -13,6 +13,10 @@ >> #include "sysemu/block-backend.h" >> #include "block/block_int.h" >> #include "sysemu/blockdev.h" >> +#include "qapi-event.h" >> + >> +/* Number of coroutines to reserve per attached device model */ >> +#define COROUTINE_POOL_RESERVATION 64 >> >> struct BlockBackend { >> char *name; >> @@ -20,6 +24,11 @@ struct BlockBackend { >> BlockDriverState *bs; >> DriveInfo *legacy_dinfo; >> QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */ >> + >> + void *dev; /* attached device model, if any */ >> + /* TODO change to DeviceState when all users are qdevified */ >> + const BlockDevOps *dev_ops; >> + void *dev_opaque; >> }; >> >> static void drive_info_del(DriveInfo *dinfo); >> @@ -81,6 +90,7 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp) >> static void blk_delete(BlockBackend *blk) >> { >> assert(!blk->refcnt); >> + assert(!blk->dev); >> if (blk->bs) { >> assert(blk->bs->blk == blk); >> blk->bs->blk = NULL; >> @@ -233,34 +243,153 @@ void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk) >> } >> } >> >> -void blk_iostatus_enable(BlockBackend *blk) >> -{ >> - bdrv_iostatus_enable(blk->bs); >> -} >> - >> +/* >> + * Attach device model @dev to @blk. >> + * Return 0 on success, -EBUSY when a device model is attached already. >> + */ >> int blk_attach_dev(BlockBackend *blk, void *dev) >> +/* TODO change to DeviceState *dev when all users are qdevified */ >> { >> - return bdrv_attach_dev(blk->bs, dev); >> + if (blk->dev) { >> + return -EBUSY; >> + } >> + blk->dev = dev; >> + bdrv_iostatus_reset(blk->bs); >> + >> + /* We're expecting I/O from the device so bump up coroutine pool size */ >> + qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION); >> + return 0; >> } >> >> +/* >> + * Attach device model @dev to @blk. >> + * @blk must not have a device model attached already. >> + * TODO qdevified devices don't use this, remove when devices are qdevified >> + */ >> void blk_attach_dev_nofail(BlockBackend *blk, void *dev) >> { >> - bdrv_attach_dev_nofail(blk->bs, dev); >> + if (blk_attach_dev(blk, dev) < 0) { >> + abort(); >> + } >> } >> >> +/* >> + * Detach device model @dev from @blk. >> + * @dev must be currently attached to @blk. >> + */ >> void blk_detach_dev(BlockBackend *blk, void *dev) >> +/* TODO change to DeviceState *dev when all users are qdevified */ >> { >> - bdrv_detach_dev(blk->bs, dev); >> + assert(blk->dev == dev); >> + blk->dev = NULL; >> + blk->dev_ops = NULL; >> + blk->dev_opaque = NULL; >> + bdrv_set_guest_block_size(blk->bs, 512); >> + qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION); >> } >> >> +/* >> + * Return the device model attached to @blk if any, else null. >> + */ >> void *blk_get_attached_dev(BlockBackend *blk) >> +/* TODO change to return DeviceState * when all users are qdevified */ >> { >> - return bdrv_get_attached_dev(blk->bs); >> + return blk->dev; >> } >> >> -void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque) >> +/* >> + * Set @blk's device model callbacks to @ops. >> + * @opaque is the opaque argument to pass to the callbacks. >> + * This is for use by device models. >> + */ >> +void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, >> + void *opaque) >> { >> - bdrv_set_dev_ops(blk->bs, ops, opaque); >> + blk->dev_ops = ops; >> + blk->dev_opaque = opaque; >> +} >> + >> +/* >> + * Notify @blk's attached device model of media change. >> + * If @load is true, notify of media load. >> + * Else, notify of media eject. >> + * Also send DEVICE_TRAY_MOVED events as appropriate. >> + */ >> +void blk_dev_change_media_cb(BlockBackend *blk, bool load) >> +{ >> + if (blk->dev_ops && blk->dev_ops->change_media_cb) { >> + bool tray_was_closed = !blk_dev_is_tray_open(blk); >> + >> + blk->dev_ops->change_media_cb(blk->dev_opaque, load); >> + if (tray_was_closed) { >> + /* tray open */ >> + qapi_event_send_device_tray_moved(blk_name(blk), >> + true, &error_abort); >> + } >> + if (load) { >> + /* tray close */ >> + qapi_event_send_device_tray_moved(blk_name(blk), >> + false, &error_abort); >> + } >> + } >> +} >> + >> +/* >> + * Does @blk's attached device model have removable media? >> + * %true if no device model is attached. >> + */ >> +bool blk_dev_has_removable_media(BlockBackend *blk) >> +{ >> + return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb); >> +} >> + >> +/* >> + * Notify @blk's attached device model of a media eject request. >> + * If @force is true, the medium is about to be yanked out forcefully. >> + */ >> +void blk_dev_eject_request(BlockBackend *blk, bool force) >> +{ >> + if (blk->dev_ops && blk->dev_ops->eject_request_cb) { >> + blk->dev_ops->eject_request_cb(blk->dev_opaque, force); >> + } >> +} >> + >> +/* >> + * Does @blk's attached device model have a tray, and is it open? >> + */ >> +bool blk_dev_is_tray_open(BlockBackend *blk) >> +{ >> + if (blk->dev_ops && blk->dev_ops->is_tray_open) { >> + return blk->dev_ops->is_tray_open(blk->dev_opaque); >> + } >> + return false; >> +} >> + >> +/* >> + * Does @blk's attached device model have the medium locked? >> + * %false if the device model has no such lock. >> + */ >> +bool blk_dev_is_medium_locked(BlockBackend *blk) >> +{ >> + if (blk->dev_ops && blk->dev_ops->is_medium_locked) { >> + return blk->dev_ops->is_medium_locked(blk->dev_opaque); >> + } >> + return false; >> +} >> + >> +/* >> + * Notify @blk's attached device model of a backend size change. >> + */ >> +void blk_dev_resize_cb(BlockBackend *blk) >> +{ >> + if (blk->dev_ops && blk->dev_ops->resize_cb) { >> + blk->dev_ops->resize_cb(blk->dev_opaque); >> + } >> +} >> + >> +void blk_iostatus_enable(BlockBackend *blk) >> +{ >> + bdrv_iostatus_enable(blk->bs); >> } >> >> int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, >> diff --git a/block/qapi.c b/block/qapi.c >> index fca981d..1301144 100644 >> --- a/block/qapi.c >> +++ b/block/qapi.c >> @@ -275,12 +275,12 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, >> Error *local_err = NULL; >> info->device = g_strdup(blk_name(blk)); >> info->type = g_strdup("unknown"); >> - info->locked = bdrv_dev_is_medium_locked(bs); >> - info->removable = bdrv_dev_has_removable_media(bs); >> + info->locked = blk_dev_is_medium_locked(blk); >> + info->removable = blk_dev_has_removable_media(blk); >> >> - if (bdrv_dev_has_removable_media(bs)) { >> + if (blk_dev_has_removable_media(blk)) { >> info->has_tray_open = true; >> - info->tray_open = bdrv_dev_is_tray_open(bs); >> + info->tray_open = blk_dev_is_tray_open(blk); >> } >> >> if (bdrv_iostatus_is_enabled(bs)) { >> diff --git a/blockdev.c b/blockdev.c >> index e115bde..d3dccb9 100644 >> --- a/blockdev.c >> +++ b/blockdev.c >> @@ -1509,14 +1509,14 @@ static void eject_device(BlockBackend *blk, int force, Error **errp) >> if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { >> return; >> } >> - if (!bdrv_dev_has_removable_media(bs)) { >> + if (!blk_dev_has_removable_media(blk)) { >> error_setg(errp, "Device '%s' is not removable", >> bdrv_get_device_name(bs)); >> return; >> } >> >> - if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) { >> - bdrv_dev_eject_request(bs, force); >> + if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) { >> + blk_dev_eject_request(blk, force); >> if (!force) { >> error_setg(errp, "Device '%s' is locked", >> bdrv_get_device_name(bs)); >> @@ -1753,7 +1753,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) >> * can be removed. If this is a drive with no device backing >> * then we can just get rid of the block driver state right here. >> */ >> - if (bdrv_get_attached_dev(bs)) { >> + if (blk_get_attached_dev(blk)) { >> blk_hide_on_behalf_of_do_drive_del(blk); >> /* Further I/O must not pause the guest */ >> bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT, >> diff --git a/include/block/block.h b/include/block/block.h >> index 5b45743..bc9ec50 100644 >> --- a/include/block/block.h >> +++ b/include/block/block.h >> @@ -48,41 +48,6 @@ typedef struct BlockFragInfo { >> uint64_t compressed_clusters; >> } BlockFragInfo; >> >> -/* Callbacks for block device models */ >> -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, bool load); >> - /* >> - * Runs when an eject request is issued from the monitor, the tray >> - * is closed, and the medium is locked. >> - * Device models that do not implement is_medium_locked will not need >> - * this callback. Device models that can lock the medium or tray might >> - * want to implement the callback and unlock the tray when "force" is >> - * true, even if they do not support eject requests. >> - */ >> - void (*eject_request_cb)(void *opaque, bool force); >> - /* >> - * 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) >> - */ >> - void (*resize_cb)(void *opaque); >> -} BlockDevOps; >> - >> typedef enum { >> BDRV_REQ_COPY_ON_READ = 0x1, >> BDRV_REQ_ZERO_WRITE = 0x2, >> @@ -230,16 +195,6 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state); >> void bdrv_reopen_abort(BDRVReopenState *reopen_state); >> void bdrv_close(BlockDriverState *bs); >> void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify); >> -int bdrv_attach_dev(BlockDriverState *bs, void *dev); >> -void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev); >> -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); >> -void bdrv_dev_eject_request(BlockDriverState *bs, bool force); >> -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_read_unthrottled(BlockDriverState *bs, int64_t sector_num, >> diff --git a/include/block/block_int.h b/include/block/block_int.h >> index e8e33a8..8898c6c 100644 >> --- a/include/block/block_int.h >> +++ b/include/block/block_int.h >> @@ -326,11 +326,6 @@ struct BlockDriverState { >> >> BlockBackend *blk; /* owning backend, if any */ >> >> - void *dev; /* attached device model, if any */ >> - /* TODO change to DeviceState when all users are qdevified */ >> - const BlockDevOps *dev_ops; >> - void *dev_opaque; >> - >> AioContext *aio_context; /* event loop used for fd handlers, timers, etc */ >> /* long-running tasks intended to always use the same AioContext as this >> * BDS may register themselves in this list to be notified of changes >> @@ -587,4 +582,11 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, >> BlockCompletionFunc *cb, void *opaque, >> Error **errp); >> >> +void blk_dev_change_media_cb(BlockBackend *blk, bool load); >> +bool blk_dev_has_removable_media(BlockBackend *blk); >> +void blk_dev_eject_request(BlockBackend *blk, bool force); >> +bool blk_dev_is_tray_open(BlockBackend *blk); >> +bool blk_dev_is_medium_locked(BlockBackend *blk); >> +void blk_dev_resize_cb(BlockBackend *blk); >> + >> #endif /* BLOCK_INT_H */ >> diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h >> index e4bfea5..02305a1 100644 >> --- a/include/sysemu/block-backend.h >> +++ b/include/sysemu/block-backend.h >> @@ -25,6 +25,41 @@ >> */ >> #include "block/block.h" >> >> +/* Callbacks for block device models */ >> +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, bool load); >> + /* >> + * Runs when an eject request is issued from the monitor, the tray >> + * is closed, and the medium is locked. >> + * Device models that do not implement is_medium_locked will not need >> + * this callback. Device models that can lock the medium or tray might >> + * want to implement the callback and unlock the tray when "force" is >> + * true, even if they do not support eject requests. >> + */ >> + void (*eject_request_cb)(void *opaque, bool force); >> + /* >> + * 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) >> + */ >> + void (*resize_cb)(void *opaque); >> +} BlockDevOps; >> + >> BlockBackend *blk_new(const char *name, Error **errp); >> BlockBackend *blk_new_with_bs(const char *name, Error **errp); >> void blk_ref(BlockBackend *blk); >> -- >> 1.9.3 >> > > This one is difficult to review. > Could it be splitted in multiple baby steps ? Not sure, but I'll think about it. I certainly can try harder in the commit message.
On 16.09.2014 20:12, Markus Armbruster wrote: > Move device model attachment / detachment and the BlockDevOps device > model callbacks and their wrappers from BlockDriverState to > BlockBackend. > > Signed-off-by: Markus Armbruster <armbru@redhat.com> > --- > block.c | 126 ++++------------------------------ > block/block-backend.c | 151 ++++++++++++++++++++++++++++++++++++++--- > block/qapi.c | 8 +-- > blockdev.c | 8 +-- > include/block/block.h | 45 ------------ > include/block/block_int.h | 12 ++-- > include/sysemu/block-backend.h | 35 ++++++++++ > 7 files changed, 203 insertions(+), 182 deletions(-) Reviewed-by: Max Reitz <mreitz@redhat.com>
Am 16.09.2014 um 20:12 hat Markus Armbruster geschrieben: > Move device model attachment / detachment and the BlockDevOps device > model callbacks and their wrappers from BlockDriverState to > BlockBackend. > > Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com>
diff --git a/block.c b/block.c index 1d9a680..fac1211 100644 --- a/block.c +++ b/block.c @@ -58,9 +58,6 @@ struct BdrvDirtyBitmap { #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */ -#define COROUTINE_POOL_RESERVATION 64 /* number of coroutines to reserve */ - -static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load); static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockCompletionFunc *cb, void *opaque); @@ -1527,7 +1524,9 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, } if (!bdrv_key_required(bs)) { - bdrv_dev_change_media_cb(bs, true); + if (bs->blk) { + blk_dev_change_media_cb(bs->blk, true); + } } else if (!runstate_check(RUN_STATE_PRELAUNCH) && !runstate_check(RUN_STATE_INMIGRATE) && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */ @@ -1852,7 +1851,9 @@ void bdrv_close(BlockDriverState *bs) } } - bdrv_dev_change_media_cb(bs, false); + if (bs->blk) { + blk_dev_change_media_cb(bs->blk, false); + } /*throttling disk I/O limits*/ if (bs->io_limits_enabled) { @@ -1971,9 +1972,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, /* move some fields that need to stay attached to the device */ /* dev info */ - bs_dest->dev_ops = bs_src->dev_ops; - bs_dest->dev_opaque = bs_src->dev_opaque; - bs_dest->dev = bs_src->dev; bs_dest->guest_block_size = bs_src->guest_block_size; bs_dest->copy_on_read = bs_src->copy_on_read; @@ -2041,7 +2039,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) assert(!bs_new->blk); assert(QLIST_EMPTY(&bs_new->dirty_bitmaps)); assert(bs_new->job == NULL); - assert(bs_new->dev == NULL); assert(bs_new->io_limits_enabled == false); assert(!throttle_have_timer(&bs_new->throttle_state)); @@ -2058,7 +2055,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) assert(!bs_new->blk); /* Check a few fields that should remain attached to the device */ - assert(bs_new->dev == NULL); assert(bs_new->job == NULL); assert(bs_new->io_limits_enabled == false); assert(!throttle_have_timer(&bs_new->throttle_state)); @@ -2097,7 +2093,6 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top) static void bdrv_delete(BlockDriverState *bs) { - assert(!bs->dev); assert(!bs->job); assert(bdrv_op_blocker_is_empty(bs)); assert(!bs->refcnt); @@ -2111,105 +2106,6 @@ static void bdrv_delete(BlockDriverState *bs) g_free(bs); } -int bdrv_attach_dev(BlockDriverState *bs, void *dev) -/* TODO change to DeviceState *dev when all users are qdevified */ -{ - if (bs->dev) { - return -EBUSY; - } - bs->dev = dev; - bdrv_iostatus_reset(bs); - - /* We're expecting I/O from the device so bump up coroutine pool size */ - qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION); - return 0; -} - -/* TODO qdevified devices don't use this, remove when devices are qdevified */ -void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev) -{ - if (bdrv_attach_dev(bs, dev) < 0) { - abort(); - } -} - -void bdrv_detach_dev(BlockDriverState *bs, void *dev) -/* TODO change to DeviceState *dev when all users are qdevified */ -{ - assert(bs->dev == dev); - bs->dev = NULL; - bs->dev_ops = NULL; - bs->dev_opaque = NULL; - bs->guest_block_size = 512; - qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION); -} - -/* TODO change to return DeviceState * when all users are qdevified */ -void *bdrv_get_attached_dev(BlockDriverState *bs) -{ - return bs->dev; -} - -void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, - void *opaque) -{ - bs->dev_ops = ops; - bs->dev_opaque = opaque; -} - -static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load) -{ - if (bs->dev_ops && bs->dev_ops->change_media_cb) { - bool tray_was_closed = !bdrv_dev_is_tray_open(bs); - bs->dev_ops->change_media_cb(bs->dev_opaque, load); - if (tray_was_closed) { - /* tray open */ - qapi_event_send_device_tray_moved(bdrv_get_device_name(bs), - true, &error_abort); - } - if (load) { - /* tray close */ - qapi_event_send_device_tray_moved(bdrv_get_device_name(bs), - false, &error_abort); - } - } -} - -bool bdrv_dev_has_removable_media(BlockDriverState *bs) -{ - return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb); -} - -void bdrv_dev_eject_request(BlockDriverState *bs, bool force) -{ - if (bs->dev_ops && bs->dev_ops->eject_request_cb) { - bs->dev_ops->eject_request_cb(bs->dev_opaque, force); - } -} - -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) -{ - if (bs->dev_ops && bs->dev_ops->resize_cb) { - bs->dev_ops->resize_cb(bs->dev_opaque); - } -} - -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 * @@ -3543,7 +3439,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset) ret = drv->bdrv_truncate(bs, offset); if (ret == 0) { ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); - bdrv_dev_resize_cb(bs); + if (bs->blk) { + blk_dev_resize_cb(bs->blk); + } } return ret; } @@ -3744,8 +3642,10 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) bs->valid_key = 0; } 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, true); + if (bs->blk) { + /* call the change callback now, we skipped it on open */ + blk_dev_change_media_cb(bs->blk, true); + } } return ret; } diff --git a/block/block-backend.c b/block/block-backend.c index b55f0b4..d49c988 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -13,6 +13,10 @@ #include "sysemu/block-backend.h" #include "block/block_int.h" #include "sysemu/blockdev.h" +#include "qapi-event.h" + +/* Number of coroutines to reserve per attached device model */ +#define COROUTINE_POOL_RESERVATION 64 struct BlockBackend { char *name; @@ -20,6 +24,11 @@ struct BlockBackend { BlockDriverState *bs; DriveInfo *legacy_dinfo; QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */ + + void *dev; /* attached device model, if any */ + /* TODO change to DeviceState when all users are qdevified */ + const BlockDevOps *dev_ops; + void *dev_opaque; }; static void drive_info_del(DriveInfo *dinfo); @@ -81,6 +90,7 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp) static void blk_delete(BlockBackend *blk) { assert(!blk->refcnt); + assert(!blk->dev); if (blk->bs) { assert(blk->bs->blk == blk); blk->bs->blk = NULL; @@ -233,34 +243,153 @@ void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk) } } -void blk_iostatus_enable(BlockBackend *blk) -{ - bdrv_iostatus_enable(blk->bs); -} - +/* + * Attach device model @dev to @blk. + * Return 0 on success, -EBUSY when a device model is attached already. + */ int blk_attach_dev(BlockBackend *blk, void *dev) +/* TODO change to DeviceState *dev when all users are qdevified */ { - return bdrv_attach_dev(blk->bs, dev); + if (blk->dev) { + return -EBUSY; + } + blk->dev = dev; + bdrv_iostatus_reset(blk->bs); + + /* We're expecting I/O from the device so bump up coroutine pool size */ + qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION); + return 0; } +/* + * Attach device model @dev to @blk. + * @blk must not have a device model attached already. + * TODO qdevified devices don't use this, remove when devices are qdevified + */ void blk_attach_dev_nofail(BlockBackend *blk, void *dev) { - bdrv_attach_dev_nofail(blk->bs, dev); + if (blk_attach_dev(blk, dev) < 0) { + abort(); + } } +/* + * Detach device model @dev from @blk. + * @dev must be currently attached to @blk. + */ void blk_detach_dev(BlockBackend *blk, void *dev) +/* TODO change to DeviceState *dev when all users are qdevified */ { - bdrv_detach_dev(blk->bs, dev); + assert(blk->dev == dev); + blk->dev = NULL; + blk->dev_ops = NULL; + blk->dev_opaque = NULL; + bdrv_set_guest_block_size(blk->bs, 512); + qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION); } +/* + * Return the device model attached to @blk if any, else null. + */ void *blk_get_attached_dev(BlockBackend *blk) +/* TODO change to return DeviceState * when all users are qdevified */ { - return bdrv_get_attached_dev(blk->bs); + return blk->dev; } -void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque) +/* + * Set @blk's device model callbacks to @ops. + * @opaque is the opaque argument to pass to the callbacks. + * This is for use by device models. + */ +void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, + void *opaque) { - bdrv_set_dev_ops(blk->bs, ops, opaque); + blk->dev_ops = ops; + blk->dev_opaque = opaque; +} + +/* + * Notify @blk's attached device model of media change. + * If @load is true, notify of media load. + * Else, notify of media eject. + * Also send DEVICE_TRAY_MOVED events as appropriate. + */ +void blk_dev_change_media_cb(BlockBackend *blk, bool load) +{ + if (blk->dev_ops && blk->dev_ops->change_media_cb) { + bool tray_was_closed = !blk_dev_is_tray_open(blk); + + blk->dev_ops->change_media_cb(blk->dev_opaque, load); + if (tray_was_closed) { + /* tray open */ + qapi_event_send_device_tray_moved(blk_name(blk), + true, &error_abort); + } + if (load) { + /* tray close */ + qapi_event_send_device_tray_moved(blk_name(blk), + false, &error_abort); + } + } +} + +/* + * Does @blk's attached device model have removable media? + * %true if no device model is attached. + */ +bool blk_dev_has_removable_media(BlockBackend *blk) +{ + return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb); +} + +/* + * Notify @blk's attached device model of a media eject request. + * If @force is true, the medium is about to be yanked out forcefully. + */ +void blk_dev_eject_request(BlockBackend *blk, bool force) +{ + if (blk->dev_ops && blk->dev_ops->eject_request_cb) { + blk->dev_ops->eject_request_cb(blk->dev_opaque, force); + } +} + +/* + * Does @blk's attached device model have a tray, and is it open? + */ +bool blk_dev_is_tray_open(BlockBackend *blk) +{ + if (blk->dev_ops && blk->dev_ops->is_tray_open) { + return blk->dev_ops->is_tray_open(blk->dev_opaque); + } + return false; +} + +/* + * Does @blk's attached device model have the medium locked? + * %false if the device model has no such lock. + */ +bool blk_dev_is_medium_locked(BlockBackend *blk) +{ + if (blk->dev_ops && blk->dev_ops->is_medium_locked) { + return blk->dev_ops->is_medium_locked(blk->dev_opaque); + } + return false; +} + +/* + * Notify @blk's attached device model of a backend size change. + */ +void blk_dev_resize_cb(BlockBackend *blk) +{ + if (blk->dev_ops && blk->dev_ops->resize_cb) { + blk->dev_ops->resize_cb(blk->dev_opaque); + } +} + +void blk_iostatus_enable(BlockBackend *blk) +{ + bdrv_iostatus_enable(blk->bs); } int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, diff --git a/block/qapi.c b/block/qapi.c index fca981d..1301144 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -275,12 +275,12 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, Error *local_err = NULL; info->device = g_strdup(blk_name(blk)); info->type = g_strdup("unknown"); - info->locked = bdrv_dev_is_medium_locked(bs); - info->removable = bdrv_dev_has_removable_media(bs); + info->locked = blk_dev_is_medium_locked(blk); + info->removable = blk_dev_has_removable_media(blk); - if (bdrv_dev_has_removable_media(bs)) { + if (blk_dev_has_removable_media(blk)) { info->has_tray_open = true; - info->tray_open = bdrv_dev_is_tray_open(bs); + info->tray_open = blk_dev_is_tray_open(blk); } if (bdrv_iostatus_is_enabled(bs)) { diff --git a/blockdev.c b/blockdev.c index e115bde..d3dccb9 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1509,14 +1509,14 @@ static void eject_device(BlockBackend *blk, int force, Error **errp) if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { return; } - if (!bdrv_dev_has_removable_media(bs)) { + if (!blk_dev_has_removable_media(blk)) { error_setg(errp, "Device '%s' is not removable", bdrv_get_device_name(bs)); return; } - if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) { - bdrv_dev_eject_request(bs, force); + if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) { + blk_dev_eject_request(blk, force); if (!force) { error_setg(errp, "Device '%s' is locked", bdrv_get_device_name(bs)); @@ -1753,7 +1753,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) * can be removed. If this is a drive with no device backing * then we can just get rid of the block driver state right here. */ - if (bdrv_get_attached_dev(bs)) { + if (blk_get_attached_dev(blk)) { blk_hide_on_behalf_of_do_drive_del(blk); /* Further I/O must not pause the guest */ bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT, diff --git a/include/block/block.h b/include/block/block.h index 5b45743..bc9ec50 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -48,41 +48,6 @@ typedef struct BlockFragInfo { uint64_t compressed_clusters; } BlockFragInfo; -/* Callbacks for block device models */ -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, bool load); - /* - * Runs when an eject request is issued from the monitor, the tray - * is closed, and the medium is locked. - * Device models that do not implement is_medium_locked will not need - * this callback. Device models that can lock the medium or tray might - * want to implement the callback and unlock the tray when "force" is - * true, even if they do not support eject requests. - */ - void (*eject_request_cb)(void *opaque, bool force); - /* - * 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) - */ - void (*resize_cb)(void *opaque); -} BlockDevOps; - typedef enum { BDRV_REQ_COPY_ON_READ = 0x1, BDRV_REQ_ZERO_WRITE = 0x2, @@ -230,16 +195,6 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state); void bdrv_reopen_abort(BDRVReopenState *reopen_state); void bdrv_close(BlockDriverState *bs); void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify); -int bdrv_attach_dev(BlockDriverState *bs, void *dev); -void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev); -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); -void bdrv_dev_eject_request(BlockDriverState *bs, bool force); -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_read_unthrottled(BlockDriverState *bs, int64_t sector_num, diff --git a/include/block/block_int.h b/include/block/block_int.h index e8e33a8..8898c6c 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -326,11 +326,6 @@ struct BlockDriverState { BlockBackend *blk; /* owning backend, if any */ - void *dev; /* attached device model, if any */ - /* TODO change to DeviceState when all users are qdevified */ - const BlockDevOps *dev_ops; - void *dev_opaque; - AioContext *aio_context; /* event loop used for fd handlers, timers, etc */ /* long-running tasks intended to always use the same AioContext as this * BDS may register themselves in this list to be notified of changes @@ -587,4 +582,11 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, BlockCompletionFunc *cb, void *opaque, Error **errp); +void blk_dev_change_media_cb(BlockBackend *blk, bool load); +bool blk_dev_has_removable_media(BlockBackend *blk); +void blk_dev_eject_request(BlockBackend *blk, bool force); +bool blk_dev_is_tray_open(BlockBackend *blk); +bool blk_dev_is_medium_locked(BlockBackend *blk); +void blk_dev_resize_cb(BlockBackend *blk); + #endif /* BLOCK_INT_H */ diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index e4bfea5..02305a1 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -25,6 +25,41 @@ */ #include "block/block.h" +/* Callbacks for block device models */ +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, bool load); + /* + * Runs when an eject request is issued from the monitor, the tray + * is closed, and the medium is locked. + * Device models that do not implement is_medium_locked will not need + * this callback. Device models that can lock the medium or tray might + * want to implement the callback and unlock the tray when "force" is + * true, even if they do not support eject requests. + */ + void (*eject_request_cb)(void *opaque, bool force); + /* + * 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) + */ + void (*resize_cb)(void *opaque); +} BlockDevOps; + BlockBackend *blk_new(const char *name, Error **errp); BlockBackend *blk_new_with_bs(const char *name, Error **errp); void blk_ref(BlockBackend *blk);
Move device model attachment / detachment and the BlockDevOps device model callbacks and their wrappers from BlockDriverState to BlockBackend. Signed-off-by: Markus Armbruster <armbru@redhat.com> --- block.c | 126 ++++------------------------------ block/block-backend.c | 151 ++++++++++++++++++++++++++++++++++++++--- block/qapi.c | 8 +-- blockdev.c | 8 +-- include/block/block.h | 45 ------------ include/block/block_int.h | 12 ++-- include/sysemu/block-backend.h | 35 ++++++++++ 7 files changed, 203 insertions(+), 182 deletions(-)