* the rbio from the hash_table, and drop
* the corresponding ref
*/
- if (bio_list_empty(&rbio->bio_list)) {
+ /*
+ * An rbio with no bios is idle only if nothing is plugged on
+ * it either. unlock_stripe() caches the rbio before it retakes
+ * the locks, with RBIO_RMW_LOCKED_BIT still set, so a
+ * lock_stripe_add() in that window can neither steal the pages
+ * nor merge and plugs onto the cached rbio instead. That rbio
+ * is still the stripe's lock owner and unlock_stripe() hands
+ * the lock on to the plugged one; only the cache's reference
+ * goes away here.
+ */
+ if (bio_list_empty(&rbio->bio_list) &&
+ list_empty(&rbio->plug_list)) {
if (!list_empty(&rbio->hash_list)) {
list_del_init(&rbio->hash_list);
refcount_dec(&rbio->refs);
- BUG_ON(!list_empty(&rbio->plug_list));
}
}
}