blockdev: acquire AioContext in eject, change, and block_passwd
By acquiring the AioContext we avoid race conditions with the dataplane thread which may also be accessing the BlockDriverState. Fix up eject, change, and block_passwd in a single patch because qmp_eject() and qmp_change_blockdev() both call eject_device(). Also fix block_passwd while we're tackling a command that takes a block encryption password. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
0b92885420
commit
e3442099a2
38
blockdev.c
38
blockdev.c
@ -1617,14 +1617,18 @@ exit:
|
|||||||
static void eject_device(BlockBackend *blk, int force, Error **errp)
|
static void eject_device(BlockBackend *blk, int force, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = blk_bs(blk);
|
BlockDriverState *bs = blk_bs(blk);
|
||||||
|
AioContext *aio_context;
|
||||||
|
|
||||||
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!blk_dev_has_removable_media(blk)) {
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) {
|
if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) {
|
||||||
@ -1632,11 +1636,14 @@ static void eject_device(BlockBackend *blk, int force, Error **errp)
|
|||||||
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));
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_close(bs);
|
bdrv_close(bs);
|
||||||
|
|
||||||
|
out:
|
||||||
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
|
void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
|
||||||
@ -1658,6 +1665,7 @@ void qmp_block_passwd(bool has_device, const char *device,
|
|||||||
{
|
{
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
AioContext *aio_context;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
bs = bdrv_lookup_bs(has_device ? device : NULL,
|
bs = bdrv_lookup_bs(has_device ? device : NULL,
|
||||||
@ -1668,16 +1676,23 @@ void qmp_block_passwd(bool has_device, const char *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
err = bdrv_set_key(bs, password);
|
err = bdrv_set_key(bs, password);
|
||||||
if (err == -EINVAL) {
|
if (err == -EINVAL) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
|
error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
|
||||||
return;
|
goto out;
|
||||||
} else if (err < 0) {
|
} else if (err < 0) {
|
||||||
error_set(errp, QERR_INVALID_PASSWORD);
|
error_set(errp, QERR_INVALID_PASSWORD);
|
||||||
return;
|
goto out;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
aio_context_release(aio_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assumes AioContext is held */
|
||||||
static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename,
|
static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename,
|
||||||
int bdrv_flags, BlockDriver *drv,
|
int bdrv_flags, BlockDriver *drv,
|
||||||
const char *password, Error **errp)
|
const char *password, Error **errp)
|
||||||
@ -1710,6 +1725,7 @@ void qmp_change_blockdev(const char *device, const char *filename,
|
|||||||
{
|
{
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
AioContext *aio_context;
|
||||||
BlockDriver *drv = NULL;
|
BlockDriver *drv = NULL;
|
||||||
int bdrv_flags;
|
int bdrv_flags;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
@ -1721,24 +1737,30 @@ void qmp_change_blockdev(const char *device, const char *filename,
|
|||||||
}
|
}
|
||||||
bs = blk_bs(blk);
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
if (format) {
|
if (format) {
|
||||||
drv = bdrv_find_whitelisted_format(format, bs->read_only);
|
drv = bdrv_find_whitelisted_format(format, bs->read_only);
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
|
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eject_device(blk, 0, &err);
|
eject_device(blk, 0, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
|
bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
|
||||||
bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0;
|
bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0;
|
||||||
|
|
||||||
qmp_bdrv_open_encrypted(bs, filename, bdrv_flags, drv, NULL, errp);
|
qmp_bdrv_open_encrypted(bs, filename, bdrv_flags, drv, NULL, errp);
|
||||||
|
|
||||||
|
out:
|
||||||
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* throttling disk I/O limits */
|
/* throttling disk I/O limits */
|
||||||
|
@ -198,6 +198,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
|
|||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
|
||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker);
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker);
|
||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_COMMIT, s->blocker);
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_COMMIT, s->blocker);
|
||||||
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker);
|
||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE,
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE,
|
||||||
s->blocker);
|
s->blocker);
|
||||||
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_MIRROR, s->blocker);
|
blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_MIRROR, s->blocker);
|
||||||
|
Loading…
Reference in New Issue
Block a user