Я предполагаю, что обработчик прерываний на диске будет активен (& bh-> b_wait), что может привести к пропущенному пробуждению, если прерывания не были отключены в процессе, ожидающем этот блок.
Помните, что условные переменные (sleep_on, wakeup) не имеют памяти: sleep_on будет приостанавливаться до вызова wakeup; не имеет значения, вызывается ли wakeup непосредственно перед sleep_on.
С момента тестирования bh-> b_lock вызывающая сторона работает с обработчиком прерываний; таким образом cli (или, более типично unix splbio ()) блокирует обработчик прерываний, предотвращая гонку.
Так как ядро сохраняет состояние прерывания (маска, приоритет, ...) с состоянием процесса, когда sleep_on вызывает перепланирование, наиболее вероятно, что прерывания будут повторно разрешены; или хотя бы со временем будет. Прерывание диска будет в конечном счете выполнено, пробуждая этот процесс.
Когда этот процесс перепланирован, его сохраненное состояние прерывания (отключено) будет восстановлено, так что проверка и назначение b_lock также предотвратят помехи от обработчик прерываний диска.