Loading include/linux/pagemap.h +37 −0 Original line number Diff line number Diff line Loading @@ -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, Loading mm/filemap.c +4 −31 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading
include/linux/pagemap.h +37 −0 Original line number Diff line number Diff line Loading @@ -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, Loading
mm/filemap.c +4 −31 Original line number Diff line number Diff line Loading @@ -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); } Loading