block: Lift device model API into BlockBackend
Move device model attachment / detachment and the BlockDevOps device
model callbacks and their wrappers from BlockDriverState to
BlockBackend.
Wrapper calls in block.c change from
    bdrv_dev_FOO_cb(bs, ...)
to
    if (bs->blk) {
        bdrv_dev_FOO_cb(bs->blk, ...);
    }
No change, because both bdrv_dev_change_media_cb() and
bdrv_dev_resize_cb() do nothing when no device model is attached, and
a device model can be attached only when bs->blk.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									6007cdd448
								
							
						
					
					
						commit
						a7f53e26a6
					
				
							
								
								
									
										126
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										126
									
								
								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; | ||||
| 
 | ||||
| @ -2043,7 +2041,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)); | ||||
| 
 | ||||
| @ -2060,7 +2057,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)); | ||||
| @ -2099,7 +2095,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); | ||||
| @ -2113,105 +2108,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 | ||||
|  * | ||||
| @ -3545,7 +3441,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; | ||||
| } | ||||
| @ -3746,8 +3644,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; | ||||
| } | ||||
|  | ||||
| @ -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;    /* null unless created by drive_new() */ | ||||
|     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); | ||||
|     if (blk->bs) { | ||||
|         assert(blk->bs->blk == blk); | ||||
|         blk->bs->blk = NULL; | ||||
| @ -237,36 +247,155 @@ void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 */ | ||||
| { | ||||
|     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) | ||||
| { | ||||
|     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 */ | ||||
| { | ||||
|     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 blk->dev; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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) | ||||
| { | ||||
|     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_attach_dev(BlockBackend *blk, void *dev) | ||||
| { | ||||
|     return bdrv_attach_dev(blk->bs, dev); | ||||
| } | ||||
| 
 | ||||
| void blk_attach_dev_nofail(BlockBackend *blk, void *dev) | ||||
| { | ||||
|     bdrv_attach_dev_nofail(blk->bs, dev); | ||||
| } | ||||
| 
 | ||||
| void blk_detach_dev(BlockBackend *blk, void *dev) | ||||
| { | ||||
|     bdrv_detach_dev(blk->bs, dev); | ||||
| } | ||||
| 
 | ||||
| void *blk_get_attached_dev(BlockBackend *blk) | ||||
| { | ||||
|     return bdrv_get_attached_dev(blk->bs); | ||||
| } | ||||
| 
 | ||||
| void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque) | ||||
| { | ||||
|     bdrv_set_dev_ops(blk->bs, ops, opaque); | ||||
| } | ||||
| 
 | ||||
| int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, | ||||
|              int nb_sectors) | ||||
| { | ||||
|  | ||||
| @ -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)) { | ||||
|  | ||||
							
								
								
									
										10
									
								
								blockdev.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								blockdev.c
									
									
									
									
									
								
							| @ -217,7 +217,7 @@ bool drive_check_orphaned(void) | ||||
|         dinfo = blk_legacy_dinfo(blk); | ||||
|         /* If dinfo->bdrv->dev is NULL, it has no device attached. */ | ||||
|         /* Unless this is a default drive, this may be an oversight. */ | ||||
|         if (!blk_bs(blk)->dev && !dinfo->is_default && | ||||
|         if (!blk_get_attached_dev(blk) && !dinfo->is_default && | ||||
|             dinfo->type != IF_NONE) { | ||||
|             fprintf(stderr, "Warning: Orphaned drive without device: " | ||||
|                     "id=%s,file=%s,if=%s,bus=%d,unit=%d\n", | ||||
| @ -1600,14 +1600,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)); | ||||
| @ -1844,7 +1844,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, | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Markus Armbruster
						Markus Armbruster