Skip to content

Commit 1e1a9ce

Browse files
Christoph Hellwigaxboe
Christoph Hellwig
authored andcommitted
block: force noio scope in blk_mq_freeze_queue
When block drivers or the core block code perform allocations with a frozen queue, this could try to recurse into the block device to reclaim memory and deadlock. Thus all allocations done by a process that froze a queue need to be done without __GFP_IO and __GFP_FS. Instead of tying to track all of them down, force a noio scope as part of freezing the queue. Note that nvme is a bit of a mess here due to the non-owner freezes, and they will be addressed separately. Signed-off-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 14ef496 commit 1e1a9ce

26 files changed

+136
-84
lines changed

block/blk-cgroup.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,7 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
15451545
struct request_queue *q = disk->queue;
15461546
struct blkg_policy_data *pd_prealloc = NULL;
15471547
struct blkcg_gq *blkg, *pinned_blkg = NULL;
1548+
unsigned int memflags;
15481549
int ret;
15491550

15501551
if (blkcg_policy_enabled(q, pol))
@@ -1559,7 +1560,7 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
15591560
return -EINVAL;
15601561

15611562
if (queue_is_mq(q))
1562-
blk_mq_freeze_queue(q);
1563+
memflags = blk_mq_freeze_queue(q);
15631564
retry:
15641565
spin_lock_irq(&q->queue_lock);
15651566

@@ -1623,7 +1624,7 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
16231624
spin_unlock_irq(&q->queue_lock);
16241625
out:
16251626
if (queue_is_mq(q))
1626-
blk_mq_unfreeze_queue(q);
1627+
blk_mq_unfreeze_queue(q, memflags);
16271628
if (pinned_blkg)
16281629
blkg_put(pinned_blkg);
16291630
if (pd_prealloc)
@@ -1667,12 +1668,13 @@ void blkcg_deactivate_policy(struct gendisk *disk,
16671668
{
16681669
struct request_queue *q = disk->queue;
16691670
struct blkcg_gq *blkg;
1671+
unsigned int memflags;
16701672

16711673
if (!blkcg_policy_enabled(q, pol))
16721674
return;
16731675

16741676
if (queue_is_mq(q))
1675-
blk_mq_freeze_queue(q);
1677+
memflags = blk_mq_freeze_queue(q);
16761678

16771679
mutex_lock(&q->blkcg_mutex);
16781680
spin_lock_irq(&q->queue_lock);
@@ -1696,7 +1698,7 @@ void blkcg_deactivate_policy(struct gendisk *disk,
16961698
mutex_unlock(&q->blkcg_mutex);
16971699

16981700
if (queue_is_mq(q))
1699-
blk_mq_unfreeze_queue(q);
1701+
blk_mq_unfreeze_queue(q, memflags);
17001702
}
17011703
EXPORT_SYMBOL_GPL(blkcg_deactivate_policy);
17021704

block/blk-iocost.c

+8-6
Original file line numberDiff line numberDiff line change
@@ -3224,6 +3224,7 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
32243224
u32 qos[NR_QOS_PARAMS];
32253225
bool enable, user;
32263226
char *body, *p;
3227+
unsigned int memflags;
32273228
int ret;
32283229

32293230
blkg_conf_init(&ctx, input);
@@ -3247,7 +3248,7 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
32473248
ioc = q_to_ioc(disk->queue);
32483249
}
32493250

3250-
blk_mq_freeze_queue(disk->queue);
3251+
memflags = blk_mq_freeze_queue(disk->queue);
32513252
blk_mq_quiesce_queue(disk->queue);
32523253

32533254
spin_lock_irq(&ioc->lock);
@@ -3347,15 +3348,15 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
33473348
wbt_enable_default(disk);
33483349

33493350
blk_mq_unquiesce_queue(disk->queue);
3350-
blk_mq_unfreeze_queue(disk->queue);
3351+
blk_mq_unfreeze_queue(disk->queue, memflags);
33513352

33523353
blkg_conf_exit(&ctx);
33533354
return nbytes;
33543355
einval:
33553356
spin_unlock_irq(&ioc->lock);
33563357

33573358
blk_mq_unquiesce_queue(disk->queue);
3358-
blk_mq_unfreeze_queue(disk->queue);
3359+
blk_mq_unfreeze_queue(disk->queue, memflags);
33593360

33603361
ret = -EINVAL;
33613362
err:
@@ -3414,6 +3415,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
34143415
{
34153416
struct blkg_conf_ctx ctx;
34163417
struct request_queue *q;
3418+
unsigned int memflags;
34173419
struct ioc *ioc;
34183420
u64 u[NR_I_LCOEFS];
34193421
bool user;
@@ -3441,7 +3443,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
34413443
ioc = q_to_ioc(q);
34423444
}
34433445

3444-
blk_mq_freeze_queue(q);
3446+
memflags = blk_mq_freeze_queue(q);
34453447
blk_mq_quiesce_queue(q);
34463448

34473449
spin_lock_irq(&ioc->lock);
@@ -3493,7 +3495,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
34933495
spin_unlock_irq(&ioc->lock);
34943496

34953497
blk_mq_unquiesce_queue(q);
3496-
blk_mq_unfreeze_queue(q);
3498+
blk_mq_unfreeze_queue(q, memflags);
34973499

34983500
blkg_conf_exit(&ctx);
34993501
return nbytes;
@@ -3502,7 +3504,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
35023504
spin_unlock_irq(&ioc->lock);
35033505

35043506
blk_mq_unquiesce_queue(q);
3505-
blk_mq_unfreeze_queue(q);
3507+
blk_mq_unfreeze_queue(q, memflags);
35063508

35073509
ret = -EINVAL;
35083510
err:

block/blk-iolatency.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -749,9 +749,11 @@ static void blkiolatency_enable_work_fn(struct work_struct *work)
749749
*/
750750
enabled = atomic_read(&blkiolat->enable_cnt);
751751
if (enabled != blkiolat->enabled) {
752-
blk_mq_freeze_queue(blkiolat->rqos.disk->queue);
752+
unsigned int memflags;
753+
754+
memflags = blk_mq_freeze_queue(blkiolat->rqos.disk->queue);
753755
blkiolat->enabled = enabled;
754-
blk_mq_unfreeze_queue(blkiolat->rqos.disk->queue);
756+
blk_mq_unfreeze_queue(blkiolat->rqos.disk->queue, memflags);
755757
}
756758
}
757759

