Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions block/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# Makefile for the kernel block layer
#

CONTEXT_ANALYSIS := y

obj-y := bdev.o fops.o bio.o elevator.o blk-core.o blk-sysfs.o \
blk-flush.o blk-settings.o blk-ioc.o blk-map.o \
blk-merge.o blk-timeout.o blk-lib.o blk-mq.o \
Expand Down
10 changes: 8 additions & 2 deletions block/bdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,9 @@ int bdev_freeze(struct block_device *bdev)
mutex_lock(&bdev->bd_holder_lock);
if (bdev->bd_holder_ops && bdev->bd_holder_ops->freeze) {
error = bdev->bd_holder_ops->freeze(bdev);
/* bdev->bd_holder_ops->freeze() releases bd_holder_lock */
lockdep_assert_not_held(&bdev->bd_holder_lock);
__release(&bdev->bd_holder_lock);
} else {
mutex_unlock(&bdev->bd_holder_lock);
error = sync_blockdev(bdev);
Expand Down Expand Up @@ -355,7 +357,9 @@ int bdev_thaw(struct block_device *bdev)
mutex_lock(&bdev->bd_holder_lock);
if (bdev->bd_holder_ops && bdev->bd_holder_ops->thaw) {
error = bdev->bd_holder_ops->thaw(bdev);
/* bdev->bd_holder_ops->thaw() releases bd_holder_lock */
lockdep_assert_not_held(&bdev->bd_holder_lock);
__release(&bdev->bd_holder_lock);
} else {
mutex_unlock(&bdev->bd_holder_lock);
}
Expand Down Expand Up @@ -1254,9 +1258,11 @@ EXPORT_SYMBOL(lookup_bdev);
void bdev_mark_dead(struct block_device *bdev, bool surprise)
{
mutex_lock(&bdev->bd_holder_lock);
if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead)
if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead) {
bdev->bd_holder_ops->mark_dead(bdev, surprise);
else {
/* bdev->bd_holder_ops->mark_dead() releases bd_holder_lock */
__release(&bdev->bd_holder_lock);
} else {
mutex_unlock(&bdev->bd_holder_lock);
sync_blockdev(bdev);
}
Expand Down
11 changes: 9 additions & 2 deletions block/bfq-cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1051,9 +1051,13 @@ static ssize_t bfq_io_set_device_weight(struct kernfs_open_file *of,

blkg_conf_init(&ctx, buf);

ret = blkg_conf_open_bdev(&ctx);
if (ret)
return ret;

ret = blkg_conf_prep(blkcg, &blkcg_policy_bfq, &ctx);
if (ret)
goto out;
goto close_bdev;

if (sscanf(ctx.body, "%llu", &v) == 1) {
/* require "default" on dfl */
Expand All @@ -1074,8 +1078,11 @@ static ssize_t bfq_io_set_device_weight(struct kernfs_open_file *of,
bfq_group_set_weight(bfqg, bfqg->entity.weight, v);
ret = 0;
}

out:
blkg_conf_exit(&ctx);
blkg_conf_unprep(&ctx);
close_bdev:
blkg_conf_close_bdev(&ctx);
return ret ?: nbytes;
}

Expand Down
98 changes: 24 additions & 74 deletions block/blk-cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ EXPORT_SYMBOL_GPL(__blkg_prfill_u64);
*
* Initialize @ctx which can be used to parse blkg config input string @input.
* Once initialized, @ctx can be used with blkg_conf_open_bdev() and
* blkg_conf_prep(), and must be cleaned up with blkg_conf_exit().
* blkg_conf_prep().
*/
void blkg_conf_init(struct blkg_conf_ctx *ctx, char *input)
{
Expand All @@ -768,10 +768,7 @@ EXPORT_SYMBOL_GPL(blkg_conf_init);
* @ctx->input and get and store the matching bdev in @ctx->bdev. @ctx->body is
* set to point past the device node prefix.
*
* This function may be called multiple times on @ctx and the extra calls become
* NOOPs. blkg_conf_prep() implicitly calls this function. Use this function
* explicitly if bdev access is needed without resolving the blkcg / policy part
* of @ctx->input. Returns -errno on error.
* Returns: -errno on error.
*/
int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
{
Expand All @@ -780,8 +777,8 @@ int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
struct block_device *bdev;
int key_len;

if (ctx->bdev)
return 0;
if (WARN_ON_ONCE(ctx->bdev))
return -EINVAL;

if (sscanf(input, "%u:%u%n", &major, &minor, &key_len) != 2)
return -EINVAL;
Expand Down Expand Up @@ -810,38 +807,7 @@ int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
ctx->bdev = bdev;
return 0;
}
/*
* Similar to blkg_conf_open_bdev, but additionally freezes the queue,
* ensures the correct locking order between freeze queue and q->rq_qos_mutex.
*
* This function returns negative error on failure. On success it returns
* memflags which must be saved and later passed to blkg_conf_exit_frozen
* for restoring the memalloc scope.
*/
unsigned long __must_check blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx)
{
int ret;
unsigned long memflags;

if (ctx->bdev)
return -EINVAL;

ret = blkg_conf_open_bdev(ctx);
if (ret < 0)
return ret;
/*
* At this point, we haven’t started protecting anything related to QoS,
* so we release q->rq_qos_mutex here, which was first acquired in blkg_
* conf_open_bdev. Later, we re-acquire q->rq_qos_mutex after freezing
* the queue to maintain the correct locking order.
*/
mutex_unlock(&ctx->bdev->bd_queue->rq_qos_mutex);

memflags = blk_mq_freeze_queue(ctx->bdev->bd_queue);
mutex_lock(&ctx->bdev->bd_queue->rq_qos_mutex);

return memflags;
}
EXPORT_SYMBOL_GPL(blkg_conf_open_bdev);

/**
* blkg_conf_prep - parse and prepare for per-blkg config update
Expand All @@ -854,22 +820,20 @@ unsigned long __must_check blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx)
* following MAJ:MIN, @ctx->bdev points to the target block device and
* @ctx->blkg to the blkg being configured.
*
* blkg_conf_open_bdev() may be called on @ctx beforehand. On success, this
* blkg_conf_open_bdev() must be called on @ctx beforehand. On success, this
* function returns with queue lock held and must be followed by
* blkg_conf_exit().
* blkg_conf_close_bdev().
*/
int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
struct blkg_conf_ctx *ctx)
__acquires(&bdev->bd_queue->queue_lock)
{
struct gendisk *disk;
struct request_queue *q;
struct blkcg_gq *blkg;
int ret;

ret = blkg_conf_open_bdev(ctx);
if (ret)
return ret;
if (WARN_ON_ONCE(!ctx->bdev))
return -EINVAL;

disk = ctx->bdev->bd_disk;
q = disk->queue;
Expand Down Expand Up @@ -967,43 +931,29 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
EXPORT_SYMBOL_GPL(blkg_conf_prep);

/**
* blkg_conf_exit - clean up per-blkg config update
* blkg_conf_unprep - counterpart of blkg_conf_prep()
* @ctx: blkg_conf_ctx initialized with blkg_conf_init()
*
* Clean up after per-blkg config update. This function must be called on all
* blkg_conf_ctx's initialized with blkg_conf_init().
*/
void blkg_conf_exit(struct blkg_conf_ctx *ctx)
__releases(&ctx->bdev->bd_queue->queue_lock)
__releases(&ctx->bdev->bd_queue->rq_qos_mutex)
void blkg_conf_unprep(struct blkg_conf_ctx *ctx)
{
if (ctx->blkg) {
spin_unlock_irq(&bdev_get_queue(ctx->bdev)->queue_lock);
ctx->blkg = NULL;
}

if (ctx->bdev) {
mutex_unlock(&ctx->bdev->bd_queue->rq_qos_mutex);
blkdev_put_no_open(ctx->bdev);
ctx->body = NULL;
ctx->bdev = NULL;
}
WARN_ON_ONCE(!ctx->blkg);
spin_unlock_irq(&ctx->bdev->bd_disk->queue->queue_lock);
ctx->blkg = NULL;
}
EXPORT_SYMBOL_GPL(blkg_conf_exit);
EXPORT_SYMBOL_GPL(blkg_conf_unprep);

/*
* Similar to blkg_conf_exit, but also unfreezes the queue. Should be used
* when blkg_conf_open_bdev_frozen is used to open the bdev.
/**
* blkg_conf_close_bdev - counterpart of blkg_conf_open_bdev()
* @ctx: blkg_conf_ctx initialized with blkg_conf_init()
*/
void blkg_conf_exit_frozen(struct blkg_conf_ctx *ctx, unsigned long memflags)
void blkg_conf_close_bdev(struct blkg_conf_ctx *ctx)
{
if (ctx->bdev) {
struct request_queue *q = ctx->bdev->bd_queue;

blkg_conf_exit(ctx);
blk_mq_unfreeze_queue(q, memflags);
}
mutex_unlock(&ctx->bdev->bd_queue->rq_qos_mutex);
blkdev_put_no_open(ctx->bdev);
ctx->body = NULL;
ctx->bdev = NULL;
}
EXPORT_SYMBOL_GPL(blkg_conf_close_bdev);

static void blkg_iostat_add(struct blkg_iostat *dst, struct blkg_iostat *src)
{
Expand Down
13 changes: 8 additions & 5 deletions block/blk-cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,15 @@ struct blkg_conf_ctx {
};

void blkg_conf_init(struct blkg_conf_ctx *ctx, char *input);
int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx);
unsigned long blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx);
int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
__cond_acquires(0, &ctx->bdev->bd_queue->rq_qos_mutex);
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);
struct blkg_conf_ctx *ctx)
__cond_acquires(0, &ctx->bdev->bd_disk->queue->queue_lock);
void blkg_conf_unprep(struct blkg_conf_ctx *ctx)
__releases(ctx->bdev->bd_disk->queue->queue_lock);
void blkg_conf_close_bdev(struct blkg_conf_ctx *ctx)
__releases(&ctx->bdev->bd_queue->rq_qos_mutex);

/**
* bio_issue_as_root_blkg - see if this bio needs to be issued as root blkg
Expand Down
2 changes: 2 additions & 0 deletions block/blk-crypto-profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct blk_crypto_keyslot {
};

static inline void blk_crypto_hw_enter(struct blk_crypto_profile *profile)
__acquires(&profile->lock)
{
/*
* Calling into the driver requires profile->lock held and the device
Expand All @@ -55,6 +56,7 @@ static inline void blk_crypto_hw_enter(struct blk_crypto_profile *profile)
}

static inline void blk_crypto_hw_exit(struct blk_crypto_profile *profile)
__releases(&profile->lock)
{
up_write(&profile->lock);
if (profile->dev)
Expand Down
Loading
Loading