Skip to content

Commit 11167b2

Browse files
committed
Merge tag 'block-6.13-20241220' of git://git.kernel.dk/linux
Pull block fixes from Jens Axboe: - Minor cleanups for bdev/nvme using the helpers introduced - Revert of a deadlock fix that still needs more work - Fix a UAF of hctx in the cpu hotplug code * tag 'block-6.13-20241220' of git://git.kernel.dk/linux: block: avoid to reuse `hctx` not removed from cpuhp callback list block: Revert "block: Fix potential deadlock while freezing queue and acquiring sysfs_lock" nvme: use blk_validate_block_size() for max LBA check block/bdev: use helper for max block size check
2 parents 7c05bd9 + 85672ca commit 11167b2

File tree

5 files changed

+35
-30
lines changed

5 files changed

+35
-30
lines changed

block/bdev.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,7 @@ int set_blocksize(struct file *file, int size)
155155
struct inode *inode = file->f_mapping->host;
156156
struct block_device *bdev = I_BDEV(inode);
157157

158-
/* Size must be a power of two, and between 512 and PAGE_SIZE */
159-
if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size))
158+
if (blk_validate_block_size(size))
160159
return -EINVAL;
161160

162161
/* Size cannot be smaller than the size supported by the device */

block/blk-mq-sysfs.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,15 @@ void blk_mq_sysfs_unregister_hctxs(struct request_queue *q)
275275
struct blk_mq_hw_ctx *hctx;
276276
unsigned long i;
277277

278-
lockdep_assert_held(&q->sysfs_dir_lock);
279-
278+
mutex_lock(&q->sysfs_dir_lock);
280279
if (!q->mq_sysfs_init_done)
281-
return;
280+
goto unlock;
282281

283282
queue_for_each_hw_ctx(q, hctx, i)
284283
blk_mq_unregister_hctx(hctx);
284+
285+
unlock:
286+
mutex_unlock(&q->sysfs_dir_lock);
285287
}
286288

287289
int blk_mq_sysfs_register_hctxs(struct request_queue *q)
@@ -290,16 +292,18 @@ int blk_mq_sysfs_register_hctxs(struct request_queue *q)
290292
unsigned long i;
291293
int ret = 0;
292294

293-
lockdep_assert_held(&q->sysfs_dir_lock);
294-
295+
mutex_lock(&q->sysfs_dir_lock);
295296
if (!q->mq_sysfs_init_done)
296-
return ret;
297+
goto unlock;
297298

298299
queue_for_each_hw_ctx(q, hctx, i) {
299300
ret = blk_mq_register_hctx(hctx);
300301
if (ret)
301302
break;
302303
}
303304

305+
unlock:
306+
mutex_unlock(&q->sysfs_dir_lock);
307+
304308
return ret;
305309
}

block/blk-mq.c

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4412,6 +4412,15 @@ struct gendisk *blk_mq_alloc_disk_for_queue(struct request_queue *q,
44124412
}
44134413
EXPORT_SYMBOL(blk_mq_alloc_disk_for_queue);
44144414

