diff options
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 3195806d78e0..87d4a398cd16 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -488,6 +488,12 @@ struct page *page_cache_alloc_cold(struct address_space *x) | |||
488 | EXPORT_SYMBOL(page_cache_alloc_cold); | 488 | EXPORT_SYMBOL(page_cache_alloc_cold); |
489 | #endif | 489 | #endif |
490 | 490 | ||
491 | static int __sleep_on_page_lock(void *word) | ||
492 | { | ||
493 | io_schedule(); | ||
494 | return 0; | ||
495 | } | ||
496 | |||
491 | /* | 497 | /* |
492 | * In order to wait for pages to become available there must be | 498 | * In order to wait for pages to become available there must be |
493 | * waitqueues associated with pages. By using a hash table of | 499 | * waitqueues associated with pages. By using a hash table of |
@@ -577,13 +583,24 @@ void fastcall __lock_page(struct page *page) | |||
577 | } | 583 | } |
578 | EXPORT_SYMBOL(__lock_page); | 584 | EXPORT_SYMBOL(__lock_page); |
579 | 585 | ||
586 | /* | ||
587 | * Variant of lock_page that does not require the caller to hold a reference | ||
588 | * on the page's mapping. | ||
589 | */ | ||
590 | void fastcall __lock_page_nosync(struct page *page) | ||
591 | { | ||
592 | DEFINE_WAIT_BIT(wait, &page->flags, PG_locked); | ||
593 | __wait_on_bit_lock(page_waitqueue(page), &wait, __sleep_on_page_lock, | ||
594 | TASK_UNINTERRUPTIBLE); | ||
595 | } | ||
596 | |||
580 | /** | 597 | /** |
581 | * find_get_page - find and get a page reference | 598 | * find_get_page - find and get a page reference |
582 | * @mapping: the address_space to search | 599 | * @mapping: the address_space to search |
583 | * @offset: the page index | 600 | * @offset: the page index |
584 | * | 601 | * |
585 | * A rather lightweight function, finding and getting a reference to a | 602 | * Is there a pagecache struct page at the given (mapping, offset) tuple? |
586 | * hashed page atomically. | 603 | * If yes, increment its refcount and return it; if no, return NULL. |
587 | */ | 604 | */ |
588 | struct page * find_get_page(struct address_space *mapping, unsigned long offset) | 605 | struct page * find_get_page(struct address_space *mapping, unsigned long offset) |
589 | { | 606 | { |
@@ -970,7 +987,7 @@ page_not_up_to_date: | |||
970 | /* Get exclusive access to the page ... */ | 987 | /* Get exclusive access to the page ... */ |
971 | lock_page(page); | 988 | lock_page(page); |
972 | 989 | ||
973 | /* Did it get unhashed before we got the lock? */ | 990 | /* Did it get truncated before we got the lock? */ |
974 | if (!page->mapping) { | 991 | if (!page->mapping) { |
975 | unlock_page(page); | 992 | unlock_page(page); |
976 | page_cache_release(page); | 993 | page_cache_release(page); |
@@ -1612,7 +1629,7 @@ no_cached_page: | |||
1612 | page_not_uptodate: | 1629 | page_not_uptodate: |
1613 | lock_page(page); | 1630 | lock_page(page); |
1614 | 1631 | ||
1615 | /* Did it get unhashed while we waited for it? */ | 1632 | /* Did it get truncated while we waited for it? */ |
1616 | if (!page->mapping) { | 1633 | if (!page->mapping) { |
1617 | unlock_page(page); | 1634 | unlock_page(page); |
1618 | goto err; | 1635 | goto err; |