Whamcloud - gitweb
b=21122 fix a race between page fault and lock cancel.
[fs/lustre-release.git] / lustre / llite / vvp_io.c
index 74aeb59..502ec4e 100644 (file)
@@ -26,7 +26,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  */
 /*
@@ -180,6 +180,11 @@ static int vvp_mmap_locks(const struct lu_env *env,
                                                   policy.l_extent.end);
                         descr->cld_enq_flags = flags;
                         result = cl_io_lock_alloc_add(env, io, descr);
+
+                        CDEBUG(D_VFSTRACE, "lock: %d: [%lu, %lu]\n",
+                               descr->cld_mode, descr->cld_start,
+                               descr->cld_end);
+
                         if (result < 0)
                                 RETURN(result);
 
@@ -301,10 +306,11 @@ static int vvp_io_setattr_lock(const struct lu_env *env,
                 if (new_size == 0)
                         enqflags = CEF_DISCARD_DATA;
         } else {
-                LASSERT((io->u.ci_setattr.sa_attr.lvb_mtime <
-                         io->u.ci_setattr.sa_attr.lvb_ctime) ||
-                        (io->u.ci_setattr.sa_attr.lvb_atime <
-                         io->u.ci_setattr.sa_attr.lvb_ctime));
+                if ((io->u.ci_setattr.sa_attr.lvb_mtime >=
+                     io->u.ci_setattr.sa_attr.lvb_ctime) ||
+                    (io->u.ci_setattr.sa_attr.lvb_atime >=
+                     io->u.ci_setattr.sa_attr.lvb_ctime))
+                        return 0;
                 new_size = 0;
         }
         cio->u.setattr.cui_local_lock = SETATTR_EXTENT_LOCK;
@@ -628,6 +634,14 @@ static int vvp_io_kernel_fault(struct vvp_fault_io *cfio)
         LL_CDEBUG_PAGE(D_PAGE, vmpage, "got addr %lu type %lx\n",
                        cfio->nopage.ft_address, (long)cfio->nopage.ft_type);
 
+        lock_page(vmpage);
+        if (vmpage->mapping == NULL) {
+                CERROR("vmpage %lu@%p was truncated!\n", vmpage->index, vmpage);
+                unlock_page(vmpage);
+                page_cache_release(vmpage);
+                return -EFAULT;
+        }
+
         cfio->ft_vmpage = vmpage;
 
         return 0;
@@ -641,12 +655,7 @@ static int vvp_io_kernel_fault(struct vvp_fault_io *cfio)
                 LL_CDEBUG_PAGE(D_PAGE, cfio->fault.ft_vmf->page,
                                "got addr %p type NOPAGE\n",
                                cfio->fault.ft_vmf->virtual_address);
-                /*XXX workaround to bug in CLIO - he deadlocked with
-                 lock cancel if page locked  */
-                if (likely(cfio->fault.ft_flags & VM_FAULT_LOCKED)) {
-                        unlock_page(cfio->fault.ft_vmf->page);
-                        cfio->fault.ft_flags &= ~VM_FAULT_LOCKED;
-                }
+                LASSERT(cfio->fault.ft_flags & VM_FAULT_LOCKED);
 
                 cfio->ft_vmpage = cfio->fault.ft_vmf->page;
                 return 0;
@@ -703,16 +712,11 @@ static int vvp_io_fault_start(const struct lu_env *env,
         kernel_result = vvp_io_kernel_fault(cfio);
         if (kernel_result != 0)
                 return kernel_result;
-        /* Temporarily lock vmpage to keep cl_page_find() happy. */
-        lock_page(cfio->ft_vmpage);
+
         page = cl_page_find(env, obj, fio->ft_index, cfio->ft_vmpage,
                             CPT_CACHEABLE);
-        unlock_page(cfio->ft_vmpage);
-        if (IS_ERR(page)) {
-                page_cache_release(cfio->ft_vmpage);
-                cfio->ft_vmpage = NULL;
+        if (IS_ERR(page))
                 return PTR_ERR(page);
-        }
 
         size = i_size_read(inode);
         last = cl_index(obj, size - 1);
@@ -768,7 +772,7 @@ static int vvp_io_read_page(const struct lu_env *env,
         /* Sanity check whether the page is protected by a lock. */
         rc = cl_page_is_under_lock(env, io, page);
         if (rc != -EBUSY) {
-                CL_PAGE_HEADER(D_WARNING, env, page, "%s: %i\n",
+                CL_PAGE_HEADER(D_WARNING, env, page, "%s: %d\n",
                                rc == -ENODATA ? "without a lock" :
                                "match failed", rc);
                 if (rc != -ENODATA)
@@ -804,7 +808,7 @@ static int vvp_page_sync_io(const struct lu_env *env, struct cl_io *io,
 
         cl_2queue_init_page(queue, page);
         cl_page_clip(env, page, 0, to);
-        
+
         result = cl_io_submit_sync(env, io, crt, queue, CRP_NORMAL, 0);
         LASSERT(cl_page_is_owned(page, io));
         cl_page_clip(env, page, 0, CFS_PAGE_SIZE);
@@ -984,8 +988,12 @@ static int vvp_io_commit_write(const struct lu_env *env,
 
         ll_inode_size_lock(inode, 0);
         if (result == 0) {
-                if (size > i_size_read(inode))
+                if (size > i_size_read(inode)) {
                         cl_isize_write_nolock(inode, size);
+                        CDEBUG(D_VFSTRACE, DFID" updating i_size %lu\n",
+                               PFID(lu_object_fid(&obj->co_lu)),
+                               (unsigned long)size);
+                }
                 cl_page_export(env, pg, 1);
         } else {
                 if (size > i_size_read(inode))