block/blk-mq.c

+13-8
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,12 @@ int blk_mq_freeze_queue_wait_timeout(struct request_queue *q,
210210
}
211211
EXPORT_SYMBOL_GPL(blk_mq_freeze_queue_wait_timeout);
212212

213-
void blk_mq_freeze_queue(struct request_queue *q)
213+
void blk_mq_freeze_queue_nomemsave(struct request_queue *q)
214214
{
215215
blk_freeze_queue_start(q);
216216
blk_mq_freeze_queue_wait(q);
217217
}
218-
EXPORT_SYMBOL_GPL(blk_mq_freeze_queue);
218+
EXPORT_SYMBOL_GPL(blk_mq_freeze_queue_nomemsave);
219219

220220
bool __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic)
221221
{
@@ -236,12 +236,12 @@ bool __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic)
236236
return unfreeze;
237237
}
238238

239-
void blk_mq_unfreeze_queue(struct request_queue *q)
239+
void blk_mq_unfreeze_queue_nomemrestore(struct request_queue *q)
240240
{
241241
if (__blk_mq_unfreeze_queue(q, false))
242242
blk_unfreeze_release_lock(q);
243243
}
244-
EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue);
244+
EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue_nomemrestore);
245245

246246
/*
247247
* non_owner variant of blk_freeze_queue_start
@@ -4223,13 +4223,14 @@ static void blk_mq_update_tag_set_shared(struct blk_mq_tag_set *set,
42234223
bool shared)
42244224
{
42254225
struct request_queue *q;
4226+
unsigned int memflags;
42264227

42274228
lockdep_assert_held(&set->tag_list_lock);
42284229

42294230
list_for_each_entry(q, &set->tag_list, tag_set_list) {
4230-
blk_mq_freeze_queue(q);
4231+
memflags = blk_mq_freeze_queue(q);
42314232
queue_set_hctx_shared(q, shared);
4232-
blk_mq_unfreeze_queue(q);
4233+
blk_mq_unfreeze_queue(q, memflags);
42334234
}
42344235
}
42354236

@@ -4992,6 +4993,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
49924993
struct request_queue *q;
49934994
LIST_HEAD(head);
49944995
int prev_nr_hw_queues = set->nr_hw_queues;
4996+
unsigned int memflags;
49954997
int i;
49964998

49974999
lockdep_assert_held(&set->tag_list_lock);
@@ -5003,8 +5005,10 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
50035005
if (set->nr_maps == 1 && nr_hw_queues == set->nr_hw_queues)
50045006
return;
50055007

5008+
memflags = memalloc_noio_save();
50065009
list_for_each_entry(q, &set->tag_list, tag_set_list)
5007-
blk_mq_freeze_queue(q);
5010+
blk_mq_freeze_queue_nomemsave(q);
5011+
50085012
/*
50095013
* Switch IO scheduler to 'none', cleaning up the data associated
50105014
* with the previous scheduler. We will switch back once we are done
@@ -5052,7 +5056,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
50525056
blk_mq_elv_switch_back(&head, q);
50535057

50545058
list_for_each_entry(q, &set->tag_list, tag_set_list)
5055-
blk_mq_unfreeze_queue(q);
5059+
blk_mq_unfreeze_queue_nomemrestore(q);
5060+
memalloc_noio_restore(memflags);
50565061

50575062
/* Free the excess tags when nr_hw_queues shrink. */
50585063
for (i = set->nr_hw_queues; i < prev_nr_hw_queues; i++)

