summaryrefslogtreecommitdiff
authorLinus Torvalds <torvalds@linux-foundation.org>2017-08-27 23:25:09 (GMT)
committer Suren Baghdasaryan <surenb@google.com>2019-03-22 21:06:54 (GMT)
commit7394f69af3719d7f51e06aca4a18584dfc4f6f85 (patch)
tree62176c8cfcda6ee790a65e903d1c0e23100742c3
parent49e19db26ad02ad7ba80f7f1c62cec5d21b5740d (diff)
downloadcommon-7394f69af3719d7f51e06aca4a18584dfc4f6f85.zip
common-7394f69af3719d7f51e06aca4a18584dfc4f6f85.tar.gz
common-7394f69af3719d7f51e06aca4a18584dfc4f6f85.tar.bz2
UPSTREAM: Avoid page waitqueue race leaving possible page locker waiting
The "lock_page_killable()" function waits for exclusive access to the page lock bit using the WQ_FLAG_EXCLUSIVE bit in the waitqueue entry set. That means that if it gets woken up, other waiters may have been skipped. That, in turn, means that if it sees the page being unlocked, it *must* take that lock and return success, even if a lethal signal is also pending. So instead of checking for lethal signals first, we need to check for them after we've checked the actual bit that we were waiting for. Even if that might then delay the killing of the process. This matches the order of the old "wait_on_bit_lock()" infrastructure that the page locking used to use (and is still used in a few other areas). Note that if we still return an error after having unsuccessfully tried to acquire the page lock, that is ok: that means that some other thread was able to get ahead of us and lock the page, and when that other thread then unlocks the page, the wakeup event will be repeated. So any other pending waiters will now get properly woken up. Fixes: 62906027091f ("mm: add PageWaiters indicating tasks are waiting for a page bit") Cc: Nick Piggin <npiggin@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mel Gorman <mgorman@techsingularity.net> Cc: Jan Kara <jack@suse.cz> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Andi Kleen <ak@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> (cherry picked from commit a8b169afbf06a678437632709caac98e16f99263) Bug: 120776455 Test: Build succeeds, device boots Signed-off-by: Suren Baghdasaryan <surenb@google.com> Change-Id: I043dc3c37926e549b27ff08b68a601d3f067bbb4
Diffstat
-rw-r--r--mm/filemap.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 854912c..7d78399 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -899,10 +899,6 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
if (likely(test_bit(bit_nr, &page->flags))) {
io_schedule();
- if (unlikely(signal_pending_state(state, current))) {
- ret = -EINTR;
- break;
- }
}
if (lock) {
@@ -912,6 +908,11 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
if (!test_bit(bit_nr, &page->flags))
break;
}
+
+ if (unlikely(signal_pending_state(state, current))) {
+ ret = -EINTR;
+ break;
+ }
}
finish_wait(q, wait);