Whamcloud - gitweb
LU-14713 llite: tighten condition for fault not drop mmap_sem 15/44715/7
authorBobi Jam <bobijam@whamcloud.com>
Thu, 2 Sep 2021 16:38:43 +0000 (00:38 +0800)
committerOleg Drokin <green@whamcloud.com>
Sat, 20 Nov 2021 06:25:38 +0000 (06:25 +0000)
As __lock_page_or_retry() indicates, filemap_fault() will return
VM_FAULT_RETRY without releasing mmap_sem iff flags contains
FAULT_FLAG_ALLOW_RETRY and FAULT_FLAG_RETRY_NOWAIT.

So ll_fault0() should pass in FAULT_FLAG_ALLOW_RETRY |
FAULT_FLAG_RETRY_NOWAIT in ll_filemap_fault() so that when it
returns VM_FAULT_RETRY, we can pass on trying normal fault
under DLM lock as mmap_sem is still being held.

While in Linux 5.1 (6b4c9f4469819) FAULT_FLAG_RETRY_NOWAIT is enough
to not drop mmap_sem when failed to lock the page.

Fixes: 87865e4ae9 ("LU-13182 llite: Avoid eternel retry loops with MAP_POPULATE")
Signed-off-by: Bobi Jam <bobijam@whamcloud.com>
Change-Id: I9420c587301722b597155558657577349a8141e4
Reviewed-on: https://review.whamcloud.com/44715
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Neil Brown <neilb@suse.de>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/llite_mmap.c

index 982002c..203a56c 100644 (file)
@@ -279,15 +279,23 @@ static vm_fault_t ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf)
 
        if (ll_sbi_has_fast_read(ll_i2sbi(inode))) {
                /* do fast fault */
+               bool allow_retry = vmf->flags & FAULT_FLAG_ALLOW_RETRY;
                bool has_retry = vmf->flags & FAULT_FLAG_RETRY_NOWAIT;
 
                /* To avoid loops, instruct downstream to not drop mmap_sem */
-               vmf->flags |= FAULT_FLAG_RETRY_NOWAIT;
+               /**
+                * only need FAULT_FLAG_ALLOW_RETRY prior to Linux 5.1
+                * (6b4c9f4469819), where FAULT_FLAG_RETRY_NOWAIT is enough
+                * to not drop mmap_sem when failed to lock the page.
+                */
+               vmf->flags |= FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT;
                ll_cl_add(inode, env, NULL, LCC_MMAP);
                fault_ret = ll_filemap_fault(vma, vmf);
                ll_cl_remove(inode, env);
                if (!has_retry)
                        vmf->flags &= ~FAULT_FLAG_RETRY_NOWAIT;
+               if (!allow_retry)
+                       vmf->flags &= ~FAULT_FLAG_ALLOW_RETRY;
 
                /* - If there is no error, then the page was found in cache and
                 *   uptodate;