block/blk-pm.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ int blk_pre_runtime_suspend(struct request_queue *q)
8989
if (percpu_ref_is_zero(&q->q_usage_counter))
9090
ret = 0;
9191
/* Switch q_usage_counter back to per-cpu mode. */
92-
blk_mq_unfreeze_queue(q);
92+
blk_mq_unfreeze_queue_nomemrestore(q);
9393

9494
if (ret < 0) {
9595
spin_lock_irq(&q->queue_lock);

block/blk-rq-qos.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id,
299299
const struct rq_qos_ops *ops)
300300
{
301301
struct request_queue *q = disk->queue;
302+
unsigned int memflags;
302303

303304
lockdep_assert_held(&q->rq_qos_mutex);
304305

@@ -310,14 +311,14 @@ int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id,
310311
* No IO can be in-flight when adding rqos, so freeze queue, which
311312
* is fine since we only support rq_qos for blk-mq queue.
312313
*/
313-
blk_mq_freeze_queue(q);
314+
memflags = blk_mq_freeze_queue(q);
314315

315316
if (rq_qos_id(q, rqos->id))
316317
goto ebusy;
317318
rqos->next = q->rq_qos;
318319
q->rq_qos = rqos;
319320

320-
blk_mq_unfreeze_queue(q);
321+
blk_mq_unfreeze_queue(q, memflags);
321322

322323
if (rqos->ops->debugfs_attrs) {
323324
mutex_lock(&q->debugfs_mutex);
@@ -327,25 +328,26 @@ int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id,
327328

328329
return 0;
329330
ebusy:
330-
blk_mq_unfreeze_queue(q);
331+
blk_mq_unfreeze_queue(q, memflags);
331332
return -EBUSY;
332333
}
333334

334335
void rq_qos_del(struct rq_qos *rqos)
335336
{
336337
struct request_queue *q = rqos->disk->queue;
337338
struct rq_qos **cur;
339+
unsigned int memflags;
338340

339341
lockdep_assert_held(&q->rq_qos_mutex);
340342

341-
blk_mq_freeze_queue(q);
343+
memflags = blk_mq_freeze_queue(q);
342344
for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) {
343345
if (*cur == rqos) {
344346
*cur = rqos->next;
345347
break;
346348
}
347349
}
348-
blk_mq_unfreeze_queue(q);
350+
blk_mq_unfreeze_queue(q, memflags);
349351

350352
mutex_lock(&q->debugfs_mutex);
351353
blk_mq_debugfs_unregister_rqos(rqos);

block/blk-settings.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -461,11 +461,12 @@ EXPORT_SYMBOL_GPL(queue_limits_commit_update);
461461
int queue_limits_commit_update_frozen(struct request_queue *q,
462462
struct queue_limits *lim)
463463
{
464+
unsigned int memflags;
464465
int ret;
465466

466-
blk_mq_freeze_queue(q);
467+
memflags = blk_mq_freeze_queue(q);
467468
ret = queue_limits_commit_update(q, lim);
468-
blk_mq_unfreeze_queue(q);
469+
blk_mq_unfreeze_queue(q, memflags);
469470

470471
return ret;
471472
}

block/blk-sysfs.c

+3-5
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
681681
struct queue_sysfs_entry *entry = to_queue(attr);
682682
struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
683683
struct request_queue *q = disk->queue;
684-
unsigned int noio_flag;
684+
unsigned int memflags;
685685
ssize_t res;
686686

687687
if (!entry->store_limit && !entry->store)
@@ -711,11 +711,9 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
711711
}
712712

