From: William Lee Irwin III Consolidate bit waiting code patterns for page waitqueues using __wait_on_bit() and __wait_on_bit_lock(). DESC consolidate-bit-waiting-code-patterns-cleanup EDESC DESC __wait_on_bit-fix EDESC Signed-off-by: Andrew Morton --- 25-akpm/include/linux/wait.h | 2 ++ 25-akpm/kernel/wait.c | 37 +++++++++++++++++++++++++++++++++++++ 25-akpm/mm/filemap.c | 40 ++++++++++++++++++---------------------- 3 files changed, 57 insertions(+), 22 deletions(-) diff -puN include/linux/wait.h~consolidate-bit-waiting-code-patterns include/linux/wait.h --- 25/include/linux/wait.h~consolidate-bit-waiting-code-patterns 2004-09-21 01:57:12.593523312 -0700 +++ 25-akpm/include/linux/wait.h 2004-09-21 01:57:12.600522248 -0700 @@ -139,6 +139,8 @@ void FASTCALL(__wake_up(wait_queue_head_ extern void FASTCALL(__wake_up_locked(wait_queue_head_t *q, unsigned int mode)); extern void FASTCALL(__wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr)); void FASTCALL(__wake_up_bit(wait_queue_head_t *, void *, int)); +int FASTCALL(__wait_on_bit(wait_queue_head_t *, struct wait_bit_queue *, void *, int, int (*)(void *), unsigned)); +int FASTCALL(__wait_on_bit_lock(wait_queue_head_t *, struct wait_bit_queue *, void *, int, int (*)(void *), unsigned)); #define wake_up(x) __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1, NULL) #define wake_up_nr(x, nr) __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr, NULL) diff -puN kernel/wait.c~consolidate-bit-waiting-code-patterns kernel/wait.c --- 25/kernel/wait.c~consolidate-bit-waiting-code-patterns 2004-09-21 01:57:12.595523008 -0700 +++ 25-akpm/kernel/wait.c 2004-09-21 01:57:12.601522096 -0700 @@ -143,6 +143,43 @@ int wake_bit_function(wait_queue_t *wait } EXPORT_SYMBOL(wake_bit_function); +/* + * To allow interruptible waiting and asynchronous (i.e. nonblocking) + * waiting, the actions of __wait_on_bit() and __wait_on_bit_lock() are + * permitted return codes. Nonzero return codes halt waiting and return. + */ +int __sched fastcall +__wait_on_bit(wait_queue_head_t *wq, struct wait_bit_queue *q, + void *word, int bit, int (*action)(void *), unsigned mode) +{ + int ret = 0; + + prepare_to_wait(wq, &q->wait, mode); + if (test_bit(bit, word)) + ret = (*action)(word); + finish_wait(wq, &q->wait); + return ret; +} +EXPORT_SYMBOL(__wait_on_bit); + +int __sched fastcall +__wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, + void *word, int bit, int (*action)(void *), unsigned mode) +{ + int ret = 0; + + while (test_and_set_bit(bit, word)) { + prepare_to_wait_exclusive(wq, &q->wait, mode); + if (test_bit(bit, word)) { + if ((ret = (*action)(word))) + break; + } + } + finish_wait(wq, &q->wait); + return ret; +} +EXPORT_SYMBOL(__wait_on_bit_lock); + void fastcall __wake_up_bit(wait_queue_head_t *wq, void *word, int bit) { struct wait_bit_key key = __WAIT_BIT_KEY_INITIALIZER(word, bit); diff -puN mm/filemap.c~consolidate-bit-waiting-code-patterns mm/filemap.c --- 25/mm/filemap.c~consolidate-bit-waiting-code-patterns 2004-09-21 01:57:12.597522704 -0700 +++ 25-akpm/mm/filemap.c 2004-09-21 01:57:12.603521792 -0700 @@ -133,9 +133,12 @@ void remove_from_page_cache(struct page } EXPORT_SYMBOL(remove_from_page_cache); -static inline int sync_page(struct page *page) +static int sync_page(void *word) { struct address_space *mapping; + struct page *page; + + page = container_of((page_flags_t *)word, struct page, flags); /* * FIXME, fercrissake. What is this barrier here for? @@ -143,7 +146,8 @@ static inline int sync_page(struct page smp_mb(); mapping = page_mapping(page); if (mapping && mapping->a_ops && mapping->a_ops->sync_page) - return mapping->a_ops->sync_page(page); + mapping->a_ops->sync_page(page); + io_schedule(); return 0; } @@ -370,19 +374,19 @@ static wait_queue_head_t *page_waitqueue return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)]; } +static inline void wake_up_page(struct page *page, int bit) +{ + __wake_up_bit(page_waitqueue(page), &page->flags, bit); +} + void fastcall wait_on_page_bit(struct page *page, int bit_nr) { - wait_queue_head_t *waitqueue = page_waitqueue(page); DEFINE_WAIT_BIT(wait, &page->flags, bit_nr); - prepare_to_wait(waitqueue, &wait.wait, TASK_UNINTERRUPTIBLE); - if (test_bit(bit_nr, &page->flags)) { - sync_page(page); - io_schedule(); - } - finish_wait(waitqueue, &wait.wait); + if (test_bit(bit_nr, &page->flags)) + __wait_on_bit(page_waitqueue(page), &wait, wait.key.flags, + bit_nr, sync_page, TASK_UNINTERRUPTIBLE); } - EXPORT_SYMBOL(wait_on_page_bit); /** @@ -406,7 +410,7 @@ void fastcall unlock_page(struct page *p if (!TestClearPageLocked(page)) BUG(); smp_mb__after_clear_bit(); - __wake_up_bit(page_waitqueue(page), &page->flags, PG_locked); + wake_up_page(page, PG_locked); } EXPORT_SYMBOL(unlock_page); @@ -422,7 +426,7 @@ void end_page_writeback(struct page *pag BUG(); smp_mb__after_clear_bit(); } - __wake_up_bit(page_waitqueue(page), &page->flags, PG_writeback); + wake_up_page(page, PG_writeback); } EXPORT_SYMBOL(end_page_writeback); @@ -437,19 +441,11 @@ EXPORT_SYMBOL(end_page_writeback); */ void fastcall __lock_page(struct page *page) { - wait_queue_head_t *wqh = page_waitqueue(page); DEFINE_WAIT_BIT(wait, &page->flags, PG_locked); - while (TestSetPageLocked(page)) { - prepare_to_wait_exclusive(wqh, &wait.wait, TASK_UNINTERRUPTIBLE); - if (PageLocked(page)) { - sync_page(page); - io_schedule(); - } - } - finish_wait(wqh, &wait.wait); + __wait_on_bit_lock(page_waitqueue(page), &wait, wait.key.flags, + PG_locked, sync_page, TASK_UNINTERRUPTIBLE); } - EXPORT_SYMBOL(__lock_page); /* _