aoe: defer rexmit timer downdev work to workqueue
[ Upstream commit cffc873d68ab09a0432b8212008c5613f8a70a2c ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
55dfffc5e9
commit
270d637100
@@ -80,6 +80,7 @@ enum {
|
|||||||
DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */
|
DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */
|
||||||
DEVFL_FREEING = (1<<7), /* set when device is being cleaned up */
|
DEVFL_FREEING = (1<<7), /* set when device is being cleaned up */
|
||||||
DEVFL_FREED = (1<<8), /* device has been cleaned up */
|
DEVFL_FREED = (1<<8), /* device has been cleaned up */
|
||||||
|
DEVFL_DEAD = (1<<9), /* device has timed out of aoe_deadsecs */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@@ -754,7 +754,7 @@ rexmit_timer(struct timer_list *timer)
|
|||||||
|
|
||||||
utgts = count_targets(d, NULL);
|
utgts = count_targets(d, NULL);
|
||||||
|
|
||||||
if (d->flags & DEVFL_TKILL) {
|
if (d->flags & (DEVFL_TKILL | DEVFL_DEAD)) {
|
||||||
spin_unlock_irqrestore(&d->lock, flags);
|
spin_unlock_irqrestore(&d->lock, flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -786,7 +786,8 @@ rexmit_timer(struct timer_list *timer)
|
|||||||
* to clean up.
|
* to clean up.
|
||||||
*/
|
*/
|
||||||
list_splice(&flist, &d->factive[0]);
|
list_splice(&flist, &d->factive[0]);
|
||||||
aoedev_downdev(d);
|
d->flags |= DEVFL_DEAD;
|
||||||
|
queue_work(aoe_wq, &d->work);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -898,6 +899,9 @@ aoecmd_sleepwork(struct work_struct *work)
|
|||||||
{
|
{
|
||||||
struct aoedev *d = container_of(work, struct aoedev, work);
|
struct aoedev *d = container_of(work, struct aoedev, work);
|
||||||
|
|
||||||
|
if (d->flags & DEVFL_DEAD)
|
||||||
|
aoedev_downdev(d);
|
||||||
|
|
||||||
if (d->flags & DEVFL_GDALLOC)
|
if (d->flags & DEVFL_GDALLOC)
|
||||||
aoeblk_gdalloc(d);
|
aoeblk_gdalloc(d);
|
||||||
|
|
||||||
|
@@ -200,8 +200,11 @@ aoedev_downdev(struct aoedev *d)
|
|||||||
struct list_head *head, *pos, *nx;
|
struct list_head *head, *pos, *nx;
|
||||||
struct request *rq, *rqnext;
|
struct request *rq, *rqnext;
|
||||||
int i;
|
int i;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
d->flags &= ~DEVFL_UP;
|
spin_lock_irqsave(&d->lock, flags);
|
||||||
|
d->flags &= ~(DEVFL_UP | DEVFL_DEAD);
|
||||||
|
spin_unlock_irqrestore(&d->lock, flags);
|
||||||
|
|
||||||
/* clean out active and to-be-retransmitted buffers */
|
/* clean out active and to-be-retransmitted buffers */
|
||||||
for (i = 0; i < NFACTIVE; i++) {
|
for (i = 0; i < NFACTIVE; i++) {
|
||||||
|
Reference in New Issue
Block a user