Whamcloud - gitweb
LU-3409 llite: silence lockdep warning in ll_md_blocking_ast
[fs/lustre-release.git] / lustre / llite / dcache.c
index 4a4f5f5..029e621 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, Whamcloud, Inc.
+ * Copyright (c) 2011, 2013, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -36,7 +36,6 @@
 
 #include <linux/fs.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/quotaops.h>
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
 #include "llite_internal.h"
 
+static void free_dentry_data(struct rcu_head *head)
+{
+       struct ll_dentry_data *lld;
+
+       lld = container_of(head, struct ll_dentry_data, lld_rcu_head);
+       OBD_FREE_PTR(lld);
+}
+
 /* should NOT be called with the dcache lock, see fs/dcache.c */
 static void ll_release(struct dentry *de)
 {
@@ -62,15 +69,16 @@ static void ll_release(struct dentry *de)
                 ll_intent_release(lld->lld_it);
                 OBD_FREE(lld->lld_it, sizeof(*lld->lld_it));
         }
-        LASSERT(lld->lld_cwd_count == 0);
-        LASSERT(lld->lld_mnt_count == 0);
-        OBD_FREE(de->d_fsdata, sizeof(*lld));
+       LASSERT(lld->lld_cwd_count == 0);
+       LASSERT(lld->lld_mnt_count == 0);
+       de->d_fsdata = NULL;
+       call_rcu(&lld->lld_rcu_head, free_dentry_data);
 
-        EXIT;
+       EXIT;
 }
 
 /* Compare if two dentries are the same.  Don't match if the existing dentry
- * is marked DCACHE_LUSTRE_INVALID.  Returns 1 if different, 0 if the same.
+ * is marked invalid.  Returns 1 if different, 0 if the same.
  *
  * This avoids a race where ll_lookup_it() instantiates a dentry, but we get
  * an AST before calling d_revalidate_it().  The dentry still exists (marked
@@ -183,12 +191,13 @@ static int ll_ddelete(HAVE_D_DELETE_CONST struct dentry *de)
 
        /* Disable this piece of code temproarily because this is called
         * inside dcache_lock so it's not appropriate to do lots of work
-        * here. */
+        * here. ATTENTION: Before this piece of code enabling, LU-2487 must be
+        * resolved. */
 #if 0
        /* if not ldlm lock for this inode, set i_nlink to 0 so that
         * this inode can be recycled later b=20433 */
        if (de->d_inode && !find_cbdata(de->d_inode))
-               de->d_inode->i_nlink = 0;
+               clear_nlink(de->d_inode);
 #endif
 
        if (d_lustre_invalid((struct dentry *)de))
@@ -251,18 +260,28 @@ int ll_dops_init(struct dentry *de, int block, int init_sa)
 
 void ll_intent_drop_lock(struct lookup_intent *it)
 {
-        struct lustre_handle *handle;
-
         if (it->it_op && it->d.lustre.it_lock_mode) {
-                handle = (struct lustre_handle *)&it->d.lustre.it_lock_handle;
+               struct lustre_handle handle;
+
+               handle.cookie = it->d.lustre.it_lock_handle;
+
                 CDEBUG(D_DLMTRACE, "releasing lock with cookie "LPX64
-                       " from it %p\n", handle->cookie, it);
-                ldlm_lock_decref(handle, it->d.lustre.it_lock_mode);
+                       " from it %p\n", handle.cookie, it);
+                ldlm_lock_decref(&handle, it->d.lustre.it_lock_mode);
 
                 /* bug 494: intent_release may be called multiple times, from
                  * this thread and we don't want to double-decref this lock */
                 it->d.lustre.it_lock_mode = 0;
-        }
+               if (it->d.lustre.it_remote_lock_mode != 0) {
+                       handle.cookie = it->d.lustre.it_remote_lock_handle;
+
+                       CDEBUG(D_DLMTRACE, "releasing remote lock with cookie"
+                              LPX64" from it %p\n", handle.cookie, it);
+                       ldlm_lock_decref(&handle,
+                                        it->d.lustre.it_remote_lock_mode);
+                       it->d.lustre.it_remote_lock_mode = 0;
+               }
+       }
 }
 
 void ll_intent_release(struct lookup_intent *it)