4415+
/*
4416+
* Only hctx removed from cpuhp list can be reused
4417+
*/
4418+
static bool blk_mq_hctx_is_reusable(struct blk_mq_hw_ctx *hctx)
4419+
{
4420+
return hlist_unhashed(&hctx->cpuhp_online) &&
4421+
hlist_unhashed(&hctx->cpuhp_dead);
4422+
}
4423+
44154424
static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx(
44164425
struct blk_mq_tag_set *set, struct request_queue *q,
44174426
int hctx_idx, int node)
@@ -4421,7 +4430,7 @@ static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx(
44214430
/* reuse dead hctx first */
44224431
spin_lock(&q->unused_hctx_lock);
44234432
list_for_each_entry(tmp, &q->unused_hctx_list, hctx_list) {
4424-
if (tmp->numa_node == node) {
4433+
if (tmp->numa_node == node && blk_mq_hctx_is_reusable(tmp)) {
44254434
hctx = tmp;
44264435
break;
44274436
}
@@ -4453,8 +4462,7 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
44534462
unsigned long i, j;
44544463

44554464
/* protect against switching io scheduler */
4456-
lockdep_assert_held(&q->sysfs_lock);
4457-
4465+
mutex_lock(&q->sysfs_lock);
44584466
for (i = 0; i < set->nr_hw_queues; i++) {
44594467
int old_node;
44604468
int node = blk_mq_get_hctx_node(set, i);
@@ -4487,6 +4495,7 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
44874495

44884496
xa_for_each_start(&q->hctx_table, j, hctx, j)
44894497
blk_mq_exit_hctx(q, set, hctx, j);
4498+
mutex_unlock(&q->sysfs_lock);
44904499

44914500
/* unregister cpuhp callbacks for exited hctxs */
44924501
blk_mq_remove_hw_queues_cpuhp(q);
@@ -4518,14 +4527,10 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
45184527

45194528
xa_init(&q->hctx_table);
45204529

4521-
mutex_lock(&q->sysfs_lock);
4522-
45234530
blk_mq_realloc_hw_ctxs(set, q);
45244531
if (!q->nr_hw_queues)
45254532
goto err_hctxs;
45264533

4527-
mutex_unlock(&q->sysfs_lock);
4528-
45294534
INIT_WORK(&q->timeout_work, blk_mq_timeout_work);
45304535
blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ);
45314536

@@ -4544,7 +4549,6 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
45444549
return 0;
45454550

45464551
err_hctxs:
4547-
mutex_unlock(&q->sysfs_lock);
45484552
blk_mq_release(q);
45494553
err_exit:
45504554
q->mq_ops = NULL;
@@ -4925,12 +4929,12 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
49254929
return false;
49264930

49274931
/* q->elevator needs protection from ->sysfs_lock */
4928-
lockdep_assert_held(&q->sysfs_lock);
4932+
mutex_lock(&q->sysfs_lock);
49294933

49304934
/* the check has to be done with holding sysfs_lock */
49314935
if (!q->elevator) {
49324936
kfree(qe);
4933-
goto out;
4937+
goto unlock;
49344938
}
49354939

49364940
INIT_LIST_HEAD(&qe->node);
@@ -4940,7 +4944,9 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
49404944
__elevator_get(qe->type);
49414945
list_add(&qe->node, head);
49424946
elevator_disable(q);
4943-
out:
4947+
unlock:
4948+
mutex_unlock(&q->sysfs_lock);
4949+
49444950
return true;
49454951
}
49464952

@@ -4969,9 +4975,11 @@ static void blk_mq_elv_switch_back(struct list_head *head,
49694975
list_del(&qe->node);
49704976
kfree(qe);
49714977

4978+
mutex_lock(&q->sysfs_lock);
49724979
elevator_switch(q, t);
49734980
/* drop the reference acquired in blk_mq_elv_switch_none */
49744981
elevator_put(t);
4982+
mutex_unlock(&q->sysfs_lock);
49754983
}
49764984

49774985
static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
@@ -4991,11 +4999,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
49914999
if (set->nr_maps == 1 && nr_hw_queues == set->nr_hw_queues)
49925000
return;
49935001

4994-
list_for_each_entry(q, &set->tag_list, tag_set_list) {
4995-
mutex_lock(&q->sysfs_dir_lock);
4996-
mutex_lock(&q->sysfs_lock);
5002+
list_for_each_entry(q, &set->tag_list, tag_set_list)
49975003
blk_mq_freeze_queue(q);
4998-
}
49995004
/*
50005005
* Switch IO scheduler to 'none', cleaning up the data associated
50015006
* with the previous scheduler. We will switch back once we are done
@@ -5051,11 +5056,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
50515056
list_for_each_entry(q, &set->tag_list, tag_set_list)
50525057
blk_mq_elv_switch_back(&head, q);
50535058

5054-
list_for_each_entry(q, &set->tag_list, tag_set_list) {
5059+
list_for_each_entry(q, &set->tag_list, tag_set_list)
50555060
blk_mq_unfreeze_queue(q);
5056-
mutex_unlock(&q->sysfs_lock);
5057-
mutex_unlock(&q->sysfs_dir_lock);
5058-
}
50595061

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

block/blk-sysfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -706,11 +706,11 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
706706
if (entry->load_module)
707707
entry->load_module(disk, page, length);
708708

709-
mutex_lock(&q->sysfs_lock);
710709
blk_mq_freeze_queue(q);
710+
mutex_lock(&q->sysfs_lock);
711711
res = entry->store(disk, page, length);
712-
blk_mq_unfreeze_queue(q);
713712
mutex_unlock(&q->sysfs_lock);
713+
blk_mq_unfreeze_queue(q);
714714
return res;
715715
}
716716

drivers/nvme/host/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2034,7 +2034,7 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id,
20342034
* or smaller than a sector size yet, so catch this early and don't
20352035
* allow block I/O.
20362036
*/
2037-
if (head->lba_shift > PAGE_SHIFT || head->lba_shift < SECTOR_SHIFT) {
2037+
if (blk_validate_block_size(bs)) {
20382038
bs = (1 << 9);
20392039
valid = false;
20402040
}

0 commit comments

Comments
 (0)