--- a/sys/vfs/fuse/fuse_vnops.c +++ b/sys/vfs/fuse/fuse_vnops.c @@ -2011,8 +2011,22 @@ struct bio *bio; while (fmp->dead == 0) { - tsleep(&fmp->helper_td, 0, "fuse_wio", 0); + /* + * DF-3029: interlocked sleep so a wakeup() from + * fuse_vop_strategy() between the queue-empty check and + * tsleep() cannot be lost (a lost wakeup strands the bio + * and blocks its waiter forever). + */ + tsleep_interlock(&fmp->helper_td, 0); spin_lock(&fmp->helper_spin); + if (TAILQ_FIRST(&fmp->bioq) == NULL) { + spin_unlock(&fmp->helper_spin); + if (fmp->dead) + break; + tsleep(&fmp->helper_td, PINTERLOCKED, + "fuse_wio", 0); + continue; + } while ((bio = TAILQ_FIRST(&fmp->bioq)) != NULL) { TAILQ_REMOVE(&fmp->bioq, bio, bio_act); spin_unlock(&fmp->helper_spin);