No functional changes in this patch, just in preparation for allowing more callers.
Unified · Split
| @@ -496,6 +496,43 @@ static inline pgoff_t linear_page_index(struct vm_area_struct *vma, · 495 unmodified lines | |||
| 496 | return pgoff; | 496 | return pgoff; |
| 497 | } | 497 | } |
| 498 | 498 | ||
| 499 | /* This has the same layout as wait_bit_key - see fs/cachefiles/rdwr.c */ | ||
| 500 | struct wait_page_key { | ||
| 501 | struct page *page; | ||
| 502 | int bit_nr; | ||
| 503 | int page_match; | ||
| 504 | }; | ||
| 505 | |||
| 506 | struct wait_page_queue { | ||
| 507 | struct page *page; | ||
| 508 | int bit_nr; | ||
| 509 | wait_queue_entry_t wait; | ||
| 510 | }; | ||
| 511 | |||
| 512 | static inline int wake_page_match(struct wait_page_queue *wait_page, | ||
| 513 | struct wait_page_key *key) | ||
| 514 | { | ||
| 515 | if (wait_page->page != key->page) | ||
| 516 | return 0; | ||
| 517 | key->page_match = 1; | ||
| 518 | |||
| 519 | if (wait_page->bit_nr != key->bit_nr) | ||
| 520 | return 0; | ||
| 521 | |||
| 522 | /* | ||
| 523 | * Stop walking if it's locked. | ||
| 524 | * Is this safe if put_and_wait_on_page_locked() is in use? | ||
| 525 | * Yes: the waker must hold a reference to this page, and if PG_locked | ||
| 526 | * has now already been set by another task, that task must also hold | ||
| 527 | * a reference to the *same usage* of this page; so there is no need | ||
| 528 | * to walk on to wake even the put_and_wait_on_page_locked() callers. | ||
| 529 | */ | ||
| 530 | if (test_bit(key->bit_nr, &key->page->flags)) | ||
| 531 | return -1; | ||
| 532 | |||
| 533 | return 1; | ||
| 534 | } | ||
| 535 | |||
| 499 | extern void __lock_page(struct page *page); | 536 | extern void __lock_page(struct page *page); |
| 500 | extern int __lock_page_killable(struct page *page); | 537 | extern int __lock_page_killable(struct page *page); |
| 501 | extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm, | 538 | extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm, |
| @@ -987,43 +987,16 @@ void __init pagecache_init(void) · 986 unmodified lines | |||
| 987 | page_writeback_init(); | 987 | page_writeback_init(); |
| 988 | } | 988 | } |
| 989 | 989 | ||
| 990 | /* This has the same layout as wait_bit_key - see fs/cachefiles/rdwr.c */ | ||
| 991 | struct wait_page_key { | ||
| 992 | struct page *page; | ||
| 993 | int bit_nr; | ||
| 994 | int page_match; | ||
| 995 | }; | ||
| 996 | |||
| 997 | struct wait_page_queue { | ||
| 998 | struct page *page; | ||
| 999 | int bit_nr; | ||
| 1000 | wait_queue_entry_t wait; | ||
| 1001 | }; | ||
| 1002 | |||
| 1003 | static int wake_page_function(wait_queue_entry_t *wait, unsigned mode, int sync, void *arg) | 990 | static int wake_page_function(wait_queue_entry_t *wait, unsigned mode, int sync, void *arg) |
| 1004 | { | 991 | { |
| 1005 | struct wait_page_key *key = arg; | 992 | struct wait_page_key *key = arg; |
| 1006 | struct wait_page_queue *wait_page | 993 | struct wait_page_queue *wait_page |
| 1007 | = container_of(wait, struct wait_page_queue, wait); | 994 | = container_of(wait, struct wait_page_queue, wait); |
| 995 | int ret; | ||
| 1008 | 996 | ||
| 1009 | if (wait_page->page != key->page) | 997 | ret = wake_page_match(wait_page, key); |
| 1010 | return 0; | 998 | if (ret != 1) |
| 1011 | key->page_match = 1; | 999 | return ret; |
| 1012 | |||
| 1013 | if (wait_page->bit_nr != key->bit_nr) | ||
| 1014 | return 0; | ||
| 1015 | |||
| 1016 | /* | ||
| 1017 | * Stop walking if it's locked. | ||
| 1018 | * Is this safe if put_and_wait_on_page_locked() is in use? | ||
| 1019 | * Yes: the waker must hold a reference to this page, and if PG_locked | ||
| 1020 | * has now already been set by another task, that task must also hold | ||
| 1021 | * a reference to the *same usage* of this page; so there is no need | ||
| 1022 | * to walk on to wake even the put_and_wait_on_page_locked() callers. | ||
| 1023 | */ | ||
| 1024 | if (test_bit(key->bit_nr, &key->page->flags)) | ||
| 1025 | return -1; | ||
| 1026 | |||
| 1027 | return autoremove_wake_function(wait, mode, sync, key); | 1000 | return autoremove_wake_function(wait, mode, sync, key); |
| 1028 | } | 1001 | } |
| 1029 | 1002 | ||