Whamcloud - gitweb
LU-1323 llite: find_vma() should be protected by mmap_sem
authorJinshan Xiong <jinshan.xiong@whamcloud.com>
Fri, 13 Apr 2012 22:21:49 +0000 (15:21 -0700)
committerOleg Drokin <green@whamcloud.com>
Fri, 1 Jun 2012 13:18:10 +0000 (09:18 -0400)
It had been wrongly protected by page_table_lock since 2004.

Signed-off-by: Jinshan Xiong <jinshan.xiong@whamcloud.com>
Change-Id: Id7b0341dc8c385ad57e195d94f4e76b6c5626515
Reviewed-on: http://review.whamcloud.com/2543
Tested-by: Hudson
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/llite_internal.h
lustre/llite/llite_mmap.c
lustre/llite/vvp_io.c

index 0932b3c..8d0cf47 100644 (file)
@@ -1039,7 +1039,8 @@ struct ll_lock_tree_node * ll_node_from_inode(struct inode *inode, __u64 start,
                                               __u64 end, ldlm_mode_t mode);
 void policy_from_vma(ldlm_policy_data_t *policy,
                 struct vm_area_struct *vma, unsigned long addr, size_t count);
-struct vm_area_struct *our_vma(unsigned long addr, size_t count);
+struct vm_area_struct *our_vma(struct mm_struct *mm, unsigned long addr,
+                               size_t count);
 
 static inline void ll_invalidate_page(struct page *vmpage)
 {
index dc40818..00e0c1a 100644 (file)
@@ -76,17 +76,15 @@ void policy_from_vma(ldlm_policy_data_t *policy,
                                ~CFS_PAGE_MASK;
 }
 
-struct vm_area_struct * our_vma(unsigned long addr, size_t count)
+struct vm_area_struct *our_vma(struct mm_struct *mm, unsigned long addr,
+                               size_t count)
 {
-        struct mm_struct *mm = current->mm;
         struct vm_area_struct *vma, *ret = NULL;
         ENTRY;
 
-        /* No MM (e.g. NFS)? No vmas too. */
-        if (!mm)
-                RETURN(NULL);
+        /* mmap_sem must have been held by caller. */
+        LASSERT(!down_write_trylock(&mm->mmap_sem));
 
-        spin_lock(&mm->page_table_lock);
         for(vma = find_vma(mm, addr);
             vma != NULL && vma->vm_start < (addr + count); vma = vma->vm_next) {
                 if (vma->vm_ops && vma->vm_ops == &ll_file_vm_ops &&
@@ -95,7 +93,6 @@ struct vm_area_struct * our_vma(unsigned long addr, size_t count)
                         break;
                 }
         }
-        spin_unlock(&mm->page_table_lock);
         RETURN(ret);
 }
 
index 2f83fc2..d45cc26 100644 (file)
@@ -130,6 +130,7 @@ static int vvp_mmap_locks(const struct lu_env *env,
                           struct ccc_io *vio, struct cl_io *io)
 {
         struct ccc_thread_info *cti = ccc_env_info(env);
+        struct mm_struct       *mm = current->mm;
         struct vm_area_struct  *vma;
         struct cl_lock_descr   *descr = &cti->cti_descr;
         ldlm_policy_data_t      policy;
@@ -147,6 +148,10 @@ static int vvp_mmap_locks(const struct lu_env *env,
         if (vio->cui_iov == NULL) /* nfs or loop back device write */
                 RETURN(0);
 
+        /* No MM (e.g. NFS)? No vmas too. */
+        if (mm == NULL)
+                RETURN(0);
+
         for (seg = 0; seg < vio->cui_nrsegs; seg++) {
                 const struct iovec *iv = &vio->cui_iov[seg];
 
@@ -157,12 +162,14 @@ static int vvp_mmap_locks(const struct lu_env *env,
 
                 count += addr & (~CFS_PAGE_MASK);
                 addr &= CFS_PAGE_MASK;
-                while((vma = our_vma(addr, count)) != NULL) {
+
+                down_read(&mm->mmap_sem);
+                while((vma = our_vma(mm, addr, count)) != NULL) {
                         struct inode *inode = vma->vm_file->f_dentry->d_inode;
                         int flags = CEF_MUST;
 
                         if (ll_file_nolock(vma->vm_file)) {
-                                /* 
+                                /*
                                  * For no lock case, a lockless lock will be
                                  * generated.
                                  */
@@ -197,6 +204,7 @@ static int vvp_mmap_locks(const struct lu_env *env,
                         count -= vma->vm_end - addr;
                         addr = vma->vm_end;
                 }
+                up_read(&mm->mmap_sem);
         }
         RETURN(0);
 }