Index: linux-2.6/include/linux/page-flags.h =================================================================== --- linux-2.6.orig/include/linux/page-flags.h 2007-04-24 10:39:56.000000000 +1000 +++ linux-2.6/include/linux/page-flags.h 2007-05-03 08:38:53.000000000 +1000 @@ -91,6 +91,8 @@ #define PG_nosave_free 18 /* Used for system suspend/resume */ #define PG_buddy 19 /* Page is free, on buddy lists */ +#define PG_waiters 20 /* Page has PG_locked waiters */ + /* PG_owner_priv_1 users should have descriptive aliases */ #define PG_checked PG_owner_priv_1 /* Used by some filesystems */ Index: linux-2.6/include/linux/pagemap.h =================================================================== --- linux-2.6.orig/include/linux/pagemap.h 2007-04-24 10:39:56.000000000 +1000 +++ linux-2.6/include/linux/pagemap.h 2007-05-03 08:35:08.000000000 +1000 @@ -141,7 +141,7 @@ static inline void lock_page(struct page *page) { might_sleep(); - if (TestSetPageLocked(page)) + if (unlikely(TestSetPageLocked(page))) __lock_page(page); } @@ -152,7 +152,7 @@ static inline void lock_page_nosync(struct page *page) { might_sleep(); - if (TestSetPageLocked(page)) + if (unlikely(TestSetPageLocked(page))) __lock_page_nosync(page); } Index: linux-2.6/mm/filemap.c =================================================================== --- linux-2.6.orig/mm/filemap.c 2007-05-02 15:00:26.000000000 +1000 +++ linux-2.6/mm/filemap.c 2007-05-03 08:34:32.000000000 +1000 @@ -532,11 +532,13 @@ */ void fastcall unlock_page(struct page *page) { + VM_BUG_ON(!PageLocked(page)); smp_mb__before_clear_bit(); - if (!TestClearPageLocked(page)) - BUG(); - smp_mb__after_clear_bit(); - wake_up_page(page, PG_locked); + ClearPageLocked(page); + if (unlikely(test_bit(PG_waiters, &page->flags))) { + clear_bit(PG_waiters, &page->flags); + wake_up_page(page, PG_locked); + } } EXPORT_SYMBOL(unlock_page); @@ -568,6 +570,11 @@ { DEFINE_WAIT_BIT(wait, &page->flags, PG_locked); + set_bit(PG_waiters, &page->flags); + if (unlikely(!TestSetPageLocked(page))) { + clear_bit(PG_waiters, &page->flags); + return; + } __wait_on_bit_lock(page_waitqueue(page), &wait, sync_page, TASK_UNINTERRUPTIBLE); }