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 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,
 | 
					static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
 | 
				
			||||||
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
 | 
					        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
 | 
				
			||||||
        BlockCompletionFunc *cb, void *opaque);
 | 
					        BlockCompletionFunc *cb, void *opaque);
 | 
				
			||||||
| 
						 | 
					@ -1527,7 +1524,9 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!bdrv_key_required(bs)) {
 | 
					    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)
 | 
					    } else if (!runstate_check(RUN_STATE_PRELAUNCH)
 | 
				
			||||||
               && !runstate_check(RUN_STATE_INMIGRATE)
 | 
					               && !runstate_check(RUN_STATE_INMIGRATE)
 | 
				
			||||||
               && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */
 | 
					               && !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*/
 | 
					    /*throttling disk I/O limits*/
 | 
				
			||||||
    if (bs->io_limits_enabled) {
 | 
					    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 */
 | 
					    /* move some fields that need to stay attached to the device */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* dev info */
 | 
					    /* 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->guest_block_size   = bs_src->guest_block_size;
 | 
				
			||||||
    bs_dest->copy_on_read       = bs_src->copy_on_read;
 | 
					    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(!bs_new->blk);
 | 
				
			||||||
    assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
 | 
					    assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
 | 
				
			||||||
    assert(bs_new->job == NULL);
 | 
					    assert(bs_new->job == NULL);
 | 
				
			||||||
    assert(bs_new->dev == NULL);
 | 
					 | 
				
			||||||
    assert(bs_new->io_limits_enabled == false);
 | 
					    assert(bs_new->io_limits_enabled == false);
 | 
				
			||||||
    assert(!throttle_have_timer(&bs_new->throttle_state));
 | 
					    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);
 | 
					    assert(!bs_new->blk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Check a few fields that should remain attached to the device */
 | 
					    /* Check a few fields that should remain attached to the device */
 | 
				
			||||||
    assert(bs_new->dev == NULL);
 | 
					 | 
				
			||||||
    assert(bs_new->job == NULL);
 | 
					    assert(bs_new->job == NULL);
 | 
				
			||||||
    assert(bs_new->io_limits_enabled == false);
 | 
					    assert(bs_new->io_limits_enabled == false);
 | 
				
			||||||
    assert(!throttle_have_timer(&bs_new->throttle_state));
 | 
					    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)
 | 
					static void bdrv_delete(BlockDriverState *bs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    assert(!bs->dev);
 | 
					 | 
				
			||||||
    assert(!bs->job);
 | 
					    assert(!bs->job);
 | 
				
			||||||
    assert(bdrv_op_blocker_is_empty(bs));
 | 
					    assert(bdrv_op_blocker_is_empty(bs));
 | 
				
			||||||
    assert(!bs->refcnt);
 | 
					    assert(!bs->refcnt);
 | 
				
			||||||
| 
						 | 
					@ -2113,105 +2108,6 @@ static void bdrv_delete(BlockDriverState *bs)
 | 
				
			||||||
    g_free(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
 | 
					 * Run consistency checks on an image
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -3545,7 +3441,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
 | 
				
			||||||
    ret = drv->bdrv_truncate(bs, offset);
 | 
					    ret = drv->bdrv_truncate(bs, offset);
 | 
				
			||||||
    if (ret == 0) {
 | 
					    if (ret == 0) {
 | 
				
			||||||
        ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
 | 
					        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;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3746,8 +3644,10 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
 | 
				
			||||||
        bs->valid_key = 0;
 | 
					        bs->valid_key = 0;
 | 
				
			||||||
    } else if (!bs->valid_key) {
 | 
					    } else if (!bs->valid_key) {
 | 
				
			||||||
        bs->valid_key = 1;
 | 
					        bs->valid_key = 1;
 | 
				
			||||||
        /* call the change callback now, we skipped it on open */
 | 
					        if (bs->blk) {
 | 
				
			||||||
        bdrv_dev_change_media_cb(bs, true);
 | 
					            /* call the change callback now, we skipped it on open */
 | 
				
			||||||
 | 
					            blk_dev_change_media_cb(bs->blk, true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,10 @@
 | 
				
			||||||
#include "sysemu/block-backend.h"
 | 
					#include "sysemu/block-backend.h"
 | 
				
			||||||
#include "block/block_int.h"
 | 
					#include "block/block_int.h"
 | 
				
			||||||
#include "sysemu/blockdev.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 {
 | 
					struct BlockBackend {
 | 
				
			||||||
    char *name;
 | 
					    char *name;
 | 
				
			||||||
| 
						 | 
					@ -20,6 +24,11 @@ struct BlockBackend {
 | 
				
			||||||
    BlockDriverState *bs;
 | 
					    BlockDriverState *bs;
 | 
				
			||||||
    DriveInfo *legacy_dinfo;    /* null unless created by drive_new() */
 | 
					    DriveInfo *legacy_dinfo;    /* null unless created by drive_new() */
 | 
				
			||||||
    QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
 | 
					    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);
 | 
					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)
 | 
					static void blk_delete(BlockBackend *blk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    assert(!blk->refcnt);
 | 
					    assert(!blk->refcnt);
 | 
				
			||||||
 | 
					    assert(!blk->dev);
 | 
				
			||||||
    if (blk->bs) {
 | 
					    if (blk->bs) {
 | 
				
			||||||
        assert(blk->bs->blk == blk);
 | 
					        assert(blk->bs->blk == blk);
 | 
				
			||||||
        blk->bs->blk = NULL;
 | 
					        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)
 | 
					void blk_iostatus_enable(BlockBackend *blk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bdrv_iostatus_enable(blk->bs);
 | 
					    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 blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
 | 
				
			||||||
             int nb_sectors)
 | 
					             int nb_sectors)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -275,12 +275,12 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
 | 
				
			||||||
    Error *local_err = NULL;
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
    info->device = g_strdup(blk_name(blk));
 | 
					    info->device = g_strdup(blk_name(blk));
 | 
				
			||||||
    info->type = g_strdup("unknown");
 | 
					    info->type = g_strdup("unknown");
 | 
				
			||||||
    info->locked = bdrv_dev_is_medium_locked(bs);
 | 
					    info->locked = blk_dev_is_medium_locked(blk);
 | 
				
			||||||
    info->removable = bdrv_dev_has_removable_media(bs);
 | 
					    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->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)) {
 | 
					    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);
 | 
					        dinfo = blk_legacy_dinfo(blk);
 | 
				
			||||||
        /* If dinfo->bdrv->dev is NULL, it has no device attached. */
 | 
					        /* If dinfo->bdrv->dev is NULL, it has no device attached. */
 | 
				
			||||||
        /* Unless this is a default drive, this may be an oversight. */
 | 
					        /* 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) {
 | 
					            dinfo->type != IF_NONE) {
 | 
				
			||||||
            fprintf(stderr, "Warning: Orphaned drive without device: "
 | 
					            fprintf(stderr, "Warning: Orphaned drive without device: "
 | 
				
			||||||
                    "id=%s,file=%s,if=%s,bus=%d,unit=%d\n",
 | 
					                    "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)) {
 | 
					    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!bdrv_dev_has_removable_media(bs)) {
 | 
					    if (!blk_dev_has_removable_media(blk)) {
 | 
				
			||||||
        error_setg(errp, "Device '%s' is not removable",
 | 
					        error_setg(errp, "Device '%s' is not removable",
 | 
				
			||||||
                   bdrv_get_device_name(bs));
 | 
					                   bdrv_get_device_name(bs));
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) {
 | 
					    if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) {
 | 
				
			||||||
        bdrv_dev_eject_request(bs, force);
 | 
					        blk_dev_eject_request(blk, force);
 | 
				
			||||||
        if (!force) {
 | 
					        if (!force) {
 | 
				
			||||||
            error_setg(errp, "Device '%s' is locked",
 | 
					            error_setg(errp, "Device '%s' is locked",
 | 
				
			||||||
                       bdrv_get_device_name(bs));
 | 
					                       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
 | 
					     * 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.
 | 
					     * 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);
 | 
					        blk_hide_on_behalf_of_do_drive_del(blk);
 | 
				
			||||||
        /* Further I/O must not pause the guest */
 | 
					        /* Further I/O must not pause the guest */
 | 
				
			||||||
        bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
 | 
					        bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,41 +48,6 @@ typedef struct BlockFragInfo {
 | 
				
			||||||
    uint64_t compressed_clusters;
 | 
					    uint64_t compressed_clusters;
 | 
				
			||||||
} BlockFragInfo;
 | 
					} 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 {
 | 
					typedef enum {
 | 
				
			||||||
    BDRV_REQ_COPY_ON_READ = 0x1,
 | 
					    BDRV_REQ_COPY_ON_READ = 0x1,
 | 
				
			||||||
    BDRV_REQ_ZERO_WRITE   = 0x2,
 | 
					    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_reopen_abort(BDRVReopenState *reopen_state);
 | 
				
			||||||
void bdrv_close(BlockDriverState *bs);
 | 
					void bdrv_close(BlockDriverState *bs);
 | 
				
			||||||
void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify);
 | 
					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,
 | 
					int bdrv_read(BlockDriverState *bs, int64_t sector_num,
 | 
				
			||||||
              uint8_t *buf, int nb_sectors);
 | 
					              uint8_t *buf, int nb_sectors);
 | 
				
			||||||
int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num,
 | 
					int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -326,11 +326,6 @@ struct BlockDriverState {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    BlockBackend *blk;          /* owning backend, if any */
 | 
					    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 */
 | 
					    AioContext *aio_context; /* event loop used for fd handlers, timers, etc */
 | 
				
			||||||
    /* long-running tasks intended to always use the same AioContext as this
 | 
					    /* long-running tasks intended to always use the same AioContext as this
 | 
				
			||||||
     * BDS may register themselves in this list to be notified of changes
 | 
					     * 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,
 | 
					                  BlockCompletionFunc *cb, void *opaque,
 | 
				
			||||||
                  Error **errp);
 | 
					                  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 */
 | 
					#endif /* BLOCK_INT_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,41 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#include "block/block.h"
 | 
					#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(const char *name, Error **errp);
 | 
				
			||||||
BlockBackend *blk_new_with_bs(const char *name, Error **errp);
 | 
					BlockBackend *blk_new_with_bs(const char *name, Error **errp);
 | 
				
			||||||
void blk_ref(BlockBackend *blk);
 | 
					void blk_ref(BlockBackend *blk);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue