There's nothing to synchronise post_one_notification() versus pipe_read(). Whilst posting is done under pipe->rd_wait.lock, the reader only takes pipe->mutex which cannot bar notification posting as that may need to be made from contexts that cannot sleep. Fix this by setting pipe->head with a barrier in post_one_notification() and reading pipe->head with a barrier in pipe_read(). If that's not sufficient, the rd_wait.lock will need to be taken, possibly in a ->confirm() op so that it only applies to notifications. The lock would, however, have to be dropped before copy_page_to_iter() is invoked.
Showing the changes to kernel (1 of 2 files). Show all
Unified · Split
| @@ -113,7 +113,7 @@ static bool post_one_notification(struct watch_queue *wqueue, · 112 unmodified lines | ||
| 113 | 113 | buf->offset = offset; |
| 114 | 114 | buf->len = len; |
| 115 | 115 | buf->flags = PIPE_BUF_FLAG_WHOLE; |
| 116 | − pipe->head = head + 1; | |
| 116 | + smp_store_release(&pipe->head, head + 1); /* vs pipe_read() */ | |
| 117 | 117 | |
| 118 | 118 | if (!test_and_clear_bit(note, wqueue->notes_bitmap)) { |
| 119 | 119 | spin_unlock_irq(&pipe->rd_wait.lock); |