Whamcloud - gitweb
- many gcc4 compilation fixes (warnings)
[fs/lustre-release.git] / lustre / llite / dcache.c
index d74dc8b..4c9023e 100644 (file)
@@ -139,15 +139,6 @@ void ll_intent_release(struct lookup_intent *it)
         EXIT;
 }
 
-void ll_intent_free(struct lookup_intent *it)
-{
-        if (it->d.fs_data) {
-                OBD_SLAB_FREE(it->d.fs_data, ll_intent_slab,
-                               sizeof(struct lustre_intent_data));
-                it->d.fs_data = NULL;
-        }
-}
-
 void ll_unhash_aliases(struct inode *inode)
 {
         struct list_head *tmp, *head;
@@ -277,7 +268,7 @@ int ll_intent_alloc(struct lookup_intent *it)
                 return 0;
         }
         OBD_SLAB_ALLOC(it->d.fs_data, ll_intent_slab, SLAB_KERNEL,
-                        sizeof(struct lustre_intent_data));
+                       sizeof(struct lustre_intent_data));
         if (!it->d.fs_data) {
                 CERROR("Failed to allocate memory for lustre specific intent "
                        "data\n");
@@ -285,39 +276,45 @@ int ll_intent_alloc(struct lookup_intent *it)
         }
 
         it->it_op_release = ll_intent_release;
-
         return 0;
 }
 
