* 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/
/* 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 */
void ll_intent_drop_lock(struct lookup_intent *it)
{
- struct lustre_handle *handle;
-
if (it->it_op && it->d.lustre.it_lock_mode) {
- struct ldlm_lock *lock;
-
- handle = (struct lustre_handle *)&it->d.lustre.it_lock_handle;
- lock = ldlm_handle2lock(handle);
- if (lock != NULL) {
- /* it can only be allowed to match after layout is
- * applied to inode otherwise false layout would be
- * seen. Applying layout shoud happen before dropping
- * the intent lock. */
- if (it->d.lustre.it_lock_bits & MDS_INODELOCK_LAYOUT)
- ldlm_lock_allow_match(lock);
- LDLM_LOCK_PUT(lock);
- }
+ 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)
void ll_invalidate_aliases(struct inode *inode)
{
struct dentry *dentry;
+ struct ll_d_hlist_node *p;
ENTRY;
LASSERT(inode != NULL);
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);
-
- if (dentry->d_name.len == 1 && dentry->d_name.name[0] == '/') {
- CERROR("called on root (?) dentry=%p, inode=%p "
- "ino=%lu\n", dentry, inode, inode->i_ino);
- lustre_dump_dentry(dentry, 1);
+ 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 (unlikely(dentry == dentry->d_sb->s_root)) {
+ CERROR("%s: called on root dentry=%p, fid="DFID"\n",
+ ll_get_fsname(dentry->d_sb, NULL, 0),
+ dentry, PFID(ll_inode2fid(inode)));
+ lustre_dump_dentry(dentry, 1);
libcfs_debug_dumpstack(NULL);
}
- d_lustre_invalidate(dentry);
+ d_lustre_invalidate(dentry, 0);
}
ll_unlock_dcache(inode);
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);
}
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 */
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);
}
}
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)
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;
RETURN(rc);
}
+#endif /* HAVE_IOP_ATOMIC_OPEN */
void ll_d_iput(struct dentry *de, struct inode *inode)
{