On Fri, 8 Oct 2010 18:22:04 -0700 Michel Lespinasse <walken@xxxxxxxxxx> wrote: > Second try on adding the VM_FAULT_RETRY functionality to the swap in path. > > This proposal would replace [patch 2/3] of this series (the initial > version of it, which was approved by linus / rik / hpa). > > Changes since the approved version: > > - split lock_page_or_retry() into an inline function in pagemap.h, > handling the trylock_page() fast path, and __lock_page_or_retry() in > filemap.c, handling the blocking path (with or without retry). > > - make do_swap_page() call lock_page_or_retry() in place of lock_page(), > and handle the retry case. Replacement patches are a bit cruel to people who've already reviewed the previous version. I always turn them into deltas so I can see what was changed. It is below. How well was the new swapin path tested? include/linux/pagemap.h | 13 +++++++++++++ mm/filemap.c | 35 ++++++++++++++--------------------- mm/memory.c | 7 ++++++- 3 files changed, 33 insertions(+), 22 deletions(-) diff -puN include/linux/pagemap.h~mm-retry-page-fault-when-blocking-on-disk-transfer-update include/linux/pagemap.h --- a/include/linux/pagemap.h~mm-retry-page-fault-when-blocking-on-disk-transfer-update +++ a/include/linux/pagemap.h @@ -299,6 +299,8 @@ static inline pgoff_t linear_page_index( 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_or_retry(struct page *page, struct mm_struct *mm, + unsigned int flags); extern void unlock_page(struct page *page); static inline void __set_page_locked(struct page *page) @@ -351,6 +353,17 @@ static inline void lock_page_nosync(stru } /* + * lock_page_or_retry - Lock the page, unless this would block and the + * caller indicated that it can handle a retry. + */ +static inline int lock_page_or_retry(struct page *page, struct mm_struct *mm, + unsigned int flags) +{ + might_sleep(); + return trylock_page(page) || __lock_page_or_retry(page, mm, flags); +} + +/* * This is exported only for wait_on_page_locked/wait_on_page_writeback. * Never use this directly! */ diff -puN mm/filemap.c~mm-retry-page-fault-when-blocking-on-disk-transfer-update mm/filemap.c --- a/mm/filemap.c~mm-retry-page-fault-when-blocking-on-disk-transfer-update +++ a/mm/filemap.c @@ -623,6 +623,19 @@ void __lock_page_nosync(struct page *pag TASK_UNINTERRUPTIBLE); } +int __lock_page_or_retry(struct page *page, struct mm_struct *mm, + unsigned int flags) +{ + if (!(flags & FAULT_FLAG_ALLOW_RETRY)) { + __lock_page(page); + return 1; + } else { + up_read(&mm->mmap_sem); + wait_on_page_locked(page); + return 0; + } +} + /** * find_get_page - find and get a page reference * @mapping: the address_space to search @@ -1512,26 +1525,6 @@ static void do_async_mmap_readahead(stru page, offset, ra->ra_pages); } -/* - * Lock the page, unless this would block and the caller indicated that it - * can handle a retry. - */ -static int lock_page_or_retry(struct page *page, - struct vm_area_struct *vma, struct vm_fault *vmf) -{ - if (trylock_page(page)) - return 1; - if (!(vmf->flags & FAULT_FLAG_ALLOW_RETRY)) { - __lock_page(page); - return 1; - } - - up_read(&vma->vm_mm->mmap_sem); - wait_on_page_locked(page); - page_cache_release(page); - return 0; -} - /** * filemap_fault - read in file data for page fault handling * @vma: vma in which the fault was taken @@ -1581,7 +1574,7 @@ retry_find: goto no_cached_page; } - if (!lock_page_or_retry(page, vma, vmf)) + if (!lock_page_or_retry(page, &vma->vm_mm, vmf->flags)) return ret | VM_FAULT_RETRY; /* Did it get truncated? */ diff -puN mm/memory.c~mm-retry-page-fault-when-blocking-on-disk-transfer-update mm/memory.c --- a/mm/memory.c~mm-retry-page-fault-when-blocking-on-disk-transfer-update +++ a/mm/memory.c @@ -2627,6 +2627,7 @@ static int do_swap_page(struct mm_struct struct page *page, *swapcache = NULL; swp_entry_t entry; pte_t pte; + int locked; struct mem_cgroup *ptr = NULL; int exclusive = 0; int ret = 0; @@ -2677,8 +2678,12 @@ static int do_swap_page(struct mm_struct goto out_release; } - lock_page(page); + locked = lock_page_or_retry(page, mm, flags); delayacct_clear_flag(DELAYACCT_PF_SWAPIN); + if (!locked) { + ret |= VM_FAULT_RETRY; + goto out_release; + } /* * Make sure try_to_free_swap or reuse_swap_page or swapoff did not _ -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxxx For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>