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

aoe: defer rexmit timer downdev work to workqueue

When aoe's rexmit_timer() notices that an aoe target fails to respond to
commands for more than aoe_deadsecs, it calls aoedev_downdev() which
cleans the outstanding aoe and block queues. This can involve sleeping,
such as in blk_mq_freeze_queue(), which should not occur in irq context.

This patch defers that aoedev_downdev() call to the aoe device's
workqueue.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=212665
Signed-off-by: Justin Sanders <jsanders.devel@gmail.com>
Link: https://lore.kernel.org/r/20250610170600.869-2-jsanders.devel@gmail.com
Tested-By: Valentin Kleibel <valentin@vrvis.at>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Justin Sanders and committed by
Jens Axboe
cffc873d 7f90d45e

+11 -3
+1
drivers/block/aoe/aoe.h
··· 80 80 DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ 81 81 DEVFL_FREEING = (1<<7), /* set when device is being cleaned up */ 82 82 DEVFL_FREED = (1<<8), /* device has been cleaned up */ 83 + DEVFL_DEAD = (1<<9), /* device has timed out of aoe_deadsecs */ 83 84 }; 84 85 85 86 enum {
+6 -2
drivers/block/aoe/aoecmd.c
··· 754 754 755 755 utgts = count_targets(d, NULL); 756 756 757 - if (d->flags & DEVFL_TKILL) { 757 + if (d->flags & (DEVFL_TKILL | DEVFL_DEAD)) { 758 758 spin_unlock_irqrestore(&d->lock, flags); 759 759 return; 760 760 } ··· 786 786 * to clean up. 787 787 */ 788 788 list_splice(&flist, &d->factive[0]); 789 - aoedev_downdev(d); 789 + d->flags |= DEVFL_DEAD; 790 + queue_work(aoe_wq, &d->work); 790 791 goto out; 791 792 } 792 793 ··· 898 897 aoecmd_sleepwork(struct work_struct *work) 899 898 { 900 899 struct aoedev *d = container_of(work, struct aoedev, work); 900 + 901 + if (d->flags & DEVFL_DEAD) 902 + aoedev_downdev(d); 901 903 902 904 if (d->flags & DEVFL_GDALLOC) 903 905 aoeblk_gdalloc(d);
+4 -1
drivers/block/aoe/aoedev.c
··· 200 200 struct list_head *head, *pos, *nx; 201 201 struct request *rq, *rqnext; 202 202 int i; 203 + unsigned long flags; 203 204 204 - d->flags &= ~DEVFL_UP; 205 + spin_lock_irqsave(&d->lock, flags); 206 + d->flags &= ~(DEVFL_UP | DEVFL_DEAD); 207 + spin_unlock_irqrestore(&d->lock, flags); 205 208 206 209 /* clean out active and to-be-retransmitted buffers */ 207 210 for (i = 0; i < NFACTIVE; i++) {