return pgoff >> (PAGE_CACHE_SHIFT - PAGE_SHIFT);
}
-extern void __lock_page(struct page *page);
-extern int __lock_page_killable(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);
static inline void __set_page_locked(struct page *page)
}
/*
- * lock_page may only be called if we have the page's inode pinned.
+ * 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.
*/
-static inline void lock_page(struct page *page)
+static inline void lock_page_nosync(struct page *page)
{
might_sleep();
if (!trylock_page(page))
- __lock_page(page);
+ __lock_page_nosync(page);
}
/*
- * lock_page_killable is like lock_page but can be interrupted by fatal
- * signals. It returns 0 if it locked the page and -EINTR if it was
- * killed while waiting.
+ * This is like lock_page(), except that it wont schedule away waiting for
+ * the page to become unlocked by IO. Instead it registers a callback
+ * in the wait_queue and returns -EIOCBRETRY. This happens if the current
+ * process has registered an "async" wait queue, if not this just blocks like
+ * lock_page(). If that happens, this helper may also return fatal signals
+ * terminating the wait, even if the page isn't locked yet.
*/
-static inline int lock_page_killable(struct page *page)
+static inline int lock_page_async(struct page *page, struct wait_bit_queue *wq)
{
- might_sleep();
- if (!trylock_page(page))
- return __lock_page_killable(page);
+ if (!trylock_page(page)) {
+ DEFINE_WAIT_BIT(wq_stack, &page->flags, PG_locked);
+
+ if (!wq)
+ wq = &wq_stack;
+ else {
+ wq->key.flags = &page->flags;
+ wq->key.bit_nr = PG_locked;
+ }
+
+ return __lock_page_async(page, wq);
+ }
+
return 0;
}
/*
- * 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.
+ * lock_page may only be called if we have the page's inode pinned.
*/
-static inline void lock_page_nosync(struct page *page)
+static inline void lock_page(struct page *page)
{
- might_sleep();
- if (!trylock_page(page))
- __lock_page_nosync(page);
+ WARN_ON(current->io_wait);
+ lock_page_async(page, NULL);
}
-
+
/*
* This is exported only for wait_on_page_locked/wait_on_page_writeback.
* Never use this directly!
wait_on_page_bit(page, PG_locked);
}
+extern int wait_on_page_bit_async(struct page *page, int bit_nr,
+ struct wait_bit_queue *);
+
+static inline int wait_on_page_locked_async(struct page *page,
+ struct wait_bit_queue *wait)
+{
+ if (PageLocked(page))
+ return wait_on_page_bit_async(page, PG_locked, wait);
+
+ return 0;
+}
+
/*
* Wait for a page to complete writeback
*/