From patchwork Wed Sep 10 08:13:51 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 387631 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 859AE14012A for ; Wed, 10 Sep 2014 18:29:45 +1000 (EST) Received: from localhost ([::1]:54337 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XRdHb-0001j9-Aj for incoming@patchwork.ozlabs.org; Wed, 10 Sep 2014 04:29:43 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:32924) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XRd2h-0002Mv-5g for qemu-devel@nongnu.org; Wed, 10 Sep 2014 04:14:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XRd2X-0003qY-W6 for qemu-devel@nongnu.org; Wed, 10 Sep 2014 04:14:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45670) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XRd2X-0003qD-NM for qemu-devel@nongnu.org; Wed, 10 Sep 2014 04:14:09 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s8A8E7hd028789 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 10 Sep 2014 04:14:08 -0400 Received: from blackfin.pond.sub.org (ovpn-116-70.ams2.redhat.com [10.36.116.70]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s8A8E0xM018696 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 10 Sep 2014 04:14:04 -0400 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 66090305CAB9; Wed, 10 Sep 2014 10:13:53 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 10 Sep 2014 10:13:51 +0200 Message-Id: <1410336832-22160-23-git-send-email-armbru@redhat.com> In-Reply-To: <1410336832-22160-1-git-send-email-armbru@redhat.com> References: <1410336832-22160-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, benoit.canet@irqsave.net, famz@redhat.com, stefanha@redhat.com Subject: [Qemu-devel] [PATCH 22/23] block: Lift device model API into BlockBackend X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Move device model attachment / detachment and the BlockDevOps device model callbacks and their wrappers from BlockDriverState to BlockBackend. Signed-off-by: Markus Armbruster --- block.c | 126 +++++------------------------------------ block/block-backend.c | 107 ++++++++++++++++++++++++++++++---- 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, 159 insertions(+), 182 deletions(-) diff --git a/block.c b/block.c index f71b87c..e81087f 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); @@ -1516,7 +1513,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 */ @@ -1841,7 +1840,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) { @@ -1949,9 +1950,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; @@ -2017,7 +2015,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)); @@ -2034,7 +2031,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)); @@ -2073,7 +2069,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); @@ -2087,105 +2082,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 * @@ -3520,7 +3416,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; } @@ -3714,8 +3612,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 1bac033..6c0c8f2 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); @@ -85,6 +94,7 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp) static void blk_delete(BlockBackend *blk) { assert(!blk->refcnt); + assert(!blk->dev); bdrv_unref(blk->bs); blk_detach_bs(blk); QTAILQ_REMOVE(&blk_backends, blk, link); @@ -237,34 +247,109 @@ BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo) assert(0); } -void blk_iostatus_enable(BlockBackend *blk) -{ - bdrv_iostatus_enable(blk->bs); -} - 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; } +/* 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(); + } } 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); } +/* TODO change to return DeviceState * when all users are qdevified */ void *blk_get_attached_dev(BlockBackend *blk) { - return bdrv_get_attached_dev(blk->bs); + return blk->dev; } -void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque) +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; +} + +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); + } + } +} + +bool blk_dev_has_removable_media(BlockBackend *blk) +{ + return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb); +} + +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); + } +} + +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; +} + +void blk_dev_resize_cb(BlockBackend *blk) +{ + if (blk->dev_ops && blk->dev_ops->resize_cb) { + blk->dev_ops->resize_cb(blk->dev_opaque); + } +} + +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; +} + +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 02121b2..921e620 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 6286c0e..6dc405b 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1508,14 +1508,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)); @@ -1746,7 +1746,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_make_anon(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 15a5290..3252039 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -47,41 +47,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, @@ -228,16 +193,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 b3246e7..3b20031 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -325,11 +325,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 73f9325..d8734bb 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);