More helpers
[linux-block.git] / include / linux / pagemap.h
index ed5d7501e1819f217912808d6f6fc9e6f1f6f28e..4fe31627fc57d7016a9ea6af834ff85de562c3c0 100644 (file)
@@ -287,9 +287,8 @@ static inline pgoff_t linear_page_index(struct vm_area_struct *vma,
        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)
@@ -308,39 +307,51 @@ static inline int trylock_page(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!
@@ -360,6 +371,18 @@ static inline void wait_on_page_locked(struct page *page)
                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
  */