All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: + lock_page_killable-avoid-lost-wakeups.patch added to -mm tree
@ 2009-01-17 21:51 Oleg Nesterov
  2009-01-18  1:38   ` Johannes Weiner
  0 siblings, 1 reply; 56+ messages in thread
From: Oleg Nesterov @ 2009-01-17 21:51 UTC (permalink / raw)
  To: Chris Mason
  Cc: Peter Zijlstra, Matthew Wilcox, Chuck Lever, Nick Piggin,
	Andrew Morton, linux-kernel

I think the patch is correct, just a question,

>  int __lock_page_killable(struct page *page)
>  {
>  	DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
> +	int ret;
>
> -	return __wait_on_bit_lock(page_waitqueue(page), &wait,
> +	ret = __wait_on_bit_lock(page_waitqueue(page), &wait,
>  					sync_page_killable, TASK_KILLABLE);
> +	/*
> +	 * wait_on_bit_lock uses prepare_to_wait_exclusive, so if multiple
> +	 * procs were waiting on this page, we were the only proc woken up.
> +	 *
> +	 * if ret != 0, we didn't actually get the lock.  We need to
> +	 * make sure any other waiters don't sleep forever.
> +	 */
> +	if (ret)
> +		wake_up_page(page, PG_locked);

This patch assumes that nobody else calls __wait_on_bit_lock() with
action which can return !0. Currently this is correct, but perhaps
it makes sense to move this wake_up_page() into __wait_on_bit_lock ?

Note that we need to "transfer" the wakeup only if wake_up_page()
has already removed us from page_waitqueue(page), this means we
don't need to check ret != 0 twice in __wait_on_bit_lock(), afaics
we can do

	if ((ret = (*action)(q->key.flags))) {
		__wake_up_bit(wq, q->key.flags, q->key.bit_nr);
		// or just __wake_up(wq, TASK_NORMAL, 1, &q->key);
		break;
	}

IOW, imho __wait_on_bit_lock() is buggy, not __lock_page_killable(),
no?

Oleg.


^ permalink raw reply	[flat|nested] 56+ messages in thread
* + lock_page_killable-avoid-lost-wakeups.patch added to -mm tree
@ 2009-01-16 22:44 akpm
  0 siblings, 0 replies; 56+ messages in thread
From: akpm @ 2009-01-16 22:44 UTC (permalink / raw)
  To: mm-commits; +Cc: chris.mason, a.p.zijlstra, cel, matthew, nickpiggin, stable


The patch titled
     lock_page_killable(): avoid lost wakeups
has been added to the -mm tree.  Its filename is
     lock_page_killable-avoid-lost-wakeups.patch

Before you just go and hit "reply", please:
   a) Consider who else should be cc'ed
   b) Prefer to cc a suitable mailing list as well
   c) Ideally: find the original patch on the mailing list and do a
      reply-to-all to that, adding suitable additional cc's

*** Remember to use Documentation/SubmitChecklist when testing your code ***

See http://userweb.kernel.org/~akpm/stuff/added-to-mm.txt to find
out what to do about this

The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/

------------------------------------------------------
Subject: lock_page_killable(): avoid lost wakeups
From: Chris Mason <chris.mason@oracle.com>

lock_page and lock_page_killable both call __wait_on_bit_lock, and both
end up using prepare_to_wait_exclusive().  This means that when someone
does finally unlock the page, only one process is going to get woken up.

But lock_page_killable can exit without taking the lock.  If nobody else
comes in and locks the page, any other waiters will wait forever.

For example, procA holding the page lock, procB and procC are waiting on
the lock.

procA: lock_page() // success
procB: lock_page_killable(), sync_page_killable(), io_schedule()
procC: lock_page_killable(), sync_page_killable(), io_schedule()

procA: unlock, wake_up_page(page, PG_locked)
procA: wake up procB

happy admin: kill procB

procB: wakes into sync_page_killable(), notices the signal and returns
-EINTR

procB: __wait_on_bit_lock sees the action() func returns < 0 and does
not take the page lock

procB: lock_page_killable() returns < 0 and exits happily.

procC: sleeping in io_schedule() forever unless someone else locks the
page.

This was seen in production on systems where the database was shutting
down.  Testing shows the patch fixes things.

Chuck Lever did all the hard work here, with a page lock debugging
patch that proved we were missing a wakeup.

Every version of lock_page_killable() should need this.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Matthew Wilcox <matthew@wil.cx>
Cc: Chuck Lever <cel@citi.umich.edu>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 mm/filemap.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff -puN mm/filemap.c~lock_page_killable-avoid-lost-wakeups mm/filemap.c
--- a/mm/filemap.c~lock_page_killable-avoid-lost-wakeups
+++ a/mm/filemap.c
@@ -623,9 +623,20 @@ EXPORT_SYMBOL(__lock_page);
 int __lock_page_killable(struct page *page)
 {
 	DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
+	int ret;
 
-	return __wait_on_bit_lock(page_waitqueue(page), &wait,
+	ret = __wait_on_bit_lock(page_waitqueue(page), &wait,
 					sync_page_killable, TASK_KILLABLE);
+	/*
+	 * wait_on_bit_lock uses prepare_to_wait_exclusive, so if multiple
+	 * procs were waiting on this page, we were the only proc woken up.
+	 *
+	 * if ret != 0, we didn't actually get the lock.  We need to
+	 * make sure any other waiters don't sleep forever.
+	 */
+	if (ret)
+		wake_up_page(page, PG_locked);
+	return ret;
 }
 
 /**
_

Patches currently in -mm which might be from chris.mason@oracle.com are

origin.patch
lock_page_killable-avoid-lost-wakeups.patch
nilfs2-segment-constructor-insert-checks-and-hole-block-allocation-in-page_mkwrite.patch
nilfs2-fix-miss-sync-issue-for-do_sync_mapping_range.patch


^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2009-02-02 15:49 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-17 21:51 + lock_page_killable-avoid-lost-wakeups.patch added to -mm tree Oleg Nesterov
2009-01-18  1:38 ` [PATCH v3] wait: prevent waiter starvation in __wait_on_bit_lock Johannes Weiner
2009-01-18  1:38   ` Johannes Weiner
2009-01-18  2:32   ` Oleg Nesterov
2009-01-18  2:32     ` Oleg Nesterov
2009-01-20 20:31     ` Johannes Weiner
2009-01-20 20:31       ` Johannes Weiner
2009-01-21 14:36       ` Oleg Nesterov
2009-01-21 14:36         ` Oleg Nesterov
2009-01-21 21:38         ` [RFC v4] " Johannes Weiner
2009-01-21 21:38           ` Johannes Weiner
2009-01-22 20:25           ` Oleg Nesterov
2009-01-22 20:25             ` Oleg Nesterov
2009-01-23  0:26             ` Dmitry Adamushko
2009-01-23  0:26               ` Dmitry Adamushko
2009-01-23  0:47               ` Oleg Nesterov
2009-01-23  0:47                 ` Oleg Nesterov
2009-01-23 10:07                 ` Dmitry Adamushko
2009-01-23 10:07                   ` Dmitry Adamushko
2009-01-23 11:05                   ` Oleg Nesterov
2009-01-23 11:05                     ` Oleg Nesterov
2009-01-23 12:36                     ` Dmitry Adamushko
2009-01-23 12:36                       ` Dmitry Adamushko
2009-01-23  9:59             ` Johannes Weiner
2009-01-23  9:59               ` Johannes Weiner
2009-01-23 11:35               ` Oleg Nesterov
2009-01-23 11:35                 ` Oleg Nesterov
2009-01-23 13:30                 ` Oleg Nesterov
2009-01-23 13:30                   ` Oleg Nesterov
2009-01-26 21:59                   ` [RFC v5] wait: prevent exclusive waiter starvation Johannes Weiner
2009-01-26 21:59                     ` Johannes Weiner
2009-01-27  3:23                     ` Oleg Nesterov
2009-01-27  3:23                       ` Oleg Nesterov
2009-01-27 19:34                       ` [RFC v6] " Johannes Weiner
2009-01-27 19:34                         ` Johannes Weiner
2009-01-27 20:05                         ` Oleg Nesterov
2009-01-27 20:05                           ` Oleg Nesterov
2009-01-27 22:31                           ` Johannes Weiner
2009-01-27 22:31                             ` Johannes Weiner
2009-01-28  9:14                           ` [RFC v7] " Johannes Weiner
2009-01-28  9:14                             ` Johannes Weiner
2009-01-29  4:42                             ` Oleg Nesterov
2009-01-29  4:42                               ` Oleg Nesterov
2009-01-29  7:37                               ` Andrew Morton
2009-01-29  7:37                                 ` Andrew Morton
2009-01-29  8:31                                 ` Oleg Nesterov
2009-01-29  8:31                                   ` Oleg Nesterov
2009-01-29  9:11                                   ` Andrew Morton
2009-01-29  9:11                                     ` Andrew Morton
2009-01-29 14:34                                     ` Chris Mason
2009-01-29 14:34                                       ` Chris Mason
2009-02-02 15:47                                       ` Chris Mason
2009-02-02 15:47                                         ` Chris Mason
2009-01-23 19:24                 ` [RFC v4] wait: prevent waiter starvation in __wait_on_bit_lock Johannes Weiner
2009-01-23 19:24                   ` Johannes Weiner
  -- strict thread matches above, loose matches on Subject: below --
2009-01-16 22:44 + lock_page_killable-avoid-lost-wakeups.patch added to -mm tree akpm

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.