Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

aoe: avoid potential deadlock at set_capacity

Move set_capacity() outside of the section procected by (&d->lock).
To avoid possible interrupt unsafe locking scenario:

CPU0 CPU1
---- ----
[1] lock(&bdev->bd_size_lock);
local_irq_disable();
[2] lock(&d->lock);
[3] lock(&bdev->bd_size_lock);
<Interrupt>
[4] lock(&d->lock);

*** DEADLOCK ***

Where [1](&bdev->bd_size_lock) hold by zram_add()->set_capacity().
[2]lock(&d->lock) hold by aoeblk_gdalloc(). And aoeblk_gdalloc()
is trying to acquire [3](&bdev->bd_size_lock) at set_capacity() call.
In this situation an attempt to acquire [4]lock(&d->lock) from
aoecmd_cfg_rsp() will lead to deadlock.

So the simplest solution is breaking lock dependency
[2](&d->lock) -> [3](&bdev->bd_size_lock) by moving set_capacity()
outside.

Signed-off-by: Maksim Kiselev <bigunclemax@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20240124072436.3745720-2-bigunclemax@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Maksim Kiselev and committed by
Jens Axboe
e169bd4f 13f3956e

+4 -1
+4 -1
drivers/block/aoe/aoeblk.c
··· 333 333 struct gendisk *gd; 334 334 mempool_t *mp; 335 335 struct blk_mq_tag_set *set; 336 + sector_t ssize; 336 337 ulong flags; 337 338 int late = 0; 338 339 int err; ··· 397 396 gd->minors = AOE_PARTITIONS; 398 397 gd->fops = &aoe_bdops; 399 398 gd->private_data = d; 400 - set_capacity(gd, d->ssize); 399 + ssize = d->ssize; 401 400 snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", 402 401 d->aoemajor, d->aoeminor); 403 402 ··· 405 404 d->flags |= DEVFL_UP; 406 405 407 406 spin_unlock_irqrestore(&d->lock, flags); 407 + 408 + set_capacity(gd, ssize); 408 409 409 410 err = device_add_disk(NULL, gd, aoe_attr_groups); 410 411 if (err)