return 0;
}
+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 orig_it, err, 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;
CDEBUG(D_VFSTRACE, "VFS Op:name=%s (%p), intent=%s\n", de->d_name.name,
GOTO(out, rc);
out:
- if (req != NULL && rc == 1)
+ if (req != NULL && rc == 1) {
ptlrpc_req_finished(req);
+ req = NULL;
+ }
if (rc == 0) {
if (it == &lookup_it) {
ll_intent_release(it);
- if (req) /* Special case: We did lookup and it failed,
+ if (req) /* special case: We did lookup and it failed,
need to free request */
ptlrpc_req_finished(req);
}
de->d_flags &= ~DCACHE_LUSTRE_INVALID;
if (it == &lookup_it)
ll_intent_release(it);
-
+
+ /*
+ * 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 (!((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 != NULL) {
- err = ll_gns_mount_object(de, nd->mnt);
- if (err == -ERESTARTSYS) {
- /*
- * making system to restart syscall as currently GNS is
- * in mounting progress.
- */
- return err;
- }
+ return rc;
+
+ /* special "." and ".." has to be always revalidated */
+ if (rc && !ll_special_name(de) && nd != NULL && !(nd->flags & LOOKUP_LAST)) {
+ ll_intent_drop_lock(it);
+ return 0;
}
+
return rc;
do_lookup:
it = &lookup_it;
}
LASSERT(sbi->ll_gns_state == LL_GNS_IDLE);
- spin_lock(&dentry->d_lock);
- dentry->d_flags |= DCACHE_GNS_MOUNTING;
- spin_unlock(&dentry->d_lock);
-
/* mounting started */
sbi->ll_gns_state = LL_GNS_MOUNTING;
spin_unlock(&sbi->ll_gns_lock);
* mount object name is taken from sbi, where it is set in mount time or
* via /proc/fs... tunable. It may be ".mntinfo" or so.
*/
-
- /*
- * FIXME: lookup_one_len() requires dentry->d_inode->i_sem to be locked,
- * but we can't use ll_lookup_one_len() as this function is called from
- * different contol paths and some of them take dentry->d_inode->i_sem
- * and others do not.
- */
dchild = lookup_one_len(sbi->ll_gns_oname, dentry,
strlen(sbi->ll_gns_oname));
up(&sbi->ll_gns_sem);
mntput(mnt);
dput(dentry);
}
- spin_lock(&dentry->d_lock);
- dentry->d_flags &= ~DCACHE_GNS_PENDING;
- spin_unlock(&dentry->d_lock);
} else {
CERROR("usermode upcall %s failed to mount %s, err %d\n",
sbi->ll_gns_upcall, path, rc);
spin_lock(&sbi->ll_gns_lock);
sbi->ll_gns_state = LL_GNS_IDLE;
spin_unlock(&sbi->ll_gns_lock);
-
- spin_lock(&dentry->d_lock);
- dentry->d_flags &= ~DCACHE_GNS_MOUNTING;
- spin_unlock(&dentry->d_lock);
}
return rc;
}
GOTO(cleanup, rc = -EACCES);
/*
- * here was checking for possible GNS mount point to skip their
+ * here was checking for possible GNS mount points to skip their
* open. I removed it as its detection based only on SUID bit is
- * not reliable. Opening such an dirs should not cause any
+ * not reliable. Opening such a dirs should not cause any
* problems, at least tests show that. --umka
*/
}