713713
mutex_lock(&q->sysfs_lock);
714-
blk_mq_freeze_queue(q);
715-
noio_flag = memalloc_noio_save();
714+
memflags = blk_mq_freeze_queue(q);
716715
res = entry->store(disk, page, length);
717-
memalloc_noio_restore(noio_flag);
718-
blk_mq_unfreeze_queue(q);
716+
blk_mq_unfreeze_queue(q, memflags);
719717
mutex_unlock(&q->sysfs_lock);
720718
return res;
721719
}

block/blk-throttle.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,7 @@ static int blk_throtl_init(struct gendisk *disk)
12021202
{
12031203
struct request_queue *q = disk->queue;
12041204
struct throtl_data *td;
1205+
unsigned int memflags;
12051206
int ret;
12061207

12071208
td = kzalloc_node(sizeof(*td), GFP_KERNEL, q->node);
@@ -1215,7 +1216,7 @@ static int blk_throtl_init(struct gendisk *disk)
12151216
* Freeze queue before activating policy, to synchronize with IO path,
12161217
* which is protected by 'q_usage_counter'.
12171218
*/
1218-
blk_mq_freeze_queue(disk->queue);
1219+
memflags = blk_mq_freeze_queue(disk->queue);
12191220
blk_mq_quiesce_queue(disk->queue);
12201221

12211222
q->td = td;
@@ -1239,7 +1240,7 @@ static int blk_throtl_init(struct gendisk *disk)
12391240

12401241
out:
12411242
blk_mq_unquiesce_queue(disk->queue);
1242-
blk_mq_unfreeze_queue(disk->queue);
1243+
blk_mq_unfreeze_queue(disk->queue, memflags);
12431244

12441245
return ret;
12451246
}

block/blk-zoned.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -1717,9 +1717,10 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
17171717
else
17181718
pr_warn("%s: failed to revalidate zones\n", disk->disk_name);
17191719
if (ret) {
1720-
blk_mq_freeze_queue(q);
1720+
unsigned int memflags = blk_mq_freeze_queue(q);
1721+
17211722
disk_free_zone_resources(disk);
1722-
blk_mq_unfreeze_queue(q);
1723+
blk_mq_unfreeze_queue(q, memflags);
17231724
}
17241725

17251726
return ret;

0 commit comments

Comments
 (0)