return pgoff >> (PAGE_CACHE_SHIFT - PAGE_SHIFT);
}
-extern void __lock_page(struct page *page);
extern void __lock_page_nosync(struct page *page);
extern int __lock_page_async(struct page *page, struct wait_bit_queue *);
extern void unlock_page(struct page *page);
return (likely(!test_and_set_bit_lock(PG_locked, &page->flags)));
}
-/*
- * lock_page may only be called if we have the page's inode pinned.
- */
-static inline void lock_page(struct page *page)
-{
- might_sleep();
- if (!trylock_page(page))
- __lock_page(page);
-}
-
/*
* lock_page_nosync should only be used if we can't pin the page's inode.
* Doesn't play quite so well with block device plugging.
return 0;
}
-
+
+/*
+ * lock_page may only be called if we have the page's inode pinned.
+ */
+static inline void lock_page(struct page *page)
+{
+ might_sleep();
+
+ if (!trylock_page(page)) {
+ int ret = __lock_page_async(page, NULL);
+ WARN_ON(ret);
+ }
+}
+
/*
* This is exported only for wait_on_page_locked/wait_on_page_writeback.
* Never use this directly!
EXPORT_SYMBOL(end_page_writeback);
/**
- * __lock_page - get a lock on the page, assuming we need to sleep to get it
+ * __lock_page_async - get a lock on the page, assuming we need to sleep to get it
* @page: the page to lock
*
* Ugly. Running sync_page() in state TASK_UNINTERRUPTIBLE is scary. If some
* 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)
-{
- DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
-
- __wait_on_bit_lock(page_waitqueue(page), &wait, sync_page,
- TASK_UNINTERRUPTIBLE);
-}
-EXPORT_SYMBOL(__lock_page);
-
int __lock_page_async(struct page *page, struct wait_bit_queue *wq)
{
+ int (*fn)(void *);
+
if (wq) {
wq->key.flags = &page->flags;
wq->key.bit_nr = PG_locked;
- }
+ fn = sync_page_killable;
+ } else
+ fn = sync_page;
- return __wait_on_bit_lock(page_waitqueue(page), wq, sync_page_killable,
+ return __wait_on_bit_lock(page_waitqueue(page), wq, fn,
TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(__lock_page_async);