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; |
