Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
7 changes: 2 additions & 5 deletions block/blk-cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1580,12 +1580,13 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
struct request_queue *q = disk->queue;
struct blkg_policy_data *pd_prealloc = NULL;
struct blkcg_gq *blkg, *pinned_blkg = NULL;
unsigned int memflags;
int ret;

if (blkcg_policy_enabled(q, pol))
return 0;

WARN_ON_ONCE(q->mq_freeze_depth == 0);

/*
* Policy is allowed to be registered without pd_alloc_fn/pd_free_fn,
* for example, ioprio. Such policy will work on blkcg level, not disk
Expand All @@ -1594,8 +1595,6 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
if (WARN_ON_ONCE(!pol->pd_alloc_fn || !pol->pd_free_fn))
return -EINVAL;

if (queue_is_mq(q))
memflags = blk_mq_freeze_queue(q);
retry:
spin_lock_irq(&q->queue_lock);

Expand Down Expand Up @@ -1658,8 +1657,6 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)

spin_unlock_irq(&q->queue_lock);
out:
if (queue_is_mq(q))
blk_mq_unfreeze_queue(q, memflags);
if (pinned_blkg)
blkg_put(pinned_blkg);
if (pd_prealloc)
Expand Down
15 changes: 7 additions & 8 deletions block/blk-iocost.c
Original file line number Diff line number Diff line change
Expand Up @@ -3408,7 +3408,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
{
struct blkg_conf_ctx ctx;
struct request_queue *q;
unsigned int memflags;
unsigned long memflags;
struct ioc *ioc;
u64 u[NR_I_LCOEFS];
bool user;
Expand All @@ -3417,9 +3417,11 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,

blkg_conf_init(&ctx, input);

ret = blkg_conf_open_bdev(&ctx);
if (ret)
memflags = blkg_conf_open_bdev_frozen(&ctx);
if (IS_ERR_VALUE(memflags)) {
ret = memflags;
goto err;
}

body = ctx.body;
q = bdev_get_queue(ctx.bdev);
Expand All @@ -3436,7 +3438,6 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
ioc = q_to_ioc(q);
}

memflags = blk_mq_freeze_queue(q);
blk_mq_quiesce_queue(q);

spin_lock_irq(&ioc->lock);
Expand Down Expand Up @@ -3488,20 +3489,18 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
spin_unlock_irq(&ioc->lock);

blk_mq_unquiesce_queue(q);
blk_mq_unfreeze_queue(q, memflags);

blkg_conf_exit(&ctx);
blkg_conf_exit_frozen(&ctx, memflags);
return nbytes;

einval:
spin_unlock_irq(&ioc->lock);

blk_mq_unquiesce_queue(q);
blk_mq_unfreeze_queue(q, memflags);

ret = -EINVAL;
err:
blkg_conf_exit(&ctx);
blkg_conf_exit_frozen(&ctx, memflags);
return ret;
}

Expand Down
11 changes: 7 additions & 4 deletions block/blk-iolatency.c
Original file line number Diff line number Diff line change
Expand Up @@ -831,16 +831,19 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
struct blkcg_gq *blkg;
struct blkg_conf_ctx ctx;
struct iolatency_grp *iolat;
unsigned long memflags;
char *p, *tok;
u64 lat_val = 0;
u64 oldval;
int ret;
int ret = 0;

blkg_conf_init(&ctx, buf);

ret = blkg_conf_open_bdev(&ctx);
if (ret)
memflags = blkg_conf_open_bdev_frozen(&ctx);
if (IS_ERR_VALUE(memflags)) {
ret = memflags;
goto out;
}

/*
* blk_iolatency_init() may fail after rq_qos_add() succeeds which can
Expand Down Expand Up @@ -890,7 +893,7 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
iolatency_clear_scaling(blkg);
ret = 0;
out:
blkg_conf_exit(&ctx);
blkg_conf_exit_frozen(&ctx, memflags);
return ret ?: nbytes;
}

Expand Down
68 changes: 42 additions & 26 deletions block/blk-mq-debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -608,9 +608,23 @@ static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs[] = {
{},
};

static void debugfs_create_files(struct dentry *parent, void *data,
static void debugfs_create_files(struct request_queue *q, struct dentry *parent,
void *data,
const struct blk_mq_debugfs_attr *attr)
{
lockdep_assert_held(&q->debugfs_mutex);
/*
* Creating new debugfs entries with queue freezed has the risk of
* deadlock.
*/
WARN_ON_ONCE(q->mq_freeze_depth != 0);
/*
* debugfs_mutex should not be nested under other locks that can be
* grabbed while queue is frozen.
*/
lockdep_assert_not_held(&q->elevator_lock);
lockdep_assert_not_held(&q->rq_qos_mutex);

