#include "llite_internal.h"
+spinlock_t ll_lookup_lock = SPIN_LOCK_UNLOCKED;
+
/* should NOT be called with the dcache lock, see fs/dcache.c */
-void ll_release(struct dentry *de)
+static void ll_release(struct dentry *de)
{
struct ll_dentry_data *lld;
ENTRY;
OBD_ALLOC_PTR(lld);
if (likely(lld != NULL)) {
- cfs_waitq_init(&lld->lld_waitq);
lock_dentry(de);
if (likely(de->d_fsdata == NULL))
de->d_fsdata = lld;
__d_drop(dentry);
unlock_dentry(dentry);
spin_unlock(&dcache_lock);
+ spin_unlock(&ll_lookup_lock);
dput(dentry);
+ spin_lock(&ll_lookup_lock);
spin_lock(&dcache_lock);
return 1;
}
- /* disconected dentry can not be find without lookup, because we
+ /* disconected dentry can not be find without lookup, because we
* not need his to unhash or mark invalid. */
if (dentry->d_flags & DCACHE_DISCONNECTED) {
unlock_dentry(dentry);
inode->i_ino, inode->i_generation, inode);
head = &inode->i_dentry;
+ spin_lock(&ll_lookup_lock);
spin_lock(&dcache_lock);
restart:
tmp = head;
goto restart;
}
spin_unlock(&dcache_lock);
+ spin_unlock(&ll_lookup_lock);
+
EXIT;
}
if (!request)
RETURN(0);
- if (it_disposition(it, DISP_LOOKUP_NEG))
+ if (it_disposition(it, DISP_LOOKUP_NEG))
RETURN(-ENOENT);
rc = ll_prep_inode(&de->d_inode, request, NULL);
struct lookup_intent *it = *itp;
#ifdef HAVE_VFS_INTENT_PATCHES
if (it) {
- LASSERTF(it->it_magic == INTENT_MAGIC,
+ LASSERTF(it->it_magic == INTENT_MAGIC,
"%p has bad intent magic: %x\n",
it, it->it_magic);
}
GOTO(out_sa, rc);
}
- exp = ll_i2mdexp(de->d_inode);
-
/* Never execute intents for mount points.
* Attributes will be fixed up in ll_inode_revalidate_it */
if (d_mountpoint(de))
GOTO(out_sa, rc = 1);
- /* Root of the lustre tree. Always valid.
- * Attributes will be fixed up in ll_inode_revalidate_it */
- if (de == de->d_sb->s_root)
- GOTO(out_sa, rc = 1);
+ /* need to get attributes in case root got changed from other client */
+ if (de == de->d_sb->s_root) {
+ rc = __ll_inode_revalidate_it(de, it, MDS_INODELOCK_LOOKUP);
+ if (rc == 0)
+ rc = 1;
+ GOTO(out_sa, rc);
+ }
+
+ exp = ll_i2mdexp(de->d_inode);
OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
ll_frob_intent(&it, &lookup_it);
do_lock:
it->it_create_mode &= ~current->fs->umask;
- it->it_flags |= O_CHECK_STALE;
+ it->it_create_mode |= M_CHECK_STALE;
rc = md_intent_lock(exp, op_data, NULL, 0, it,
lookup_flags,
&req, ll_md_blocking_ast, 0);
- it->it_flags &= ~O_CHECK_STALE;
+ it->it_create_mode &= ~M_CHECK_STALE;
ll_finish_md_op_data(op_data);
if (it->it_op == IT_GETATTR && !first)
- ll_statahead_exit(de, rc);
+ /* If there are too many locks on client-side, then some
+ * locks taken by statahead maybe dropped automatically
+ * before the real "revalidate" using them. */
+ ll_statahead_exit(de, req == NULL ? rc : 0);
+ else if (first == -EEXIST)
+ ll_statahead_mark(de);
/* 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. */
if (rc != -ESTALE) {
CDEBUG(D_INFO, "ll_intent_lock: rc %d : it->it_status "
"%d\n", rc, it->d.lustre.it_status);
+ } else {
+#ifndef HAVE_VFS_INTENT_PATCHES
+ if (it_disposition(it, DISP_OPEN_OPEN) &&
+ !it_open_error(DISP_OPEN_OPEN, it))
+ /* server have valid open - close file first*/
+ ll_release_openhandle(de, it);
+#endif
}
GOTO(out, rc = 0);
}
GOTO(out, rc = 0);
}
- if ((it->it_op & IT_OPEN) && de->d_inode &&
- !S_ISREG(de->d_inode->i_mode) &&
+ if ((it->it_op & IT_OPEN) && de->d_inode &&
+ !S_ISREG(de->d_inode->i_mode) &&
!S_ISDIR(de->d_inode->i_mode)) {
ll_release_openhandle(de, it);
}
/* unfortunately ll_intent_lock may cause a callback and revoke our
* dentry */
+ spin_lock(&ll_lookup_lock);
spin_lock(&dcache_lock);
lock_dentry(de);
__d_drop(de);
unlock_dentry(de);
d_rehash_cond(de, 0);
spin_unlock(&dcache_lock);
+ spin_unlock(&ll_lookup_lock);
out:
/* We do not free request as it may be reused during following lookup
if (it && it->it_op == IT_GETATTR && rc == 1) {
first = ll_statahead_enter(de->d_parent->d_inode, &de, 0);
if (!first)
- ll_statahead_exit(de, rc);
+ ll_statahead_exit(de, 1);
+ else if (first == -EEXIST)
+ ll_statahead_mark(de);
}
return rc;
}
#ifdef HAVE_VFS_INTENT_PATCHES
-static int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
+int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
{
int rc;
ENTRY;
(struct ptlrpc_request *)
it->d.lustre.it_data);
} else {
- struct file *filp;
-
- nd->intent.open.file->private_data = it;
- filp = lookup_instantiate_filp(nd, dentry,NULL);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
/* 2.6.1[456] have a bug in open_namei() that forgets to check
* nd->intent.open.file for error, so we need to return it as lookup's result
* instead */
- if (IS_ERR(filp))
- rc = 0;
+ struct file *filp;
+
+ nd->intent.open.file->private_data = it;
+ filp = lookup_instantiate_filp(nd, dentry,NULL);
+ if (IS_ERR(filp)) {
+ rc = PTR_ERR(filp);
+ }
+#else
+ nd->intent.open.file->private_data = it;
+ (void)lookup_instantiate_filp(nd, dentry,NULL);
#endif
}
#else
.d_unpin = ll_unpin,
#endif
};
-
-static int ll_fini_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
-{
- ENTRY;
- /* need lookup */
- RETURN(0);
-}
-
-struct dentry_operations ll_fini_d_ops = {
- .d_revalidate = ll_fini_revalidate_nd,
- .d_release = ll_release,
-};
-
-/*
- * It is for the following race condition:
- * When someone (maybe statahead thread) adds the dentry to the dentry hash
- * table, the dentry's "d_op" maybe NULL, at the same time, another (maybe
- * "ls -l") process finds such dentry by "do_lookup()" without "do_revalidate()"
- * called. It causes statahead window lost, and maybe other issues. --Fan Yong
- */
-static int ll_init_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
-{
- struct l_wait_info lwi = { 0 };
- struct ll_dentry_data *lld;
- ENTRY;
-
- ll_set_dd(dentry);
- lld = ll_d2d(dentry);
- if (unlikely(lld == NULL))
- RETURN(-ENOMEM);
-
- l_wait_event(lld->lld_waitq, dentry->d_op != &ll_init_d_ops, &lwi);
- if (likely(dentry->d_op == &ll_d_ops))
- RETURN(ll_revalidate_nd(dentry, nd));
- else
- RETURN(dentry->d_op == &ll_fini_d_ops ? 0 : -EINVAL);
-}
-
-struct dentry_operations ll_init_d_ops = {
- .d_revalidate = ll_init_revalidate_nd,
- .d_release = ll_release,
-};