+void ll_intent_free(struct lookup_intent *it)
+{
+        if (it->d.fs_data) {
+                OBD_SLAB_FREE(it->d.fs_data, ll_intent_slab,
+                              sizeof(struct lustre_intent_data));
+                it->d.fs_data = NULL;
+        }
+}
+
+static inline int 
+ll_special_name(struct dentry *de)
+{
+       if (de->d_name.name[0] == '.') switch (de->d_name.len) {
+               case 2:
+                       if (de->d_name.name[1] == '.')
+                               return 1;
+               case 1:
+                       return 1;
+               default:
+                       return 0;
+       }
+       return 0;
+}
+
 int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd,
                      struct lookup_intent *it)
 {
         struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
         struct ptlrpc_request *req = NULL;
+        int gns_it, gns_flags, rc = 0;
         struct obd_export *exp;
         struct it_cb_data icbd;
         struct lustre_id pid;
         struct lustre_id cid;
-        int orig_it, rc = 0;
         ENTRY;
 
-        spin_lock(&de->d_lock);
-
-        if ((de->d_flags & DCACHE_GNS_PENDING) &&
-            !(de->d_flags & DCACHE_GNS_MOUNTING))
-        {
-                spin_unlock(&de->d_lock);
-                        
-                if (nd) {
-                        int err = ll_gns_mount_object(de, nd->mnt);
-                        if (err)
-                                CERROR("can't mount %s, err = %d\n",
-                                       de->d_name.name, err);
-                }
-                RETURN(1);
-        }
-        spin_unlock(&de->d_lock);
-
         CDEBUG(D_VFSTRACE, "VFS Op:name=%s (%p), intent=%s\n", de->d_name.name,
                de, LL_IT2STR(it));
 
@@ -325,8 +322,10 @@ int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd,
         if (de->d_inode == NULL)
                 RETURN(0);
 
-        /* Root of the tree is always valid, attributes would be fixed in
-          ll_inode_revalidate_it */
+        /*
+         * root of the tree is always valid, attributes would be fixed in
+         * ll_inode_revalidate_it()
+         */
         if (de->d_sb->s_root == de)
                 RETURN(1);
 
@@ -354,45 +353,13 @@ int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd,
                 nd->mnt->mnt_last_used = jiffies;
 
         OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
-        orig_it = it ? it->it_op : IT_OPEN;
-        ll_frob_intent(&it, &lookup_it);
-        LASSERT(it != NULL);
-
-        if (it->it_op == IT_GETATTR) { /* We need to check for LOOKUP lock as
-                                          well */
-                rc = ll_intent_alloc(&lookup_it);
-                if (rc)
-                        LBUG(); /* Can't think of better idea just yet */
-
-                rc = md_intent_lock(exp, &pid, de->d_name.name,
-                                    de->d_name.len, NULL, 0, &cid, &lookup_it,
-                                    flags, &req, ll_mdc_blocking_ast);
-                /* If there was no lookup lock, no point in even checking for
-                   UPDATE lock */
-                if (!rc) {
-                        it = &lookup_it;
-                        if (!req) {
-                                ll_intent_free(it);
-                                goto do_lookup;
-                        }
-                        GOTO(out, rc);
-                }
-                if (it_disposition(&lookup_it, DISP_LOOKUP_NEG)) {
-                        it = &lookup_it;
-                        ll_intent_free(it);
-                        GOTO(out, rc = 0);
-                }
-
-                if (req)
-                        ptlrpc_req_finished(req);
-                req = NULL;
-                ll_lookup_finish_locks(&lookup_it, de);
-                /* XXX: on 2.6 ll_lookup_finish_locks does not call ll_intent_release */
-                ll_intent_release(&lookup_it);
-        }
+        gns_it = nd ? nd->intent.open.it_op : IT_OPEN;
+        gns_flags = nd ? nd->flags : LOOKUP_CONTINUE;
 
-#if 1
-        if ((it->it_op == IT_OPEN) && de->d_inode) {
+        if (it && it->it_op == IT_GETATTR)
+                it = NULL; /* will use it_lookup */
+        else if (it && (it->it_op == IT_OPEN) && de->d_inode) {
+                /* open lock stuff */
                 struct inode *inode = de->d_inode;
                 struct ll_inode_info *lli = ll_i2info(inode);
                 struct obd_client_handle **och_p;
@@ -436,9 +403,17 @@ int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd,
                            if it would be, we'll reopen the open request to
                            MDS later during file open path */
                         up(&lli->lli_och_sem);
+                        if (ll_intent_alloc(it))
+                                LBUG();
                         memcpy(&LUSTRE_IT(it)->it_lock_handle, &lockh,
                                sizeof(lockh));
                         LUSTRE_IT(it)->it_lock_mode = lockmode;
+
+                        /* 
+                         * we do not check here for possible GNS dentry as if
+                         * file is opened on it, it is mounted already and we do
+                         * not need do anything. --umka
+                         */
                         RETURN(1);
                 } else {
                         /* Hm, interesting. Lock is present, but no open
@@ -447,10 +422,12 @@ int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd,
                         ldlm_lock_decref(&lockh, lockmode);
                 }
         }
-#endif
 
 do_lock:
-        rc = md_intent_lock(exp, &pid, de->d_name.name, de->d_name.len,
+        ll_frob_intent(&it, &lookup_it);
+        LASSERT(it != NULL);
+
+        rc = md_intent_lock(exp, &pid, (char *)de->d_name.name, de->d_name.len,
                             NULL, 0, &cid, it, flags, &req, ll_mdc_blocking_ast);
         /* If req is NULL, then md_intent_lock() only tried to do a lock match;
          * if all was well, it will return 1 if it found locks, 0 otherwise. */
@@ -484,18 +461,51 @@ revalidate_finish:
 
         GOTO(out, rc);
 out:
-        if (req != NULL && rc == 1)
+        /* If we had succesful it lookup on mds, but it happened to be negative,
+           we do not free request as it will be reused during lookup (see
+           comment in mdc/mdc_locks.c::mdc_intent_lock(). But if
+           request was not completed, we need to free it. (bug 5154) */
+        if (req != NULL && (rc == 1 || !it_disposition(it, DISP_ENQ_COMPLETE))) {
                 ptlrpc_req_finished(req);
+                req = NULL;
+        }
 
         if (rc == 0) {
-                if (it == &lookup_it) {
+                if (it == &lookup_it)
                         ll_intent_release(it);
-                        if (req) /* Special case: We did lookup and it failed,
-                                    need to free request */
-                                ptlrpc_req_finished(req);
-                }
+
                 ll_unhash_aliases(de->d_inode);
-                return 0;
+                RETURN(0);
+        }
+
+        /* 
+         * if we found that this is possible GNS mount and dentry is still valid
+         * and may be used by system, we drop the lock and return 0, that means
+         * that re-lookup is needed. Such a way we cause real mounting only in
+         * lookup control path, which is always made with parent's i_sem taken.
+         * --umka
+         */
+        if (nd && atomic_read(&ll_i2sbi(de->d_inode)->ll_gns_enabled) &&
+            (de->d_inode->i_mode & S_ISUID) && S_ISDIR(de->d_inode->i_mode) &&
+            (gns_flags & LOOKUP_CONTINUE || (gns_it & (IT_CHDIR | IT_OPEN)))) {
+                /* 
+                 * special "." and ".." has to be always revalidated because
+                 * they never should be passed to lookup()
+                 */
+                if (!ll_special_name(de)) {
+                        CDEBUG(D_DENTRY, "possible GNS dentry %*s %p found, "
+                               "causing mounting\n", (int)de->d_name.len,
+                               de->d_name.name, de);
+                        
+                        LASSERT(req == NULL);
+                        if (it == &lookup_it) {
+                                ll_intent_release(it);
+                        } else {
+                                ll_intent_drop_lock(it);
+                        }
+                        ll_unhash_aliases(de->d_inode);
+                        RETURN(0);
+                }
         }
 
         CDEBUG(D_DENTRY, "revalidated dentry %*s (%p) parent %p "
@@ -503,34 +513,29 @@ out:
                de->d_name.name, de, de->d_parent, de->d_inode,
                atomic_read(&de->d_count));
 
-        ll_lookup_finish_locks(it, de);
-        de->d_flags &= ~DCACHE_LUSTRE_INVALID;
         if (it == &lookup_it)
                 ll_intent_release(it);
-    
-        if (!((de->d_inode->i_mode & S_ISUID) && S_ISDIR(de->d_inode->i_mode)) ||
-            !(flags & LOOKUP_CONTINUE || (orig_it & (IT_CHDIR | IT_OPEN))))
-                return rc;
-
-        if (nd && !(de->d_flags & DCACHE_GNS_MOUNTING)) {
-                int err = ll_gns_mount_object(de, nd->mnt);
-                if (err)
-                        CERROR("can't mount %s, err = %d\n",
-                               de->d_name.name, err);
-        }
+        else
+                ll_lookup_finish_locks(it, de);
+
+        de->d_flags &= ~DCACHE_LUSTRE_INVALID;
         return rc;
+
 do_lookup:
-        it = &lookup_it;
-        if (ll_intent_alloc(it))
-                LBUG();
-// We did that already, right?  ll_inode2id(&pid, de->d_parent->d_inode);
-        rc = md_intent_lock(exp, &pid, de->d_name.name,
-                            de->d_name.len, NULL, 0, NULL,
-                            it, 0, &req, ll_mdc_blocking_ast);
+        if (it != &lookup_it) {
+                ll_intent_release(it);
+                it = &lookup_it;
+                if (ll_intent_alloc(it))
+                        LBUG();
+        }
+        
+        rc = md_intent_lock(exp, &pid, (char *)de->d_name.name, de->d_name.len,
+                            NULL, 0, NULL, it, 0, &req, ll_mdc_blocking_ast);
         if (rc >= 0) {
-                struct mds_body *mds_body = lustre_msg_buf(req->rq_repmsg, 1, sizeof(*mds_body));
+                struct mds_body *mds_body = lustre_msg_buf(req->rq_repmsg, 1,
+                                                           sizeof(*mds_body));
 
-                /* See if we got same inode, if not - return error */
+                /* see if we got same inode, if not - return error */
                 if (id_equal_stc(&cid, &mds_body->id1))
                         goto revalidate_finish;
         }
@@ -679,7 +684,7 @@ struct dentry_operations ll_d_ops = {
         .d_revalidate_it = ll_revalidate_it,
 #endif
         .d_release = ll_release,
-        .d_iput = ll_dentry_iput,
+        /*.d_iput = ll_dentry_iput,*/
         .d_delete = ll_ddelete,
         .d_compare = ll_dcompare,
 #if 0