Skip to content

Commit ab96bba

Browse files
jognessaxboe
authored andcommittedJul 16, 2020
block: remove retry loop in ioc_release_fn()
The reverse-order double lock dance in ioc_release_fn() is using a retry loop. This is a problem on PREEMPT_RT because it could preempt the task that would release q->queue_lock and thus live lock in the retry loop. RCU is already managing the freeing of the request queue and icq. If the trylock fails, use RCU to guarantee that the request queue and icq are not freed and re-acquire the locks in the correct order, allowing forward progress. Signed-off-by: John Ogness <[email protected]> Reviewed-by: Daniel Wagner <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent a43f085 commit ab96bba

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed
 

‎block/blk-ioc.c

+17-3
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,23 @@ static void ioc_release_fn(struct work_struct *work)
107107
ioc_destroy_icq(icq);
108108
spin_unlock(&q->queue_lock);
109109
} else {
110-
spin_unlock_irq(&ioc->lock);
111-
cpu_relax();
112-
spin_lock_irq(&ioc->lock);
110+
/* Make sure q and icq cannot be freed. */
111+
rcu_read_lock();
112+
113+
/* Re-acquire the locks in the correct order. */
114+
spin_unlock(&ioc->lock);
115+
spin_lock(&q->queue_lock);
116+
spin_lock(&ioc->lock);
117+
118+
/*
119+
* The icq may have been destroyed when the ioc lock
120+
* was released.
121+
*/
122+
if (!(icq->flags & ICQ_DESTROYED))
123+
ioc_destroy_icq(icq);
124+
125+
spin_unlock(&q->queue_lock);
126+
rcu_read_unlock();
113127
}
114128
}
115129

0 commit comments

Comments
 (0)
Please sign in to comment.