if (IS_ERR_OR_NULL(parent))
return;

Expand All @@ -624,21 +638,14 @@ void blk_mq_debugfs_register(struct request_queue *q)
struct blk_mq_hw_ctx *hctx;
unsigned long i;

debugfs_create_files(q->debugfs_dir, q, blk_mq_debugfs_queue_attrs);
debugfs_create_files(q, q->debugfs_dir, q, blk_mq_debugfs_queue_attrs);

queue_for_each_hw_ctx(q, hctx, i) {
if (!hctx->debugfs_dir)
blk_mq_debugfs_register_hctx(q, hctx);
}

if (q->rq_qos) {
struct rq_qos *rqos = q->rq_qos;

while (rqos) {
blk_mq_debugfs_register_rqos(rqos);
rqos = rqos->next;
}
}
blk_mq_debugfs_register_rq_qos(q);
}

static void blk_mq_debugfs_register_ctx(struct blk_mq_hw_ctx *hctx,
Expand All @@ -650,7 +657,8 @@ static void blk_mq_debugfs_register_ctx(struct blk_mq_hw_ctx *hctx,
snprintf(name, sizeof(name), "cpu%u", ctx->cpu);
ctx_dir = debugfs_create_dir(name, hctx->debugfs_dir);

debugfs_create_files(ctx_dir, ctx, blk_mq_debugfs_ctx_attrs);
debugfs_create_files(hctx->queue, ctx_dir, ctx,
blk_mq_debugfs_ctx_attrs);
}

void blk_mq_debugfs_register_hctx(struct request_queue *q,
Expand All @@ -666,7 +674,8 @@ void blk_mq_debugfs_register_hctx(struct request_queue *q,
snprintf(name, sizeof(name), "hctx%u", hctx->queue_num);
hctx->debugfs_dir = debugfs_create_dir(name, q->debugfs_dir);

debugfs_create_files(hctx->debugfs_dir, hctx, blk_mq_debugfs_hctx_attrs);
debugfs_create_files(q, hctx->debugfs_dir, hctx,
blk_mq_debugfs_hctx_attrs);

hctx_for_each_ctx(hctx, ctx, i)
blk_mq_debugfs_register_ctx(hctx, ctx);
Expand All @@ -686,8 +695,10 @@ void blk_mq_debugfs_register_hctxs(struct request_queue *q)
struct blk_mq_hw_ctx *hctx;
unsigned long i;

mutex_lock(&q->debugfs_mutex);
queue_for_each_hw_ctx(q, hctx, i)
blk_mq_debugfs_register_hctx(q, hctx);
mutex_unlock(&q->debugfs_mutex);
}

void blk_mq_debugfs_unregister_hctxs(struct request_queue *q)
Expand Down Expand Up @@ -717,7 +728,7 @@ void blk_mq_debugfs_register_sched(struct request_queue *q)

q->sched_debugfs_dir = debugfs_create_dir("sched", q->debugfs_dir);

debugfs_create_files(q->sched_debugfs_dir, q, e->queue_debugfs_attrs);
debugfs_create_files(q, q->sched_debugfs_dir, q, e->queue_debugfs_attrs);
}

void blk_mq_debugfs_unregister_sched(struct request_queue *q)
Expand All @@ -741,17 +752,7 @@ static const char *rq_qos_id_to_name(enum rq_qos_id id)
return "unknown";
}

void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos)
{
lockdep_assert_held(&rqos->disk->queue->debugfs_mutex);

if (!rqos->disk->queue->debugfs_dir)
return;
debugfs_remove_recursive(rqos->debugfs_dir);
rqos->debugfs_dir = NULL;
}

void blk_mq_debugfs_register_rqos(struct rq_qos *rqos)
static void blk_mq_debugfs_register_rqos(struct rq_qos *rqos)
{
struct request_queue *q = rqos->disk->queue;
const char *dir_name = rq_qos_id_to_name(rqos->id);
Expand All @@ -766,7 +767,22 @@ void blk_mq_debugfs_register_rqos(struct rq_qos *rqos)
q->debugfs_dir);

