Async page wait 25-akpm/include/linux/pagemap.h | 19 ++++++++++++++++++ 25-akpm/mm/filemap.c | 41 ++++++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 8 deletions(-) diff -puN include/linux/pagemap.h~aio-02-lockpage_wq include/linux/pagemap.h --- 25/include/linux/pagemap.h~aio-02-lockpage_wq Fri May 16 16:29:31 2003 +++ 25-akpm/include/linux/pagemap.h Fri May 16 16:29:31 2003 @@ -135,6 +135,16 @@ static inline void lock_page(struct page if (TestSetPageLocked(page)) __lock_page(page); } + +extern int FASTCALL(__lock_page_wq(struct page *page, wait_queue_t *wait)); +static inline int lock_page_wq(struct page *page, wait_queue_t *wait) +{ + if (TestSetPageLocked(page)) + return __lock_page_wq(page, wait); + else + return 0; +} + /* * This is exported only for wait_on_page_locked/wait_on_page_writeback. @@ -155,6 +165,15 @@ static inline void wait_on_page_locked(s wait_on_page_bit(page, PG_locked); } +extern int FASTCALL(wait_on_page_bit_wq(struct page *page, int bit_nr, + wait_queue_t *wait)); +static inline int wait_on_page_locked_wq(struct page *page, wait_queue_t *wait) +{ + if (PageLocked(page)) + return wait_on_page_bit_wq(page, PG_locked, wait); + return 0; +} + /* * Wait for a page to complete writeback */ diff -puN mm/filemap.c~aio-02-lockpage_wq mm/filemap.c --- 25/mm/filemap.c~aio-02-lockpage_wq Fri May 16 16:29:31 2003 +++ 25-akpm/mm/filemap.c Fri May 16 16:29:31 2003 @@ -267,19 +267,32 @@ static wait_queue_head_t *page_waitqueue return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)]; } -void wait_on_page_bit(struct page *page, int bit_nr) +int wait_on_page_bit_wq(struct page *page, int bit_nr, wait_queue_t *wait) { wait_queue_head_t *waitqueue = page_waitqueue(page); - DEFINE_WAIT(wait); + DEFINE_WAIT(local_wait); + if (!wait) + wait = &local_wait; + do { - prepare_to_wait(waitqueue, &wait, TASK_UNINTERRUPTIBLE); + prepare_to_wait(waitqueue, wait, TASK_UNINTERRUPTIBLE); if (test_bit(bit_nr, &page->flags)) { sync_page(page); + if (!is_sync_wait(wait)) + return -EIOCBRETRY; io_schedule(); } } while (test_bit(bit_nr, &page->flags)); - finish_wait(waitqueue, &wait); + finish_wait(waitqueue, wait); + + return 0; +} +EXPORT_SYMBOL(wait_on_page_bit_wq); + +void wait_on_page_bit(struct page *page, int bit_nr) +{ + wait_on_page_bit_wq(page, bit_nr, NULL); } EXPORT_SYMBOL(wait_on_page_bit); @@ -335,19 +348,31 @@ EXPORT_SYMBOL(end_page_writeback); * chances are that on the second loop, the block layer's plug list is empty, * so sync_page() will then return in state TASK_UNINTERRUPTIBLE. */ -void __lock_page(struct page *page) +int __lock_page_wq(struct page *page, wait_queue_t *wait) { wait_queue_head_t *wqh = page_waitqueue(page); - DEFINE_WAIT(wait); + DEFINE_WAIT(local_wait); + if (!wait) + wait = &local_wait; + while (TestSetPageLocked(page)) { - prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); + prepare_to_wait(wqh, wait, TASK_UNINTERRUPTIBLE); if (PageLocked(page)) { sync_page(page); + if (!is_sync_wait(wait)) + return -EIOCBRETRY; io_schedule(); } } - finish_wait(wqh, &wait); + finish_wait(wqh, wait); + return 0; +} +EXPORT_SYMBOL(__lock_page_wq); + +void __lock_page(struct page *page) +{ + __lock_page_wq(page, NULL); } EXPORT_SYMBOL(__lock_page); _