@@ -288,6 +307,7 @@ void ll_intent_release(struct lookup_intent *it)
 void ll_invalidate_aliases(struct inode *inode)
 {
        struct dentry *dentry;
+       struct ll_d_hlist_node *p;
        ENTRY;
 
        LASSERT(inode != NULL);
@@ -296,11 +316,11 @@ void ll_invalidate_aliases(struct inode *inode)
               inode->i_ino, inode->i_generation, inode);
 
        ll_lock_dcache(inode);
-       cfs_list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
-                CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p "
-                       "inode %p flags %d\n", dentry->d_name.len,
-                       dentry->d_name.name, dentry, dentry->d_parent,
-                       dentry->d_inode, dentry->d_flags);
+       ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
+               CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p "
+                      "inode %p flags %d\n", dentry->d_name.len,
+                      dentry->d_name.name, dentry, dentry->d_parent,
+                      dentry->d_inode, dentry->d_flags);
 
                 if (dentry->d_name.len == 1 && dentry->d_name.name[0] == '/') {
                         CERROR("called on root (?) dentry=%p, inode=%p "
@@ -309,7 +329,7 @@ void ll_invalidate_aliases(struct inode *inode)
                         libcfs_debug_dumpstack(NULL);
                 }
 
-               d_lustre_invalidate(dentry);
+               d_lustre_invalidate(dentry, 0);
        }
        ll_unlock_dcache(inode);
 
@@ -329,7 +349,7 @@ int ll_revalidate_it_finish(struct ptlrpc_request *request,
         if (it_disposition(it, DISP_LOOKUP_NEG))
                 RETURN(-ENOENT);
 
-        rc = ll_prep_inode(&de->d_inode, request, NULL);
+        rc = ll_prep_inode(&de->d_inode, request, NULL, it);
 
         RETURN(rc);
 }
@@ -421,12 +441,12 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
        if (it->it_op == IT_LOOKUP && !d_lustre_invalid(de))
                 RETURN(1);
 
-        if ((it->it_op == IT_OPEN) && de->d_inode) {
-                struct inode *inode = de->d_inode;
-                struct ll_inode_info *lli = ll_i2info(inode);
-                struct obd_client_handle **och_p;
-                __u64 *och_usecount;
-                __u64 ibits;
+       if (it->it_op == IT_OPEN) {
+               struct inode *inode = de->d_inode;
+               struct ll_inode_info *lli = ll_i2info(inode);
+               struct obd_client_handle **och_p;
+               __u64 *och_usecount;
+               __u64 ibits;
 
                 /*
                  * We used to check for MDS_INODELOCK_OPEN here, but in fact
@@ -453,7 +473,7 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
                 ibits = MDS_INODELOCK_LOOKUP;
                 if (!ll_have_md_lock(inode, &ibits, LCK_MINMODE))
                         goto do_lock;
-                cfs_mutex_lock(&lli->lli_och_mutex);
+               mutex_lock(&lli->lli_och_mutex);
                 if (*och_p) { /* Everything is open already, do nothing */
                         /*(*och_usecount)++;  Do not let them steal our open
                           handle from under us */
@@ -465,10 +485,10 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
                            hope the lock won't be invalidated in between. But
                            if it would be, we'll reopen the open request to
                            MDS later during file open path */
-                        cfs_mutex_unlock(&lli->lli_och_mutex);
+                       mutex_unlock(&lli->lli_och_mutex);
                         RETURN(1);
                 } else {
-                        cfs_mutex_unlock(&lli->lli_och_mutex);
+                       mutex_unlock(&lli->lli_och_mutex);
                 }
         }
 
@@ -487,7 +507,8 @@ do_lock:
         if (IS_ERR(op_data))
                 RETURN(PTR_ERR(op_data));
 
