mm: abstract out wake_page_match() from wake_page_function()
authorJens Axboe <axboe@kernel.dk>
Sat, 23 May 2020 14:22:14 +0000 (08:22 -0600)
committerJens Axboe <axboe@kernel.dk>
Mon, 22 Jun 2020 02:44:25 +0000 (20:44 -0600)
No functional changes in this patch, just in preparation for allowing
more callers.

Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/pagemap.h
mm/filemap.c

index cf2468d..2f18221 100644 (file)
@@ -496,6 +496,43 @@ static inline pgoff_t linear_page_index(struct vm_area_struct *vma,
        return pgoff;
 }
 
+/* This has the same layout as wait_bit_key - see fs/cachefiles/rdwr.c */
+struct wait_page_key {
+       struct page *page;
+       int bit_nr;
+       int page_match;
+};
+
+struct wait_page_queue {
+       struct page *page;
+       int bit_nr;
+       wait_queue_entry_t wait;
+};
+
+static inline int wake_page_match(struct wait_page_queue *wait_page,
+                                 struct wait_page_key *key)
+{
+       if (wait_page->page != key->page)
+              return 0;
+       key->page_match = 1;
+
+       if (wait_page->bit_nr != key->bit_nr)
+               return 0;
+
+       /*
+        * Stop walking if it's locked.
+        * Is this safe if put_and_wait_on_page_locked() is in use?
+        * Yes: the waker must hold a reference to this page, and if PG_locked
+        * has now already been set by another task, that task must also hold
+        * a reference to the *same usage* of this page; so there is no need
+        * to walk on to wake even the put_and_wait_on_page_locked() callers.
+        */
+       if (test_bit(key->bit_nr, &key->page->flags))
+               return -1;
+
+       return 1;
+}
+
 extern void __lock_page(struct page *page);
 extern int __lock_page_killable(struct page *page);
 extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
index 3378d4f..c3175db 100644 (file)
@@ -987,43 +987,16 @@ void __init pagecache_init(void)
        page_writeback_init();
 }
 
-/* This has the same layout as wait_bit_key - see fs/cachefiles/rdwr.c */
-struct wait_page_key {
-       struct page *page;
-       int bit_nr;
-       int page_match;
-};
-
-struct wait_page_queue {
-       struct page *page;
-       int bit_nr;
-       wait_queue_entry_t wait;
-};
-
 static int wake_page_function(wait_queue_entry_t *wait, unsigned mode, int sync, void *arg)
 {
        struct wait_page_key *key = arg;
        struct wait_page_queue *wait_page
                = container_of(wait, struct wait_page_queue, wait);
+       int ret;
 
-       if (wait_page->page != key->page)
-              return 0;
-       key->page_match = 1;
-
-       if (wait_page->bit_nr != key->bit_nr)
-               return 0;
-
-       /*
-        * Stop walking if it's locked.
-        * Is this safe if put_and_wait_on_page_locked() is in use?
-        * Yes: the waker must hold a reference to this page, and if PG_locked
-        * has now already been set by another task, that task must also hold
-        * a reference to the *same usage* of this page; so there is no need
-        * to walk on to wake even the put_and_wait_on_page_locked() callers.
-        */
-       if (test_bit(key->bit_nr, &key->page->flags))
-               return -1;
-
+       ret = wake_page_match(wait_page, key);
+       if (ret != 1)
+               return ret;
        return autoremove_wake_function(wait, mode, sync, key);
 }