Whamcloud - gitweb
LU-13182 llite: Avoid eternel retry loops with MAP_POPULATE
[fs/lustre-release.git] / lustre / llite / llite_mmap.c
index 673ff2c..242f4f4 100644 (file)
@@ -148,7 +148,7 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage,
        struct vvp_io           *vio;
        int                      result;
        __u16                    refcheck;
-       sigset_t                 set;
+       sigset_t old, new;
        struct inode             *inode = NULL;
        struct ll_inode_info     *lli;
        ENTRY;
@@ -173,14 +173,15 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage,
        vio->u.fault.ft_vma    = vma;
        vio->u.fault.ft_vmpage = vmpage;
 
-       set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM));
+       siginitsetinv(&new, sigmask(SIGKILL) | sigmask(SIGTERM));
+       sigprocmask(SIG_BLOCK, &new, &old);
 
        inode = vvp_object_inode(io->ci_obj);
        lli = ll_i2info(inode);
 
        result = cl_io_loop(env, io);
 
-       cfs_restore_sigs(set);
+       sigprocmask(SIG_SETMASK, &old, NULL);
 
         if (result == 0) {
                 lock_page(vmpage);
@@ -279,16 +280,22 @@ static vm_fault_t ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf)
 
        if (ll_sbi_has_fast_read(ll_i2sbi(file_inode(vma->vm_file)))) {
                /* do fast fault */
+               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;
                ll_cl_add(vma->vm_file, env, NULL, LCC_MMAP);
                fault_ret = ll_filemap_fault(vma, vmf);
                ll_cl_remove(vma->vm_file, env);
+               if (!has_retry)
+                       vmf->flags &= ~FAULT_FLAG_RETRY_NOWAIT;
 
                /* - If there is no error, then the page was found in cache and
                 *   uptodate;
                 * - If VM_FAULT_RETRY is set, the page existed but failed to
-                *   lock. It will return to kernel and retry;
+                *   lock. We will try slow path to avoid loops.
                 * - Otherwise, it should try normal fault under DLM lock. */
-               if ((fault_ret & VM_FAULT_RETRY) ||
+               if (!(fault_ret & VM_FAULT_RETRY) &&
                    !(fault_ret & VM_FAULT_ERROR))
                        GOTO(out, result = 0);
 
@@ -352,7 +359,7 @@ static vm_fault_t ll_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        bool cached;
        vm_fault_t result;
        ktime_t kstart = ktime_get();
-       sigset_t set;
+       sigset_t old, new;
 
        result = pcc_fault(vma, vmf, &cached);
        if (cached)
@@ -360,8 +367,10 @@ static vm_fault_t ll_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
        /* Only SIGKILL and SIGTERM is allowed for fault/nopage/mkwrite
         * so that it can be killed by admin but not cause segfault by
-        * other signals. */
-       set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM));
+        * other signals.
+        */
+       siginitsetinv(&new, sigmask(SIGKILL) | sigmask(SIGTERM));
+       sigprocmask(SIG_BLOCK, &new, &old);
 
        /* make sure offset is not a negative number */
        if (vmf->pgoff > (MAX_LFS_FILESIZE >> PAGE_SHIFT))
@@ -390,7 +399,7 @@ restart:
 
                result |= VM_FAULT_LOCKED;
        }
-       cfs_restore_sigs(set);
+       sigprocmask(SIG_SETMASK, &old, NULL);
 
 out:
        if (vmf->page && result == VM_FAULT_LOCKED) {
@@ -517,7 +526,7 @@ int ll_teardown_mmaps(struct address_space *mapping, __u64 first, __u64 last)
         if (mapping_mapped(mapping)) {
                 rc = 0;
                unmap_mapping_range(mapping, first + PAGE_SIZE - 1,
-                                   last - first + 1, 1);
+                                   last - first + 1, 0);
         }
 
         RETURN(rc);