History

watch_queue: Fix lack of barrier/sync/lock between post and read

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.

David Howells committed 4 years ago

Commit 2ed147f1 parent 7ea1a012 files · +3 −2Browse files

Showing the changes to kernel (1 of 2 files). Show all

Unified · Split

kernel/watch_queue.c+1−1
@@ -113,7 +113,7 @@ static bool post_one_notification(struct watch_queue *wqueue, · 112 unmodified lines
113113 buf->offset = offset;
114114 buf->len = len;
115115 buf->flags = PIPE_BUF_FLAG_WHOLE;
116− pipe->head = head + 1;
116+ smp_store_release(&pipe->head, head + 1); /* vs pipe_read() */
117117
118118 if (!test_and_clear_bit(note, wqueue->notes_bitmap)) {
119119 spin_unlock_irq(&pipe->rd_wait.lock);