blockjob: Add permissions to block_job_add_bdrv()
Block jobs don't actually do I/O through the the reference they create with block_job_add_bdrv(), but they might want to use the permisssion system to express what the block job does to intermediate nodes. This adds permissions to block_job_add_bdrv() to provide the means to request permissions. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Acked-by: Fam Zheng <famz@redhat.com>
This commit is contained in:
parent
26de9438c1
commit
76d554e20b
@ -657,7 +657,9 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|||||||
job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
|
job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
block_job_add_bdrv(&job->common, target);
|
/* FIXME Use real permissions */
|
||||||
|
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
|
||||||
|
&error_abort);
|
||||||
job->common.len = len;
|
job->common.len = len;
|
||||||
block_job_txn_add_job(txn, &job->common);
|
block_job_txn_add_job(txn, &job->common);
|
||||||
|
|
||||||
|
@ -267,13 +267,17 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
|||||||
* disappear from the chain after this operation. */
|
* disappear from the chain after this operation. */
|
||||||
assert(bdrv_chain_contains(top, base));
|
assert(bdrv_chain_contains(top, base));
|
||||||
for (iter = top; iter != backing_bs(base); iter = backing_bs(iter)) {
|
for (iter = top; iter != backing_bs(base); iter = backing_bs(iter)) {
|
||||||
block_job_add_bdrv(&s->common, iter);
|
/* FIXME Use real permissions */
|
||||||
|
block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
|
||||||
|
BLK_PERM_ALL, &error_abort);
|
||||||
}
|
}
|
||||||
/* overlay_bs must be blocked because it needs to be modified to
|
/* overlay_bs must be blocked because it needs to be modified to
|
||||||
* update the backing image string, but if it's the root node then
|
* update the backing image string, but if it's the root node then
|
||||||
* don't block it again */
|
* don't block it again */
|
||||||
if (bs != overlay_bs) {
|
if (bs != overlay_bs) {
|
||||||
block_job_add_bdrv(&s->common, overlay_bs);
|
/* FIXME Use real permissions */
|
||||||
|
block_job_add_bdrv(&s->common, "overlay of top", overlay_bs, 0,
|
||||||
|
BLK_PERM_ALL, &error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME Use real permissions */
|
/* FIXME Use real permissions */
|
||||||
|
@ -1052,13 +1052,18 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
block_job_add_bdrv(&s->common, target);
|
/* FIXME Use real permissions */
|
||||||
|
block_job_add_bdrv(&s->common, "target", target, 0, BLK_PERM_ALL,
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
/* In commit_active_start() all intermediate nodes disappear, so
|
/* In commit_active_start() all intermediate nodes disappear, so
|
||||||
* any jobs in them must be blocked */
|
* any jobs in them must be blocked */
|
||||||
if (bdrv_chain_contains(bs, target)) {
|
if (bdrv_chain_contains(bs, target)) {
|
||||||
BlockDriverState *iter;
|
BlockDriverState *iter;
|
||||||
for (iter = backing_bs(bs); iter != target; iter = backing_bs(iter)) {
|
for (iter = backing_bs(bs); iter != target; iter = backing_bs(iter)) {
|
||||||
block_job_add_bdrv(&s->common, iter);
|
/* FIXME Use real permissions */
|
||||||
|
block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
|
||||||
|
BLK_PERM_ALL, &error_abort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +248,9 @@ void stream_start(const char *job_id, BlockDriverState *bs,
|
|||||||
/* Block all intermediate nodes between bs and base, because they
|
/* Block all intermediate nodes between bs and base, because they
|
||||||
* will disappear from the chain after this operation */
|
* will disappear from the chain after this operation */
|
||||||
for (iter = backing_bs(bs); iter && iter != base; iter = backing_bs(iter)) {
|
for (iter = backing_bs(bs); iter && iter != base; iter = backing_bs(iter)) {
|
||||||
block_job_add_bdrv(&s->common, iter);
|
/* FIXME Use real permissions */
|
||||||
|
block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
|
||||||
|
BLK_PERM_ALL, &error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->base = base;
|
s->base = base;
|
||||||
|
36
blockjob.c
36
blockjob.c
@ -55,6 +55,19 @@ struct BlockJobTxn {
|
|||||||
|
|
||||||
static QLIST_HEAD(, BlockJob) block_jobs = QLIST_HEAD_INITIALIZER(block_jobs);
|
static QLIST_HEAD(, BlockJob) block_jobs = QLIST_HEAD_INITIALIZER(block_jobs);
|
||||||
|
|
||||||
|
static char *child_job_get_parent_desc(BdrvChild *c)
|
||||||
|
{
|
||||||
|
BlockJob *job = c->opaque;
|
||||||
|
return g_strdup_printf("%s job '%s'",
|
||||||
|
BlockJobType_lookup[job->driver->job_type],
|
||||||
|
job->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const BdrvChildRole child_job = {
|
||||||
|
.get_parent_desc = child_job_get_parent_desc,
|
||||||
|
.stay_at_node = true,
|
||||||
|
};
|
||||||
|
|
||||||
BlockJob *block_job_next(BlockJob *job)
|
BlockJob *block_job_next(BlockJob *job)
|
||||||
{
|
{
|
||||||
if (!job) {
|
if (!job) {
|
||||||
@ -115,11 +128,22 @@ static void block_job_detach_aio_context(void *opaque)
|
|||||||
block_job_unref(job);
|
block_job_unref(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
void block_job_add_bdrv(BlockJob *job, BlockDriverState *bs)
|
int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
|
||||||
|
uint64_t perm, uint64_t shared_perm, Error **errp)
|
||||||
{
|
{
|
||||||
job->nodes = g_slist_prepend(job->nodes, bs);
|
BdrvChild *c;
|
||||||
|
|
||||||
|
c = bdrv_root_attach_child(bs, name, &child_job, perm, shared_perm,
|
||||||
|
job, errp);
|
||||||
|
if (c == NULL) {
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
job->nodes = g_slist_prepend(job->nodes, c);
|
||||||
bdrv_ref(bs);
|
bdrv_ref(bs);
|
||||||
bdrv_op_block_all(bs, job->blocker);
|
bdrv_op_block_all(bs, job->blocker);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||||
@ -171,7 +195,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
|||||||
job = g_malloc0(driver->instance_size);
|
job = g_malloc0(driver->instance_size);
|
||||||
error_setg(&job->blocker, "block device is in use by block job: %s",
|
error_setg(&job->blocker, "block device is in use by block job: %s",
|
||||||
BlockJobType_lookup[driver->job_type]);
|
BlockJobType_lookup[driver->job_type]);
|
||||||
block_job_add_bdrv(job, bs);
|
block_job_add_bdrv(job, "main node", bs, 0, BLK_PERM_ALL, &error_abort);
|
||||||
bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker);
|
bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker);
|
||||||
|
|
||||||
job->driver = driver;
|
job->driver = driver;
|
||||||
@ -238,9 +262,9 @@ void block_job_unref(BlockJob *job)
|
|||||||
BlockDriverState *bs = blk_bs(job->blk);
|
BlockDriverState *bs = blk_bs(job->blk);
|
||||||
bs->job = NULL;
|
bs->job = NULL;
|
||||||
for (l = job->nodes; l; l = l->next) {
|
for (l = job->nodes; l; l = l->next) {
|
||||||
bs = l->data;
|
BdrvChild *c = l->data;
|
||||||
bdrv_op_unblock_all(bs, job->blocker);
|
bdrv_op_unblock_all(c->bs, job->blocker);
|
||||||
bdrv_unref(bs);
|
bdrv_root_unref_child(c);
|
||||||
}
|
}
|
||||||
g_slist_free(job->nodes);
|
g_slist_free(job->nodes);
|
||||||
blk_remove_aio_context_notifier(job->blk,
|
blk_remove_aio_context_notifier(job->blk,
|
||||||
|
@ -169,13 +169,16 @@ BlockJob *block_job_get(const char *id);
|
|||||||
/**
|
/**
|
||||||
* block_job_add_bdrv:
|
* block_job_add_bdrv:
|
||||||
* @job: A block job
|
* @job: A block job
|
||||||
|
* @name: The name to assign to the new BdrvChild
|
||||||
* @bs: A BlockDriverState that is involved in @job
|
* @bs: A BlockDriverState that is involved in @job
|
||||||
|
* @perm, @shared_perm: Permissions to request on the node
|
||||||
*
|
*
|
||||||
* Add @bs to the list of BlockDriverState that are involved in
|
* Add @bs to the list of BlockDriverState that are involved in
|
||||||
* @job. This means that all operations will be blocked on @bs while
|
* @job. This means that all operations will be blocked on @bs while
|
||||||
* @job exists.
|
* @job exists.
|
||||||
*/
|
*/
|
||||||
void block_job_add_bdrv(BlockJob *job, BlockDriverState *bs);
|
int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
|
||||||
|
uint64_t perm, uint64_t shared_perm, Error **errp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* block_job_set_speed:
|
* block_job_set_speed:
|
||||||
|
Loading…
Reference in New Issue
Block a user