mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
mm: abstract out wake_page_match() from wake_page_function()
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>
This commit is contained in:
parent
2e85abf053
commit
c7510ab2cf
2 changed files with 41 additions and 31 deletions
|
@ -496,6 +496,43 @@ static inline pgoff_t linear_page_index(struct vm_area_struct *vma,
|
||||||
return pgoff;
|
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 void __lock_page(struct page *page);
|
||||||
extern int __lock_page_killable(struct page *page);
|
extern int __lock_page_killable(struct page *page);
|
||||||
extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
|
extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
|
||||||
|
|
35
mm/filemap.c
35
mm/filemap.c
|
@ -987,43 +987,16 @@ void __init pagecache_init(void)
|
||||||
page_writeback_init();
|
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)
|
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_key *key = arg;
|
||||||
struct wait_page_queue *wait_page
|
struct wait_page_queue *wait_page
|
||||||
= container_of(wait, struct wait_page_queue, wait);
|
= container_of(wait, struct wait_page_queue, wait);
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (wait_page->page != key->page)
|
ret = wake_page_match(wait_page, key);
|
||||||
return 0;
|
if (ret != 1)
|
||||||
key->page_match = 1;
|
return ret;
|
||||||
|
|
||||||
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 autoremove_wake_function(wait, mode, sync, key);
|
return autoremove_wake_function(wait, mode, sync, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue