#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)
{
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
/* 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))
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 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);
+ }
+
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);
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);
+ 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 "
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
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);
}
}
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,
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;
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)
{
- 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 = {