rqos->debugfs_dir = debugfs_create_dir(dir_name, q->rqos_debugfs_dir);
debugfs_create_files(rqos->debugfs_dir, rqos, rqos->ops->debugfs_attrs);
debugfs_create_files(q, rqos->debugfs_dir, rqos,
rqos->ops->debugfs_attrs);
}

void blk_mq_debugfs_register_rq_qos(struct request_queue *q)
{
lockdep_assert_held(&q->debugfs_mutex);

if (q->rq_qos) {
struct rq_qos *rqos = q->rq_qos;

while (rqos) {
blk_mq_debugfs_register_rqos(rqos);
rqos = rqos->next;
}
}
}

void blk_mq_debugfs_register_sched_hctx(struct request_queue *q,
Expand All @@ -789,7 +805,7 @@ void blk_mq_debugfs_register_sched_hctx(struct request_queue *q,

hctx->sched_debugfs_dir = debugfs_create_dir("sched",
hctx->debugfs_dir);
debugfs_create_files(hctx->sched_debugfs_dir, hctx,
debugfs_create_files(q, hctx->sched_debugfs_dir, hctx,
e->hctx_debugfs_attrs);
}

Expand Down
8 changes: 2 additions & 6 deletions block/blk-mq-debugfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ void blk_mq_debugfs_register_sched_hctx(struct request_queue *q,
struct blk_mq_hw_ctx *hctx);
void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hctx);

void blk_mq_debugfs_register_rqos(struct rq_qos *rqos);
void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos);
void blk_mq_debugfs_register_rq_qos(struct request_queue *q);
#else
static inline void blk_mq_debugfs_register(struct request_queue *q)
{
Expand Down Expand Up @@ -74,13 +73,10 @@ static inline void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hc
{
}

static inline void blk_mq_debugfs_register_rqos(struct rq_qos *rqos)
static inline void blk_mq_debugfs_register_rq_qos(struct request_queue *q)
{
}

static inline void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos)
{
}
#endif

#if defined(CONFIG_BLK_DEV_ZONED) && defined(CONFIG_BLK_DEBUG_FS)
Expand Down
35 changes: 6 additions & 29 deletions block/blk-rq-qos.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,52 +323,34 @@ void rq_qos_exit(struct request_queue *q)
}

int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id,
const struct rq_qos_ops *ops)
const struct rq_qos_ops *ops)
{
struct request_queue *q = disk->queue;
unsigned int memflags;

WARN_ON_ONCE(q->mq_freeze_depth == 0);
lockdep_assert_held(&q->rq_qos_mutex);

if (rq_qos_id(q, id))
return -EBUSY;

rqos->disk = disk;
rqos->id = id;
rqos->ops = ops;

/*
* No IO can be in-flight when adding rqos, so freeze queue, which
* is fine since we only support rq_qos for blk-mq queue.
*/
memflags = blk_mq_freeze_queue(q);

if (rq_qos_id(q, rqos->id))
goto ebusy;
rqos->next = q->rq_qos;
q->rq_qos = rqos;
blk_queue_flag_set(QUEUE_FLAG_QOS_ENABLED, q);

blk_mq_unfreeze_queue(q, memflags);

if (rqos->ops->debugfs_attrs) {
mutex_lock(&q->debugfs_mutex);
blk_mq_debugfs_register_rqos(rqos);
mutex_unlock(&q->debugfs_mutex);
}

return 0;
ebusy:
blk_mq_unfreeze_queue(q, memflags);
return -EBUSY;
}

void rq_qos_del(struct rq_qos *rqos)
{
struct request_queue *q = rqos->disk->queue;
struct rq_qos **cur;
unsigned int memflags;

WARN_ON_ONCE(q->mq_freeze_depth == 0);
lockdep_assert_held(&q->rq_qos_mutex);

memflags = blk_mq_freeze_queue(q);
for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) {
if (*cur == rqos) {
*cur = rqos->next;
Expand All @@ -377,9 +359,4 @@ void rq_qos_del(struct rq_qos *rqos)
}
if (!q->rq_qos)
blk_queue_flag_clear(QUEUE_FLAG_QOS_ENABLED, q);
blk_mq_unfreeze_queue(q, memflags);

mutex_lock(&q->debugfs_mutex);
blk_mq_debugfs_unregister_rqos(rqos);
mutex_unlock(&q->debugfs_mutex);
}
Loading