diff options
-rw-r--r-- | include/linux/pagemap.h | 15 | ||||
-rw-r--r-- | mm/filemap.c | 17 | ||||
-rw-r--r-- | mm/page-writeback.c | 2 |
3 files changed, 33 insertions, 1 deletions
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 0a2f5d27f60e..64f950925151 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
@@ -130,14 +130,29 @@ static inline pgoff_t linear_page_index(struct vm_area_struct *vma, | |||
130 | } | 130 | } |
131 | 131 | ||
132 | extern void FASTCALL(__lock_page(struct page *page)); | 132 | extern void FASTCALL(__lock_page(struct page *page)); |
133 | extern void FASTCALL(__lock_page_nosync(struct page *page)); | ||
133 | extern void FASTCALL(unlock_page(struct page *page)); | 134 | extern void FASTCALL(unlock_page(struct page *page)); |
134 | 135 | ||
136 | /* | ||
137 | * lock_page may only be called if we have the page's inode pinned. | ||
138 | */ | ||
135 | static inline void lock_page(struct page *page) | 139 | static inline void lock_page(struct page *page) |
136 | { | 140 | { |
137 | might_sleep(); | 141 | might_sleep(); |
138 | if (TestSetPageLocked(page)) | 142 | if (TestSetPageLocked(page)) |
139 | __lock_page(page); | 143 | __lock_page(page); |
140 | } | 144 | } |
145 | |||
146 | /* | ||
147 | * lock_page_nosync should only be used if we can't pin the page's inode. | ||
148 | * Doesn't play quite so well with block device plugging. | ||
149 | */ | ||
150 | static inline void lock_page_nosync(struct page *page) | ||
151 | { | ||
152 | might_sleep(); | ||
153 | if (TestSetPageLocked(page)) | ||
154 | __lock_page_nosync(page); | ||
155 | } | ||
141 | 156 | ||
142 | /* | 157 | /* |
143 | * This is exported only for wait_on_page_locked/wait_on_page_writeback. | 158 | * This is exported only for wait_on_page_locked/wait_on_page_writeback. |
diff --git a/mm/filemap.c b/mm/filemap.c index b9a60c43b61a..d5af1cab4268 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,6 +583,17 @@ 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 |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index b9f4c6f1be86..555752907dc3 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -701,7 +701,7 @@ int set_page_dirty_lock(struct page *page) | |||
701 | { | 701 | { |
702 | int ret; | 702 | int ret; |
703 | 703 | ||
704 | lock_page(page); | 704 | lock_page_nosync(page); |
705 | ret = set_page_dirty(page); | 705 | ret = set_page_dirty(page); |
706 | unlock_page(page); | 706 | unlock_page(page); |
707 | return ret; | 707 | return ret; |