162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * dcache.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * dentry cache handling code
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/fs.h>
1162306a36Sopenharmony_ci#include <linux/types.h>
1262306a36Sopenharmony_ci#include <linux/slab.h>
1362306a36Sopenharmony_ci#include <linux/namei.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <cluster/masklog.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "ocfs2.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "alloc.h"
2062306a36Sopenharmony_ci#include "dcache.h"
2162306a36Sopenharmony_ci#include "dlmglue.h"
2262306a36Sopenharmony_ci#include "file.h"
2362306a36Sopenharmony_ci#include "inode.h"
2462306a36Sopenharmony_ci#include "ocfs2_trace.h"
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_civoid ocfs2_dentry_attach_gen(struct dentry *dentry)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	unsigned long gen =
2962306a36Sopenharmony_ci		OCFS2_I(d_inode(dentry->d_parent))->ip_dir_lock_gen;
3062306a36Sopenharmony_ci	BUG_ON(d_inode(dentry));
3162306a36Sopenharmony_ci	dentry->d_fsdata = (void *)gen;
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	struct inode *inode;
3862306a36Sopenharmony_ci	int ret = 0;    /* if all else fails, just return false */
3962306a36Sopenharmony_ci	struct ocfs2_super *osb;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (flags & LOOKUP_RCU)
4262306a36Sopenharmony_ci		return -ECHILD;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	inode = d_inode(dentry);
4562306a36Sopenharmony_ci	osb = OCFS2_SB(dentry->d_sb);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	trace_ocfs2_dentry_revalidate(dentry, dentry->d_name.len,
4862306a36Sopenharmony_ci				      dentry->d_name.name);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	/* For a negative dentry -
5162306a36Sopenharmony_ci	 * check the generation number of the parent and compare with the
5262306a36Sopenharmony_ci	 * one stored in the inode.
5362306a36Sopenharmony_ci	 */
5462306a36Sopenharmony_ci	if (inode == NULL) {
5562306a36Sopenharmony_ci		unsigned long gen = (unsigned long) dentry->d_fsdata;
5662306a36Sopenharmony_ci		unsigned long pgen;
5762306a36Sopenharmony_ci		spin_lock(&dentry->d_lock);
5862306a36Sopenharmony_ci		pgen = OCFS2_I(d_inode(dentry->d_parent))->ip_dir_lock_gen;
5962306a36Sopenharmony_ci		spin_unlock(&dentry->d_lock);
6062306a36Sopenharmony_ci		trace_ocfs2_dentry_revalidate_negative(dentry->d_name.len,
6162306a36Sopenharmony_ci						       dentry->d_name.name,
6262306a36Sopenharmony_ci						       pgen, gen);
6362306a36Sopenharmony_ci		if (gen != pgen)
6462306a36Sopenharmony_ci			goto bail;
6562306a36Sopenharmony_ci		goto valid;
6662306a36Sopenharmony_ci	}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	BUG_ON(!osb);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	if (inode == osb->root_inode || is_bad_inode(inode))
7162306a36Sopenharmony_ci		goto bail;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	spin_lock(&OCFS2_I(inode)->ip_lock);
7462306a36Sopenharmony_ci	/* did we or someone else delete this inode? */
7562306a36Sopenharmony_ci	if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {
7662306a36Sopenharmony_ci		spin_unlock(&OCFS2_I(inode)->ip_lock);
7762306a36Sopenharmony_ci		trace_ocfs2_dentry_revalidate_delete(
7862306a36Sopenharmony_ci				(unsigned long long)OCFS2_I(inode)->ip_blkno);
7962306a36Sopenharmony_ci		goto bail;
8062306a36Sopenharmony_ci	}
8162306a36Sopenharmony_ci	spin_unlock(&OCFS2_I(inode)->ip_lock);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	/*
8462306a36Sopenharmony_ci	 * We don't need a cluster lock to test this because once an
8562306a36Sopenharmony_ci	 * inode nlink hits zero, it never goes back.
8662306a36Sopenharmony_ci	 */
8762306a36Sopenharmony_ci	if (inode->i_nlink == 0) {
8862306a36Sopenharmony_ci		trace_ocfs2_dentry_revalidate_orphaned(
8962306a36Sopenharmony_ci			(unsigned long long)OCFS2_I(inode)->ip_blkno,
9062306a36Sopenharmony_ci			S_ISDIR(inode->i_mode));
9162306a36Sopenharmony_ci		goto bail;
9262306a36Sopenharmony_ci	}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	/*
9562306a36Sopenharmony_ci	 * If the last lookup failed to create dentry lock, let us
9662306a36Sopenharmony_ci	 * redo it.
9762306a36Sopenharmony_ci	 */
9862306a36Sopenharmony_ci	if (!dentry->d_fsdata) {
9962306a36Sopenharmony_ci		trace_ocfs2_dentry_revalidate_nofsdata(
10062306a36Sopenharmony_ci				(unsigned long long)OCFS2_I(inode)->ip_blkno);
10162306a36Sopenharmony_ci		goto bail;
10262306a36Sopenharmony_ci	}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_civalid:
10562306a36Sopenharmony_ci	ret = 1;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cibail:
10862306a36Sopenharmony_ci	trace_ocfs2_dentry_revalidate_ret(ret);
10962306a36Sopenharmony_ci	return ret;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic int ocfs2_match_dentry(struct dentry *dentry,
11362306a36Sopenharmony_ci			      u64 parent_blkno,
11462306a36Sopenharmony_ci			      int skip_unhashed)
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	struct inode *parent;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	/*
11962306a36Sopenharmony_ci	 * ocfs2_lookup() does a d_splice_alias() _before_ attaching
12062306a36Sopenharmony_ci	 * to the lock data, so we skip those here, otherwise
12162306a36Sopenharmony_ci	 * ocfs2_dentry_attach_lock() will get its original dentry
12262306a36Sopenharmony_ci	 * back.
12362306a36Sopenharmony_ci	 */
12462306a36Sopenharmony_ci	if (!dentry->d_fsdata)
12562306a36Sopenharmony_ci		return 0;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (!dentry->d_parent)
12862306a36Sopenharmony_ci		return 0;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	if (skip_unhashed && d_unhashed(dentry))
13162306a36Sopenharmony_ci		return 0;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	parent = d_inode(dentry->d_parent);
13462306a36Sopenharmony_ci	/* Negative parent dentry? */
13562306a36Sopenharmony_ci	if (!parent)
13662306a36Sopenharmony_ci		return 0;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	/* Name is in a different directory. */
13962306a36Sopenharmony_ci	if (OCFS2_I(parent)->ip_blkno != parent_blkno)
14062306a36Sopenharmony_ci		return 0;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	return 1;
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/*
14662306a36Sopenharmony_ci * Walk the inode alias list, and find a dentry which has a given
14762306a36Sopenharmony_ci * parent. ocfs2_dentry_attach_lock() wants to find _any_ alias as it
14862306a36Sopenharmony_ci * is looking for a dentry_lock reference. The downconvert thread is
14962306a36Sopenharmony_ci * looking to unhash aliases, so we allow it to skip any that already
15062306a36Sopenharmony_ci * have that property.
15162306a36Sopenharmony_ci */
15262306a36Sopenharmony_cistruct dentry *ocfs2_find_local_alias(struct inode *inode,
15362306a36Sopenharmony_ci				      u64 parent_blkno,
15462306a36Sopenharmony_ci				      int skip_unhashed)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	struct dentry *dentry;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	spin_lock(&inode->i_lock);
15962306a36Sopenharmony_ci	hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
16062306a36Sopenharmony_ci		spin_lock(&dentry->d_lock);
16162306a36Sopenharmony_ci		if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
16262306a36Sopenharmony_ci			trace_ocfs2_find_local_alias(dentry->d_name.len,
16362306a36Sopenharmony_ci						     dentry->d_name.name);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci			dget_dlock(dentry);
16662306a36Sopenharmony_ci			spin_unlock(&dentry->d_lock);
16762306a36Sopenharmony_ci			spin_unlock(&inode->i_lock);
16862306a36Sopenharmony_ci			return dentry;
16962306a36Sopenharmony_ci		}
17062306a36Sopenharmony_ci		spin_unlock(&dentry->d_lock);
17162306a36Sopenharmony_ci	}
17262306a36Sopenharmony_ci	spin_unlock(&inode->i_lock);
17362306a36Sopenharmony_ci	return NULL;
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ciDEFINE_SPINLOCK(dentry_attach_lock);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci/*
17962306a36Sopenharmony_ci * Attach this dentry to a cluster lock.
18062306a36Sopenharmony_ci *
18162306a36Sopenharmony_ci * Dentry locks cover all links in a given directory to a particular
18262306a36Sopenharmony_ci * inode. We do this so that ocfs2 can build a lock name which all
18362306a36Sopenharmony_ci * nodes in the cluster can agree on at all times. Shoving full names
18462306a36Sopenharmony_ci * in the cluster lock won't work due to size restrictions. Covering
18562306a36Sopenharmony_ci * links inside of a directory is a good compromise because it still
18662306a36Sopenharmony_ci * allows us to use the parent directory lock to synchronize
18762306a36Sopenharmony_ci * operations.
18862306a36Sopenharmony_ci *
18962306a36Sopenharmony_ci * Call this function with the parent dir semaphore and the parent dir
19062306a36Sopenharmony_ci * cluster lock held.
19162306a36Sopenharmony_ci *
19262306a36Sopenharmony_ci * The dir semaphore will protect us from having to worry about
19362306a36Sopenharmony_ci * concurrent processes on our node trying to attach a lock at the
19462306a36Sopenharmony_ci * same time.
19562306a36Sopenharmony_ci *
19662306a36Sopenharmony_ci * The dir cluster lock (held at either PR or EX mode) protects us
19762306a36Sopenharmony_ci * from unlink and rename on other nodes.
19862306a36Sopenharmony_ci *
19962306a36Sopenharmony_ci * A dput() can happen asynchronously due to pruning, so we cover
20062306a36Sopenharmony_ci * attaching and detaching the dentry lock with a
20162306a36Sopenharmony_ci * dentry_attach_lock.
20262306a36Sopenharmony_ci *
20362306a36Sopenharmony_ci * A node which has done lookup on a name retains a protected read
20462306a36Sopenharmony_ci * lock until final dput. If the user requests and unlink or rename,
20562306a36Sopenharmony_ci * the protected read is upgraded to an exclusive lock. Other nodes
20662306a36Sopenharmony_ci * who have seen the dentry will then be informed that they need to
20762306a36Sopenharmony_ci * downgrade their lock, which will involve d_delete on the
20862306a36Sopenharmony_ci * dentry. This happens in ocfs2_dentry_convert_worker().
20962306a36Sopenharmony_ci */
21062306a36Sopenharmony_ciint ocfs2_dentry_attach_lock(struct dentry *dentry,
21162306a36Sopenharmony_ci			     struct inode *inode,
21262306a36Sopenharmony_ci			     u64 parent_blkno)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	int ret;
21562306a36Sopenharmony_ci	struct dentry *alias;
21662306a36Sopenharmony_ci	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	trace_ocfs2_dentry_attach_lock(dentry->d_name.len, dentry->d_name.name,
21962306a36Sopenharmony_ci				       (unsigned long long)parent_blkno, dl);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	/*
22262306a36Sopenharmony_ci	 * Negative dentry. We ignore these for now.
22362306a36Sopenharmony_ci	 *
22462306a36Sopenharmony_ci	 * XXX: Could we can improve ocfs2_dentry_revalidate() by
22562306a36Sopenharmony_ci	 * tracking these?
22662306a36Sopenharmony_ci	 */
22762306a36Sopenharmony_ci	if (!inode)
22862306a36Sopenharmony_ci		return 0;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	if (d_really_is_negative(dentry) && dentry->d_fsdata) {
23162306a36Sopenharmony_ci		/* Converting a negative dentry to positive
23262306a36Sopenharmony_ci		   Clear dentry->d_fsdata */
23362306a36Sopenharmony_ci		dentry->d_fsdata = dl = NULL;
23462306a36Sopenharmony_ci	}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	if (dl) {
23762306a36Sopenharmony_ci		mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno,
23862306a36Sopenharmony_ci				" \"%pd\": old parent: %llu, new: %llu\n",
23962306a36Sopenharmony_ci				dentry,
24062306a36Sopenharmony_ci				(unsigned long long)parent_blkno,
24162306a36Sopenharmony_ci				(unsigned long long)dl->dl_parent_blkno);
24262306a36Sopenharmony_ci		return 0;
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	alias = ocfs2_find_local_alias(inode, parent_blkno, 0);
24662306a36Sopenharmony_ci	if (alias) {
24762306a36Sopenharmony_ci		/*
24862306a36Sopenharmony_ci		 * Great, an alias exists, which means we must have a
24962306a36Sopenharmony_ci		 * dentry lock already. We can just grab the lock off
25062306a36Sopenharmony_ci		 * the alias and add it to the list.
25162306a36Sopenharmony_ci		 *
25262306a36Sopenharmony_ci		 * We're depending here on the fact that this dentry
25362306a36Sopenharmony_ci		 * was found and exists in the dcache and so must have
25462306a36Sopenharmony_ci		 * a reference to the dentry_lock because we can't
25562306a36Sopenharmony_ci		 * race creates. Final dput() cannot happen on it
25662306a36Sopenharmony_ci		 * since we have it pinned, so our reference is safe.
25762306a36Sopenharmony_ci		 */
25862306a36Sopenharmony_ci		dl = alias->d_fsdata;
25962306a36Sopenharmony_ci		mlog_bug_on_msg(!dl, "parent %llu, ino %llu\n",
26062306a36Sopenharmony_ci				(unsigned long long)parent_blkno,
26162306a36Sopenharmony_ci				(unsigned long long)OCFS2_I(inode)->ip_blkno);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci		mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno,
26462306a36Sopenharmony_ci				" \"%pd\": old parent: %llu, new: %llu\n",
26562306a36Sopenharmony_ci				dentry,
26662306a36Sopenharmony_ci				(unsigned long long)parent_blkno,
26762306a36Sopenharmony_ci				(unsigned long long)dl->dl_parent_blkno);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci		trace_ocfs2_dentry_attach_lock_found(dl->dl_lockres.l_name,
27062306a36Sopenharmony_ci				(unsigned long long)parent_blkno,
27162306a36Sopenharmony_ci				(unsigned long long)OCFS2_I(inode)->ip_blkno);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci		goto out_attach;
27462306a36Sopenharmony_ci	}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	/*
27762306a36Sopenharmony_ci	 * There are no other aliases
27862306a36Sopenharmony_ci	 */
27962306a36Sopenharmony_ci	dl = kmalloc(sizeof(*dl), GFP_NOFS);
28062306a36Sopenharmony_ci	if (!dl) {
28162306a36Sopenharmony_ci		ret = -ENOMEM;
28262306a36Sopenharmony_ci		mlog_errno(ret);
28362306a36Sopenharmony_ci		return ret;
28462306a36Sopenharmony_ci	}
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	dl->dl_count = 0;
28762306a36Sopenharmony_ci	/*
28862306a36Sopenharmony_ci	 * Does this have to happen below, for all attaches, in case
28962306a36Sopenharmony_ci	 * the struct inode gets blown away by the downconvert thread?
29062306a36Sopenharmony_ci	 */
29162306a36Sopenharmony_ci	dl->dl_inode = igrab(inode);
29262306a36Sopenharmony_ci	dl->dl_parent_blkno = parent_blkno;
29362306a36Sopenharmony_ci	ocfs2_dentry_lock_res_init(dl, parent_blkno, inode);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ciout_attach:
29662306a36Sopenharmony_ci	spin_lock(&dentry_attach_lock);
29762306a36Sopenharmony_ci	if (unlikely(dentry->d_fsdata && !alias)) {
29862306a36Sopenharmony_ci		/* d_fsdata is set by a racing thread which is doing
29962306a36Sopenharmony_ci		 * the same thing as this thread is doing. Leave the racing
30062306a36Sopenharmony_ci		 * thread going ahead and we return here.
30162306a36Sopenharmony_ci		 */
30262306a36Sopenharmony_ci		spin_unlock(&dentry_attach_lock);
30362306a36Sopenharmony_ci		iput(dl->dl_inode);
30462306a36Sopenharmony_ci		ocfs2_lock_res_free(&dl->dl_lockres);
30562306a36Sopenharmony_ci		kfree(dl);
30662306a36Sopenharmony_ci		return 0;
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	dentry->d_fsdata = dl;
31062306a36Sopenharmony_ci	dl->dl_count++;
31162306a36Sopenharmony_ci	spin_unlock(&dentry_attach_lock);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	/*
31462306a36Sopenharmony_ci	 * This actually gets us our PRMODE level lock. From now on,
31562306a36Sopenharmony_ci	 * we'll have a notification if one of these names is
31662306a36Sopenharmony_ci	 * destroyed on another node.
31762306a36Sopenharmony_ci	 */
31862306a36Sopenharmony_ci	ret = ocfs2_dentry_lock(dentry, 0);
31962306a36Sopenharmony_ci	if (!ret)
32062306a36Sopenharmony_ci		ocfs2_dentry_unlock(dentry, 0);
32162306a36Sopenharmony_ci	else
32262306a36Sopenharmony_ci		mlog_errno(ret);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	/*
32562306a36Sopenharmony_ci	 * In case of error, manually free the allocation and do the iput().
32662306a36Sopenharmony_ci	 * We need to do this because error here means no d_instantiate(),
32762306a36Sopenharmony_ci	 * which means iput() will not be called during dput(dentry).
32862306a36Sopenharmony_ci	 */
32962306a36Sopenharmony_ci	if (ret < 0 && !alias) {
33062306a36Sopenharmony_ci		ocfs2_lock_res_free(&dl->dl_lockres);
33162306a36Sopenharmony_ci		BUG_ON(dl->dl_count != 1);
33262306a36Sopenharmony_ci		spin_lock(&dentry_attach_lock);
33362306a36Sopenharmony_ci		dentry->d_fsdata = NULL;
33462306a36Sopenharmony_ci		spin_unlock(&dentry_attach_lock);
33562306a36Sopenharmony_ci		kfree(dl);
33662306a36Sopenharmony_ci		iput(inode);
33762306a36Sopenharmony_ci	}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	dput(alias);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	return ret;
34262306a36Sopenharmony_ci}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci/*
34562306a36Sopenharmony_ci * ocfs2_dentry_iput() and friends.
34662306a36Sopenharmony_ci *
34762306a36Sopenharmony_ci * At this point, our particular dentry is detached from the inodes
34862306a36Sopenharmony_ci * alias list, so there's no way that the locking code can find it.
34962306a36Sopenharmony_ci *
35062306a36Sopenharmony_ci * The interesting stuff happens when we determine that our lock needs
35162306a36Sopenharmony_ci * to go away because this is the last subdir alias in the
35262306a36Sopenharmony_ci * system. This function needs to handle a couple things:
35362306a36Sopenharmony_ci *
35462306a36Sopenharmony_ci * 1) Synchronizing lock shutdown with the downconvert threads. This
35562306a36Sopenharmony_ci *    is already handled for us via the lockres release drop function
35662306a36Sopenharmony_ci *    called in ocfs2_release_dentry_lock()
35762306a36Sopenharmony_ci *
35862306a36Sopenharmony_ci * 2) A race may occur when we're doing our lock shutdown and
35962306a36Sopenharmony_ci *    another process wants to create a new dentry lock. Right now we
36062306a36Sopenharmony_ci *    let them race, which means that for a very short while, this
36162306a36Sopenharmony_ci *    node might have two locks on a lock resource. This should be a
36262306a36Sopenharmony_ci *    problem though because one of them is in the process of being
36362306a36Sopenharmony_ci *    thrown out.
36462306a36Sopenharmony_ci */
36562306a36Sopenharmony_cistatic void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
36662306a36Sopenharmony_ci				   struct ocfs2_dentry_lock *dl)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	iput(dl->dl_inode);
36962306a36Sopenharmony_ci	ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
37062306a36Sopenharmony_ci	ocfs2_lock_res_free(&dl->dl_lockres);
37162306a36Sopenharmony_ci	kfree(dl);
37262306a36Sopenharmony_ci}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_civoid ocfs2_dentry_lock_put(struct ocfs2_super *osb,
37562306a36Sopenharmony_ci			   struct ocfs2_dentry_lock *dl)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	int unlock = 0;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	BUG_ON(dl->dl_count == 0);
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	spin_lock(&dentry_attach_lock);
38262306a36Sopenharmony_ci	dl->dl_count--;
38362306a36Sopenharmony_ci	unlock = !dl->dl_count;
38462306a36Sopenharmony_ci	spin_unlock(&dentry_attach_lock);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	if (unlock)
38762306a36Sopenharmony_ci		ocfs2_drop_dentry_lock(osb, dl);
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_cistatic void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode)
39162306a36Sopenharmony_ci{
39262306a36Sopenharmony_ci	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	if (!dl) {
39562306a36Sopenharmony_ci		/*
39662306a36Sopenharmony_ci		 * No dentry lock is ok if we're disconnected or
39762306a36Sopenharmony_ci		 * unhashed.
39862306a36Sopenharmony_ci		 */
39962306a36Sopenharmony_ci		if (!(dentry->d_flags & DCACHE_DISCONNECTED) &&
40062306a36Sopenharmony_ci		    !d_unhashed(dentry)) {
40162306a36Sopenharmony_ci			unsigned long long ino = 0ULL;
40262306a36Sopenharmony_ci			if (inode)
40362306a36Sopenharmony_ci				ino = (unsigned long long)OCFS2_I(inode)->ip_blkno;
40462306a36Sopenharmony_ci			mlog(ML_ERROR, "Dentry is missing cluster lock. "
40562306a36Sopenharmony_ci			     "inode: %llu, d_flags: 0x%x, d_name: %pd\n",
40662306a36Sopenharmony_ci			     ino, dentry->d_flags, dentry);
40762306a36Sopenharmony_ci		}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci		goto out;
41062306a36Sopenharmony_ci	}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	mlog_bug_on_msg(dl->dl_count == 0, "dentry: %pd, count: %u\n",
41362306a36Sopenharmony_ci			dentry, dl->dl_count);
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	ocfs2_dentry_lock_put(OCFS2_SB(dentry->d_sb), dl);
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ciout:
41862306a36Sopenharmony_ci	iput(inode);
41962306a36Sopenharmony_ci}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci/*
42262306a36Sopenharmony_ci * d_move(), but keep the locks in sync.
42362306a36Sopenharmony_ci *
42462306a36Sopenharmony_ci * When we are done, "dentry" will have the parent dir and name of
42562306a36Sopenharmony_ci * "target", which will be thrown away.
42662306a36Sopenharmony_ci *
42762306a36Sopenharmony_ci * We manually update the lock of "dentry" if need be.
42862306a36Sopenharmony_ci *
42962306a36Sopenharmony_ci * "target" doesn't have it's dentry lock touched - we allow the later
43062306a36Sopenharmony_ci * dput() to handle this for us.
43162306a36Sopenharmony_ci *
43262306a36Sopenharmony_ci * This is called during ocfs2_rename(), while holding parent
43362306a36Sopenharmony_ci * directory locks. The dentries have already been deleted on other
43462306a36Sopenharmony_ci * nodes via ocfs2_remote_dentry_delete().
43562306a36Sopenharmony_ci *
43662306a36Sopenharmony_ci * Normally, the VFS handles the d_move() for the file system, after
43762306a36Sopenharmony_ci * the ->rename() callback. OCFS2 wants to handle this internally, so
43862306a36Sopenharmony_ci * the new lock can be created atomically with respect to the cluster.
43962306a36Sopenharmony_ci */
44062306a36Sopenharmony_civoid ocfs2_dentry_move(struct dentry *dentry, struct dentry *target,
44162306a36Sopenharmony_ci		       struct inode *old_dir, struct inode *new_dir)
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	int ret;
44462306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(old_dir->i_sb);
44562306a36Sopenharmony_ci	struct inode *inode = d_inode(dentry);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	/*
44862306a36Sopenharmony_ci	 * Move within the same directory, so the actual lock info won't
44962306a36Sopenharmony_ci	 * change.
45062306a36Sopenharmony_ci	 *
45162306a36Sopenharmony_ci	 * XXX: Is there any advantage to dropping the lock here?
45262306a36Sopenharmony_ci	 */
45362306a36Sopenharmony_ci	if (old_dir == new_dir)
45462306a36Sopenharmony_ci		goto out_move;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	ocfs2_dentry_lock_put(osb, dentry->d_fsdata);
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	dentry->d_fsdata = NULL;
45962306a36Sopenharmony_ci	ret = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(new_dir)->ip_blkno);
46062306a36Sopenharmony_ci	if (ret)
46162306a36Sopenharmony_ci		mlog_errno(ret);
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ciout_move:
46462306a36Sopenharmony_ci	d_move(dentry, target);
46562306a36Sopenharmony_ci}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ciconst struct dentry_operations ocfs2_dentry_ops = {
46862306a36Sopenharmony_ci	.d_revalidate		= ocfs2_dentry_revalidate,
46962306a36Sopenharmony_ci	.d_iput			= ocfs2_dentry_iput,
47062306a36Sopenharmony_ci};
471