summaryrefslogtreecommitdiff
path: root/kernel/watch_queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/watch_queue.c')
-rw-r--r--kernel/watch_queue.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c
index 538520861e8b..932a88ac1f39 100644
--- a/kernel/watch_queue.c
+++ b/kernel/watch_queue.c
@@ -101,7 +101,7 @@ static bool post_one_notification(struct watch_queue *wqueue,
struct pipe_inode_info *pipe = wqueue->pipe;
struct pipe_buffer *buf;
struct page *page;
- unsigned int head, tail, note, offset, len;
+ unsigned int head, tail, note, offset, len, nr_notes;
bool done = false;
spin_lock_irq(&pipe->rd_wait.lock);
@@ -111,8 +111,10 @@ static bool post_one_notification(struct watch_queue *wqueue,
if (pipe_full(head, tail, pipe->ring_size))
goto lost;
- note = find_first_bit(wqueue->notes_bitmap, wqueue->nr_notes);
- if (note >= wqueue->nr_notes)
+ /* Pairs with the smp_store_release() in watch_queue_set_size(). */
+ nr_notes = smp_load_acquire(&wqueue->nr_notes);
+ note = find_first_bit(wqueue->notes_bitmap, nr_notes);
+ if (note >= nr_notes)
goto lost;
page = wqueue->notes[note / WATCH_QUEUE_NOTES_PER_PAGE];
@@ -297,7 +299,8 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)
wqueue->notes = pages;
wqueue->notes_bitmap = bitmap;
wqueue->nr_pages = nr_pages;
- wqueue->nr_notes = nr_notes;
+ /* Pairs with the smp_load_acquire() in post_one_notification(). */
+ smp_store_release(&wqueue->nr_notes, nr_notes);
return 0;
error_p: