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