-        it->it_create_mode &= ~cfs_curproc_umask();
+        if (!IS_POSIXACL(parent) || !exp_connect_umask(exp))
+                it->it_create_mode &= ~cfs_curproc_umask();
         it->it_create_mode |= M_CHECK_STALE;
         rc = md_intent_lock(exp, op_data, NULL, 0, it,
                             lookup_flags,
@@ -534,19 +555,39 @@ out:
         if (req != NULL && !it_disposition(it, DISP_ENQ_COMPLETE))
                 ptlrpc_req_finished(req);
         if (rc == 0) {
+               /* mdt may grant layout lock for the newly created file, so
+                * release the lock to avoid leaking */
+               ll_intent_drop_lock(it);
                ll_invalidate_aliases(de->d_inode);
        } else {
                __u64 bits = 0;
+               __u64 matched_bits = 0;
 
                CDEBUG(D_DENTRY, "revalidated dentry %.*s (%p) parent %p "
                       "inode %p refc %d\n", de->d_name.len,
                       de->d_name.name, de, de->d_parent, de->d_inode,
                       d_refcount(de));
+
                ll_set_lock_data(exp, de->d_inode, it, &bits);
-               if ((bits & MDS_INODELOCK_LOOKUP) && d_lustre_invalid(de))
+
+               /* Note: We have to match both LOOKUP and PERM lock
+                * here to make sure the dentry is valid and no one
+                * changing the permission.
+                * But if the client connects < 2.4 server, which will
+                * only grant LOOKUP lock, so we can only Match LOOKUP
+                * lock for old server */
+               if (exp_connect_flags(ll_i2mdexp(de->d_inode)) &&
+                                                       OBD_CONNECT_LVB_TYPE)
+                       matched_bits =
+                               MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM;
+               else
+                       matched_bits = MDS_INODELOCK_LOOKUP;            
+
+               if (((bits & matched_bits) == matched_bits) &&
+                   d_lustre_invalid(de))
                        d_lustre_revalidate(de);
-                ll_lookup_finish_locks(it, de);
-        }
+               ll_lookup_finish_locks(it, de);
+       }
 
 mark:
         if (it != NULL && it->it_op == IT_GETATTR && rc > 0)
@@ -616,6 +657,34 @@ out_sa:
         goto mark;
 }
 
+#ifdef HAVE_IOP_ATOMIC_OPEN
+/*
+ * Always trust cached dentries. Update statahead window if necessary.
+ */
+int ll_revalidate_nd(struct dentry *dentry, unsigned int flags)
+{
+       struct inode *parent = dentry->d_parent->d_inode;
+       int unplug = 0;
+
+       ENTRY;
+       CDEBUG(D_VFSTRACE, "VFS Op:name=%s,flags=%u\n",
+              dentry->d_name.name, flags);
+
+       if (!(flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) &&
+           ll_need_statahead(parent, dentry) > 0) {
+               if (flags & LOOKUP_RCU)
+                       RETURN(-ECHILD);
+
+               if (dentry->d_inode == NULL)
+                       unplug = 1;
+               do_statahead_enter(parent, &dentry, unplug);
+               ll_statahead_mark(parent, dentry);
+       }
+
+       RETURN(1);
+}
+
+#else /* !HAVE_IOP_ATOMIC_OPEN */
 int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
 {
         int rc;
@@ -683,13 +752,14 @@ out_it:
 
         RETURN(rc);
 }
+#endif /* HAVE_IOP_ATOMIC_OPEN */
 
 void ll_d_iput(struct dentry *de, struct inode *inode)
 {
-        LASSERT(inode);
-        if (!find_cbdata(inode))
-                inode->i_nlink = 0;
-        iput(inode);
+       LASSERT(inode);
+       if (!find_cbdata(inode))
+               clear_nlink(inode);
+       iput(inode);
 }
 
 struct dentry_operations ll_d_ops = {