From: Yu Kuai Currently there are many helpers to be used in different cases: - blkg_conf_open_bdev() - blkg_conf_open_bdev_frozen() - blkg_conf_prep() - blkg_conf_exit() - blkg_conf_exit_frozen() This patch introduce two new helpers: - blkg_conf_start() - blkg_conf_end() And following patches will convert all blkcg policy to use this two helpers. Signed-off-by: Yu Kuai --- block/blk-cgroup.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ block/blk-cgroup.h | 3 +++ 2 files changed, 64 insertions(+) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 3c23d2d1e237..63089ae269cb 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -824,6 +824,67 @@ unsigned long __must_check blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx) return memflags; } +void blkg_conf_end(struct blkg_conf_ctx *ctx) +{ + struct request_queue *q = bdev_get_queue(ctx->bdev); + + mutex_unlock(&q->blkcg_mutex); + mutex_unlock(&q->rq_qos_mutex); + mutex_unlock(&q->elevator_lock); + blk_mq_unfreeze_queue(q, ctx->memflags); + blkdev_put_no_open(ctx->bdev); +} +EXPORT_SYMBOL_GPL(blkg_conf_end); + +int blkg_conf_start(struct blkcg *blkcg, struct blkg_conf_ctx *ctx) +{ + char *input = ctx->input; + unsigned int major, minor; + struct block_device *bdev; + struct request_queue *q; + int key_len; + + if (sscanf(input, "%u:%u%n", &major, &minor, &key_len) != 2) + return -EINVAL; + + input += key_len; + if (!isspace(*input)) + return -EINVAL; + + input = skip_spaces(input); + bdev = blkdev_get_no_open(MKDEV(major, minor), false); + if (!bdev) + return -ENODEV; + + if (bdev_is_partition(bdev)) { + blkdev_put_no_open(bdev); + return -ENODEV; + } + + if (!disk_live(bdev->bd_disk)) { + blkdev_put_no_open(bdev); + return -ENODEV; + } + + ctx->body = input; + ctx->bdev = bdev; + ctx->memflags = blk_mq_freeze_queue(ctx->bdev->bd_queue); + + q = bdev->bd_queue; + mutex_lock(&q->elevator_lock); + mutex_lock(&q->rq_qos_mutex); + mutex_lock(&q->blkcg_mutex); + + ctx->blkg = blkg_lookup_create(blkcg, bdev->bd_disk); + if (!ctx->blkg) { + blkg_conf_end(ctx); + return -ENOMEM; + } + + return 0; +} +EXPORT_SYMBOL_GPL(blkg_conf_start); + /** * blkg_conf_prep - parse and prepare for per-blkg config update * @blkcg: target block cgroup diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 540be30aebcd..e7868989befb 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -217,6 +217,7 @@ struct blkg_conf_ctx { char *body; struct block_device *bdev; struct blkcg_gq *blkg; + unsigned long memflags; }; void blkg_conf_init(struct blkg_conf_ctx *ctx, char *input); @@ -226,6 +227,8 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, struct blkg_conf_ctx *ctx); void blkg_conf_exit(struct blkg_conf_ctx *ctx); void blkg_conf_exit_frozen(struct blkg_conf_ctx *ctx, unsigned long memflags); +void blkg_conf_end(struct blkg_conf_ctx *ctx); +int blkg_conf_start(struct blkcg *blkcg, struct blkg_conf_ctx *ctx); /** * bio_issue_as_root_blkg - see if this bio needs to be issued as root blkg -- 2.51.0