xref: /openbmc/linux/fs/ocfs2/dcache.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
1328970deSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2*fa60ce2cSMasahiro Yamada /*
3ccd979bdSMark Fasheh  * dcache.c
4ccd979bdSMark Fasheh  *
5ccd979bdSMark Fasheh  * dentry cache handling code
6ccd979bdSMark Fasheh  *
7ccd979bdSMark Fasheh  * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
8ccd979bdSMark Fasheh  */
9ccd979bdSMark Fasheh 
10ccd979bdSMark Fasheh #include <linux/fs.h>
11ccd979bdSMark Fasheh #include <linux/types.h>
12ccd979bdSMark Fasheh #include <linux/slab.h>
13ccd979bdSMark Fasheh #include <linux/namei.h>
14ccd979bdSMark Fasheh 
15ccd979bdSMark Fasheh #include <cluster/masklog.h>
16ccd979bdSMark Fasheh 
17ccd979bdSMark Fasheh #include "ocfs2.h"
18ccd979bdSMark Fasheh 
19ccd979bdSMark Fasheh #include "alloc.h"
20ccd979bdSMark Fasheh #include "dcache.h"
2180c05846SMark Fasheh #include "dlmglue.h"
22ccd979bdSMark Fasheh #include "file.h"
23ccd979bdSMark Fasheh #include "inode.h"
24a5b8443bSTao Ma #include "ocfs2_trace.h"
25ccd979bdSMark Fasheh 
ocfs2_dentry_attach_gen(struct dentry * dentry)265e98d492SGoldwyn Rodrigues void ocfs2_dentry_attach_gen(struct dentry *dentry)
275e98d492SGoldwyn Rodrigues {
285e98d492SGoldwyn Rodrigues 	unsigned long gen =
292b0143b5SDavid Howells 		OCFS2_I(d_inode(dentry->d_parent))->ip_dir_lock_gen;
302b0143b5SDavid Howells 	BUG_ON(d_inode(dentry));
315e98d492SGoldwyn Rodrigues 	dentry->d_fsdata = (void *)gen;
325e98d492SGoldwyn Rodrigues }
335e98d492SGoldwyn Rodrigues 
3480c05846SMark Fasheh 
ocfs2_dentry_revalidate(struct dentry * dentry,unsigned int flags)350b728e19SAl Viro static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags)
36ccd979bdSMark Fasheh {
3734286d66SNick Piggin 	struct inode *inode;
38ccd979bdSMark Fasheh 	int ret = 0;    /* if all else fails, just return false */
3934286d66SNick Piggin 	struct ocfs2_super *osb;
4034286d66SNick Piggin 
410b728e19SAl Viro 	if (flags & LOOKUP_RCU)
4234286d66SNick Piggin 		return -ECHILD;
4334286d66SNick Piggin 
442b0143b5SDavid Howells 	inode = d_inode(dentry);
4534286d66SNick Piggin 	osb = OCFS2_SB(dentry->d_sb);
46ccd979bdSMark Fasheh 
47a5b8443bSTao Ma 	trace_ocfs2_dentry_revalidate(dentry, dentry->d_name.len,
48a5b8443bSTao Ma 				      dentry->d_name.name);
49ccd979bdSMark Fasheh 
505e98d492SGoldwyn Rodrigues 	/* For a negative dentry -
515e98d492SGoldwyn Rodrigues 	 * check the generation number of the parent and compare with the
525e98d492SGoldwyn Rodrigues 	 * one stored in the inode.
535e98d492SGoldwyn Rodrigues 	 */
54ccd979bdSMark Fasheh 	if (inode == NULL) {
555e98d492SGoldwyn Rodrigues 		unsigned long gen = (unsigned long) dentry->d_fsdata;
567b9a2378SAl Viro 		unsigned long pgen;
577b9a2378SAl Viro 		spin_lock(&dentry->d_lock);
582b0143b5SDavid Howells 		pgen = OCFS2_I(d_inode(dentry->d_parent))->ip_dir_lock_gen;
597b9a2378SAl Viro 		spin_unlock(&dentry->d_lock);
60a5b8443bSTao Ma 		trace_ocfs2_dentry_revalidate_negative(dentry->d_name.len,
61a5b8443bSTao Ma 						       dentry->d_name.name,
62a5b8443bSTao Ma 						       pgen, gen);
635e98d492SGoldwyn Rodrigues 		if (gen != pgen)
64ccd979bdSMark Fasheh 			goto bail;
655e98d492SGoldwyn Rodrigues 		goto valid;
66ccd979bdSMark Fasheh 	}
67ccd979bdSMark Fasheh 
68ccd979bdSMark Fasheh 	BUG_ON(!osb);
69ccd979bdSMark Fasheh 
7080c05846SMark Fasheh 	if (inode == osb->root_inode || is_bad_inode(inode))
7180c05846SMark Fasheh 		goto bail;
7280c05846SMark Fasheh 
73ccd979bdSMark Fasheh 	spin_lock(&OCFS2_I(inode)->ip_lock);
74ccd979bdSMark Fasheh 	/* did we or someone else delete this inode? */
75ccd979bdSMark Fasheh 	if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {
76ccd979bdSMark Fasheh 		spin_unlock(&OCFS2_I(inode)->ip_lock);
77a5b8443bSTao Ma 		trace_ocfs2_dentry_revalidate_delete(
78b0697053SMark Fasheh 				(unsigned long long)OCFS2_I(inode)->ip_blkno);
79ccd979bdSMark Fasheh 		goto bail;
80ccd979bdSMark Fasheh 	}
81ccd979bdSMark Fasheh 	spin_unlock(&OCFS2_I(inode)->ip_lock);
82ccd979bdSMark Fasheh 
8380c05846SMark Fasheh 	/*
8480c05846SMark Fasheh 	 * We don't need a cluster lock to test this because once an
8580c05846SMark Fasheh 	 * inode nlink hits zero, it never goes back.
8680c05846SMark Fasheh 	 */
8780c05846SMark Fasheh 	if (inode->i_nlink == 0) {
88a5b8443bSTao Ma 		trace_ocfs2_dentry_revalidate_orphaned(
89b0697053SMark Fasheh 			(unsigned long long)OCFS2_I(inode)->ip_blkno,
90ccd979bdSMark Fasheh 			S_ISDIR(inode->i_mode));
91ccd979bdSMark Fasheh 		goto bail;
92ccd979bdSMark Fasheh 	}
93ccd979bdSMark Fasheh 
94a1b08e75STao Ma 	/*
95a1b08e75STao Ma 	 * If the last lookup failed to create dentry lock, let us
96a1b08e75STao Ma 	 * redo it.
97a1b08e75STao Ma 	 */
98a1b08e75STao Ma 	if (!dentry->d_fsdata) {
99a5b8443bSTao Ma 		trace_ocfs2_dentry_revalidate_nofsdata(
100a1b08e75STao Ma 				(unsigned long long)OCFS2_I(inode)->ip_blkno);
101a1b08e75STao Ma 		goto bail;
102a1b08e75STao Ma 	}
103a1b08e75STao Ma 
1045e98d492SGoldwyn Rodrigues valid:
105ccd979bdSMark Fasheh 	ret = 1;
106ccd979bdSMark Fasheh 
107ccd979bdSMark Fasheh bail:
108a5b8443bSTao Ma 	trace_ocfs2_dentry_revalidate_ret(ret);
109ccd979bdSMark Fasheh 	return ret;
110ccd979bdSMark Fasheh }
111ccd979bdSMark Fasheh 
ocfs2_match_dentry(struct dentry * dentry,u64 parent_blkno,int skip_unhashed)11280c05846SMark Fasheh static int ocfs2_match_dentry(struct dentry *dentry,
11380c05846SMark Fasheh 			      u64 parent_blkno,
11480c05846SMark Fasheh 			      int skip_unhashed)
11580c05846SMark Fasheh {
11680c05846SMark Fasheh 	struct inode *parent;
11780c05846SMark Fasheh 
11880c05846SMark Fasheh 	/*
11980c05846SMark Fasheh 	 * ocfs2_lookup() does a d_splice_alias() _before_ attaching
12080c05846SMark Fasheh 	 * to the lock data, so we skip those here, otherwise
12180c05846SMark Fasheh 	 * ocfs2_dentry_attach_lock() will get its original dentry
12280c05846SMark Fasheh 	 * back.
12380c05846SMark Fasheh 	 */
12480c05846SMark Fasheh 	if (!dentry->d_fsdata)
12580c05846SMark Fasheh 		return 0;
12680c05846SMark Fasheh 
12780c05846SMark Fasheh 	if (!dentry->d_parent)
12880c05846SMark Fasheh 		return 0;
12980c05846SMark Fasheh 
13080c05846SMark Fasheh 	if (skip_unhashed && d_unhashed(dentry))
13180c05846SMark Fasheh 		return 0;
13280c05846SMark Fasheh 
1332b0143b5SDavid Howells 	parent = d_inode(dentry->d_parent);
13480c05846SMark Fasheh 	/* Negative parent dentry? */
13580c05846SMark Fasheh 	if (!parent)
13680c05846SMark Fasheh 		return 0;
13780c05846SMark Fasheh 
13880c05846SMark Fasheh 	/* Name is in a different directory. */
13980c05846SMark Fasheh 	if (OCFS2_I(parent)->ip_blkno != parent_blkno)
14080c05846SMark Fasheh 		return 0;
14180c05846SMark Fasheh 
14280c05846SMark Fasheh 	return 1;
14380c05846SMark Fasheh }
14480c05846SMark Fasheh 
14580c05846SMark Fasheh /*
14680c05846SMark Fasheh  * Walk the inode alias list, and find a dentry which has a given
14780c05846SMark Fasheh  * parent. ocfs2_dentry_attach_lock() wants to find _any_ alias as it
14834d024f8SMark Fasheh  * is looking for a dentry_lock reference. The downconvert thread is
14934d024f8SMark Fasheh  * looking to unhash aliases, so we allow it to skip any that already
15034d024f8SMark Fasheh  * have that property.
15180c05846SMark Fasheh  */
ocfs2_find_local_alias(struct inode * inode,u64 parent_blkno,int skip_unhashed)15280c05846SMark Fasheh struct dentry *ocfs2_find_local_alias(struct inode *inode,
15380c05846SMark Fasheh 				      u64 parent_blkno,
15480c05846SMark Fasheh 				      int skip_unhashed)
15580c05846SMark Fasheh {
156a614a092SAl Viro 	struct dentry *dentry;
15780c05846SMark Fasheh 
158873feea0SNick Piggin 	spin_lock(&inode->i_lock);
159946e51f2SAl Viro 	hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
160da502956SNick Piggin 		spin_lock(&dentry->d_lock);
16180c05846SMark Fasheh 		if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
162a5b8443bSTao Ma 			trace_ocfs2_find_local_alias(dentry->d_name.len,
163a5b8443bSTao Ma 						     dentry->d_name.name);
16480c05846SMark Fasheh 
165dc0474beSNick Piggin 			dget_dlock(dentry);
166da502956SNick Piggin 			spin_unlock(&dentry->d_lock);
167a614a092SAl Viro 			spin_unlock(&inode->i_lock);
168a614a092SAl Viro 			return dentry;
16980c05846SMark Fasheh 		}
170da502956SNick Piggin 		spin_unlock(&dentry->d_lock);
17180c05846SMark Fasheh 	}
172873feea0SNick Piggin 	spin_unlock(&inode->i_lock);
173a614a092SAl Viro 	return NULL;
17480c05846SMark Fasheh }
17580c05846SMark Fasheh 
176d680efe9SMark Fasheh DEFINE_SPINLOCK(dentry_attach_lock);
177d680efe9SMark Fasheh 
17880c05846SMark Fasheh /*
17980c05846SMark Fasheh  * Attach this dentry to a cluster lock.
18080c05846SMark Fasheh  *
18180c05846SMark Fasheh  * Dentry locks cover all links in a given directory to a particular
18280c05846SMark Fasheh  * inode. We do this so that ocfs2 can build a lock name which all
18380c05846SMark Fasheh  * nodes in the cluster can agree on at all times. Shoving full names
18480c05846SMark Fasheh  * in the cluster lock won't work due to size restrictions. Covering
18580c05846SMark Fasheh  * links inside of a directory is a good compromise because it still
18680c05846SMark Fasheh  * allows us to use the parent directory lock to synchronize
18780c05846SMark Fasheh  * operations.
18880c05846SMark Fasheh  *
18980c05846SMark Fasheh  * Call this function with the parent dir semaphore and the parent dir
19080c05846SMark Fasheh  * cluster lock held.
19180c05846SMark Fasheh  *
19280c05846SMark Fasheh  * The dir semaphore will protect us from having to worry about
19380c05846SMark Fasheh  * concurrent processes on our node trying to attach a lock at the
19480c05846SMark Fasheh  * same time.
19580c05846SMark Fasheh  *
19680c05846SMark Fasheh  * The dir cluster lock (held at either PR or EX mode) protects us
19780c05846SMark Fasheh  * from unlink and rename on other nodes.
19880c05846SMark Fasheh  *
19980c05846SMark Fasheh  * A dput() can happen asynchronously due to pruning, so we cover
20080c05846SMark Fasheh  * attaching and detaching the dentry lock with a
20180c05846SMark Fasheh  * dentry_attach_lock.
20280c05846SMark Fasheh  *
20380c05846SMark Fasheh  * A node which has done lookup on a name retains a protected read
20480c05846SMark Fasheh  * lock until final dput. If the user requests and unlink or rename,
20580c05846SMark Fasheh  * the protected read is upgraded to an exclusive lock. Other nodes
20680c05846SMark Fasheh  * who have seen the dentry will then be informed that they need to
20780c05846SMark Fasheh  * downgrade their lock, which will involve d_delete on the
20880c05846SMark Fasheh  * dentry. This happens in ocfs2_dentry_convert_worker().
20980c05846SMark Fasheh  */
ocfs2_dentry_attach_lock(struct dentry * dentry,struct inode * inode,u64 parent_blkno)21080c05846SMark Fasheh int ocfs2_dentry_attach_lock(struct dentry *dentry,
21180c05846SMark Fasheh 			     struct inode *inode,
2120027dd5bSMark Fasheh 			     u64 parent_blkno)
21380c05846SMark Fasheh {
21480c05846SMark Fasheh 	int ret;
21580c05846SMark Fasheh 	struct dentry *alias;
21680c05846SMark Fasheh 	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
21780c05846SMark Fasheh 
218a5b8443bSTao Ma 	trace_ocfs2_dentry_attach_lock(dentry->d_name.len, dentry->d_name.name,
2190027dd5bSMark Fasheh 				       (unsigned long long)parent_blkno, dl);
22080c05846SMark Fasheh 
22180c05846SMark Fasheh 	/*
22280c05846SMark Fasheh 	 * Negative dentry. We ignore these for now.
22380c05846SMark Fasheh 	 *
22480c05846SMark Fasheh 	 * XXX: Could we can improve ocfs2_dentry_revalidate() by
22580c05846SMark Fasheh 	 * tracking these?
22680c05846SMark Fasheh 	 */
22780c05846SMark Fasheh 	if (!inode)
22880c05846SMark Fasheh 		return 0;
22980c05846SMark Fasheh 
2302b0143b5SDavid Howells 	if (d_really_is_negative(dentry) && dentry->d_fsdata) {
2315e98d492SGoldwyn Rodrigues 		/* Converting a negative dentry to positive
2325e98d492SGoldwyn Rodrigues 		   Clear dentry->d_fsdata */
2335e98d492SGoldwyn Rodrigues 		dentry->d_fsdata = dl = NULL;
2345e98d492SGoldwyn Rodrigues 	}
2355e98d492SGoldwyn Rodrigues 
23680c05846SMark Fasheh 	if (dl) {
23780c05846SMark Fasheh 		mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno,
238a455589fSAl Viro 				" \"%pd\": old parent: %llu, new: %llu\n",
239a455589fSAl Viro 				dentry,
24080c05846SMark Fasheh 				(unsigned long long)parent_blkno,
24180c05846SMark Fasheh 				(unsigned long long)dl->dl_parent_blkno);
24280c05846SMark Fasheh 		return 0;
24380c05846SMark Fasheh 	}
24480c05846SMark Fasheh 
24580c05846SMark Fasheh 	alias = ocfs2_find_local_alias(inode, parent_blkno, 0);
24680c05846SMark Fasheh 	if (alias) {
24780c05846SMark Fasheh 		/*
24880c05846SMark Fasheh 		 * Great, an alias exists, which means we must have a
24980c05846SMark Fasheh 		 * dentry lock already. We can just grab the lock off
25080c05846SMark Fasheh 		 * the alias and add it to the list.
25180c05846SMark Fasheh 		 *
25280c05846SMark Fasheh 		 * We're depending here on the fact that this dentry
25380c05846SMark Fasheh 		 * was found and exists in the dcache and so must have
25480c05846SMark Fasheh 		 * a reference to the dentry_lock because we can't
25580c05846SMark Fasheh 		 * race creates. Final dput() cannot happen on it
25680c05846SMark Fasheh 		 * since we have it pinned, so our reference is safe.
25780c05846SMark Fasheh 		 */
25880c05846SMark Fasheh 		dl = alias->d_fsdata;
2590027dd5bSMark Fasheh 		mlog_bug_on_msg(!dl, "parent %llu, ino %llu\n",
26080c05846SMark Fasheh 				(unsigned long long)parent_blkno,
2610027dd5bSMark Fasheh 				(unsigned long long)OCFS2_I(inode)->ip_blkno);
26280c05846SMark Fasheh 
26380c05846SMark Fasheh 		mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno,
264a455589fSAl Viro 				" \"%pd\": old parent: %llu, new: %llu\n",
265a455589fSAl Viro 				dentry,
26680c05846SMark Fasheh 				(unsigned long long)parent_blkno,
26780c05846SMark Fasheh 				(unsigned long long)dl->dl_parent_blkno);
26880c05846SMark Fasheh 
269a5b8443bSTao Ma 		trace_ocfs2_dentry_attach_lock_found(dl->dl_lockres.l_name,
270a5b8443bSTao Ma 				(unsigned long long)parent_blkno,
271a5b8443bSTao Ma 				(unsigned long long)OCFS2_I(inode)->ip_blkno);
27280c05846SMark Fasheh 
27380c05846SMark Fasheh 		goto out_attach;
27480c05846SMark Fasheh 	}
27580c05846SMark Fasheh 
27680c05846SMark Fasheh 	/*
27780c05846SMark Fasheh 	 * There are no other aliases
27880c05846SMark Fasheh 	 */
27980c05846SMark Fasheh 	dl = kmalloc(sizeof(*dl), GFP_NOFS);
28080c05846SMark Fasheh 	if (!dl) {
28180c05846SMark Fasheh 		ret = -ENOMEM;
28280c05846SMark Fasheh 		mlog_errno(ret);
28380c05846SMark Fasheh 		return ret;
28480c05846SMark Fasheh 	}
28580c05846SMark Fasheh 
28680c05846SMark Fasheh 	dl->dl_count = 0;
28780c05846SMark Fasheh 	/*
28880c05846SMark Fasheh 	 * Does this have to happen below, for all attaches, in case
28934d024f8SMark Fasheh 	 * the struct inode gets blown away by the downconvert thread?
29080c05846SMark Fasheh 	 */
29180c05846SMark Fasheh 	dl->dl_inode = igrab(inode);
29280c05846SMark Fasheh 	dl->dl_parent_blkno = parent_blkno;
29380c05846SMark Fasheh 	ocfs2_dentry_lock_res_init(dl, parent_blkno, inode);
29480c05846SMark Fasheh 
29580c05846SMark Fasheh out_attach:
29680c05846SMark Fasheh 	spin_lock(&dentry_attach_lock);
297be99ca27SWengang Wang 	if (unlikely(dentry->d_fsdata && !alias)) {
298be99ca27SWengang Wang 		/* d_fsdata is set by a racing thread which is doing
299be99ca27SWengang Wang 		 * the same thing as this thread is doing. Leave the racing
300be99ca27SWengang Wang 		 * thread going ahead and we return here.
301be99ca27SWengang Wang 		 */
302be99ca27SWengang Wang 		spin_unlock(&dentry_attach_lock);
303be99ca27SWengang Wang 		iput(dl->dl_inode);
304be99ca27SWengang Wang 		ocfs2_lock_res_free(&dl->dl_lockres);
305be99ca27SWengang Wang 		kfree(dl);
306be99ca27SWengang Wang 		return 0;
307be99ca27SWengang Wang 	}
308be99ca27SWengang Wang 
30980c05846SMark Fasheh 	dentry->d_fsdata = dl;
31080c05846SMark Fasheh 	dl->dl_count++;
31180c05846SMark Fasheh 	spin_unlock(&dentry_attach_lock);
31280c05846SMark Fasheh 
31380c05846SMark Fasheh 	/*
31480c05846SMark Fasheh 	 * This actually gets us our PRMODE level lock. From now on,
31580c05846SMark Fasheh 	 * we'll have a notification if one of these names is
31680c05846SMark Fasheh 	 * destroyed on another node.
31780c05846SMark Fasheh 	 */
31880c05846SMark Fasheh 	ret = ocfs2_dentry_lock(dentry, 0);
3190027dd5bSMark Fasheh 	if (!ret)
32080c05846SMark Fasheh 		ocfs2_dentry_unlock(dentry, 0);
3210027dd5bSMark Fasheh 	else
3220027dd5bSMark Fasheh 		mlog_errno(ret);
32380c05846SMark Fasheh 
324a5a0a630SSunil Mushran 	/*
325a5a0a630SSunil Mushran 	 * In case of error, manually free the allocation and do the iput().
326a5a0a630SSunil Mushran 	 * We need to do this because error here means no d_instantiate(),
327a5a0a630SSunil Mushran 	 * which means iput() will not be called during dput(dentry).
328a5a0a630SSunil Mushran 	 */
329a5a0a630SSunil Mushran 	if (ret < 0 && !alias) {
330a5a0a630SSunil Mushran 		ocfs2_lock_res_free(&dl->dl_lockres);
331a5a0a630SSunil Mushran 		BUG_ON(dl->dl_count != 1);
332a5a0a630SSunil Mushran 		spin_lock(&dentry_attach_lock);
333a5a0a630SSunil Mushran 		dentry->d_fsdata = NULL;
334a5a0a630SSunil Mushran 		spin_unlock(&dentry_attach_lock);
335a5a0a630SSunil Mushran 		kfree(dl);
336a5a0a630SSunil Mushran 		iput(inode);
337a5a0a630SSunil Mushran 	}
338a5a0a630SSunil Mushran 
33980c05846SMark Fasheh 	dput(alias);
34080c05846SMark Fasheh 
34180c05846SMark Fasheh 	return ret;
34280c05846SMark Fasheh }
34380c05846SMark Fasheh 
34480c05846SMark Fasheh /*
34580c05846SMark Fasheh  * ocfs2_dentry_iput() and friends.
34680c05846SMark Fasheh  *
34780c05846SMark Fasheh  * At this point, our particular dentry is detached from the inodes
34880c05846SMark Fasheh  * alias list, so there's no way that the locking code can find it.
34980c05846SMark Fasheh  *
35080c05846SMark Fasheh  * The interesting stuff happens when we determine that our lock needs
35180c05846SMark Fasheh  * to go away because this is the last subdir alias in the
35280c05846SMark Fasheh  * system. This function needs to handle a couple things:
35380c05846SMark Fasheh  *
35480c05846SMark Fasheh  * 1) Synchronizing lock shutdown with the downconvert threads. This
35580c05846SMark Fasheh  *    is already handled for us via the lockres release drop function
35680c05846SMark Fasheh  *    called in ocfs2_release_dentry_lock()
35780c05846SMark Fasheh  *
35880c05846SMark Fasheh  * 2) A race may occur when we're doing our lock shutdown and
35980c05846SMark Fasheh  *    another process wants to create a new dentry lock. Right now we
36080c05846SMark Fasheh  *    let them race, which means that for a very short while, this
36180c05846SMark Fasheh  *    node might have two locks on a lock resource. This should be a
36280c05846SMark Fasheh  *    problem though because one of them is in the process of being
36380c05846SMark Fasheh  *    thrown out.
36480c05846SMark Fasheh  */
ocfs2_drop_dentry_lock(struct ocfs2_super * osb,struct ocfs2_dentry_lock * dl)36580c05846SMark Fasheh static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
36680c05846SMark Fasheh 				   struct ocfs2_dentry_lock *dl)
36780c05846SMark Fasheh {
3688ed6b237SGoldwyn Rodrigues 	iput(dl->dl_inode);
36980c05846SMark Fasheh 	ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
37080c05846SMark Fasheh 	ocfs2_lock_res_free(&dl->dl_lockres);
3718ed6b237SGoldwyn Rodrigues 	kfree(dl);
37280c05846SMark Fasheh }
37380c05846SMark Fasheh 
ocfs2_dentry_lock_put(struct ocfs2_super * osb,struct ocfs2_dentry_lock * dl)37480c05846SMark Fasheh void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
37580c05846SMark Fasheh 			   struct ocfs2_dentry_lock *dl)
37680c05846SMark Fasheh {
3778ed6b237SGoldwyn Rodrigues 	int unlock = 0;
37880c05846SMark Fasheh 
37980c05846SMark Fasheh 	BUG_ON(dl->dl_count == 0);
38080c05846SMark Fasheh 
38180c05846SMark Fasheh 	spin_lock(&dentry_attach_lock);
38280c05846SMark Fasheh 	dl->dl_count--;
38380c05846SMark Fasheh 	unlock = !dl->dl_count;
38480c05846SMark Fasheh 	spin_unlock(&dentry_attach_lock);
38580c05846SMark Fasheh 
38680c05846SMark Fasheh 	if (unlock)
38780c05846SMark Fasheh 		ocfs2_drop_dentry_lock(osb, dl);
38880c05846SMark Fasheh }
38980c05846SMark Fasheh 
ocfs2_dentry_iput(struct dentry * dentry,struct inode * inode)39080c05846SMark Fasheh static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode)
39180c05846SMark Fasheh {
39280c05846SMark Fasheh 	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
39380c05846SMark Fasheh 
394bccb9dadSMark Fasheh 	if (!dl) {
395bccb9dadSMark Fasheh 		/*
396bccb9dadSMark Fasheh 		 * No dentry lock is ok if we're disconnected or
397bccb9dadSMark Fasheh 		 * unhashed.
398bccb9dadSMark Fasheh 		 */
399bccb9dadSMark Fasheh 		if (!(dentry->d_flags & DCACHE_DISCONNECTED) &&
400bccb9dadSMark Fasheh 		    !d_unhashed(dentry)) {
401bccb9dadSMark Fasheh 			unsigned long long ino = 0ULL;
402bccb9dadSMark Fasheh 			if (inode)
403bccb9dadSMark Fasheh 				ino = (unsigned long long)OCFS2_I(inode)->ip_blkno;
404bccb9dadSMark Fasheh 			mlog(ML_ERROR, "Dentry is missing cluster lock. "
405a455589fSAl Viro 			     "inode: %llu, d_flags: 0x%x, d_name: %pd\n",
406a455589fSAl Viro 			     ino, dentry->d_flags, dentry);
407bccb9dadSMark Fasheh 		}
40880c05846SMark Fasheh 
40980c05846SMark Fasheh 		goto out;
410bccb9dadSMark Fasheh 	}
41180c05846SMark Fasheh 
412a455589fSAl Viro 	mlog_bug_on_msg(dl->dl_count == 0, "dentry: %pd, count: %u\n",
413a455589fSAl Viro 			dentry, dl->dl_count);
41480c05846SMark Fasheh 
41580c05846SMark Fasheh 	ocfs2_dentry_lock_put(OCFS2_SB(dentry->d_sb), dl);
41680c05846SMark Fasheh 
41780c05846SMark Fasheh out:
41880c05846SMark Fasheh 	iput(inode);
41980c05846SMark Fasheh }
42080c05846SMark Fasheh 
42180c05846SMark Fasheh /*
42280c05846SMark Fasheh  * d_move(), but keep the locks in sync.
42380c05846SMark Fasheh  *
42480c05846SMark Fasheh  * When we are done, "dentry" will have the parent dir and name of
42580c05846SMark Fasheh  * "target", which will be thrown away.
42680c05846SMark Fasheh  *
42780c05846SMark Fasheh  * We manually update the lock of "dentry" if need be.
42880c05846SMark Fasheh  *
42980c05846SMark Fasheh  * "target" doesn't have it's dentry lock touched - we allow the later
43080c05846SMark Fasheh  * dput() to handle this for us.
43180c05846SMark Fasheh  *
43280c05846SMark Fasheh  * This is called during ocfs2_rename(), while holding parent
43380c05846SMark Fasheh  * directory locks. The dentries have already been deleted on other
43480c05846SMark Fasheh  * nodes via ocfs2_remote_dentry_delete().
43580c05846SMark Fasheh  *
4363a4fa0a2SRobert P. J. Day  * Normally, the VFS handles the d_move() for the file system, after
43780c05846SMark Fasheh  * the ->rename() callback. OCFS2 wants to handle this internally, so
43880c05846SMark Fasheh  * the new lock can be created atomically with respect to the cluster.
43980c05846SMark Fasheh  */
ocfs2_dentry_move(struct dentry * dentry,struct dentry * target,struct inode * old_dir,struct inode * new_dir)44080c05846SMark Fasheh void ocfs2_dentry_move(struct dentry *dentry, struct dentry *target,
44180c05846SMark Fasheh 		       struct inode *old_dir, struct inode *new_dir)
44280c05846SMark Fasheh {
44380c05846SMark Fasheh 	int ret;
44480c05846SMark Fasheh 	struct ocfs2_super *osb = OCFS2_SB(old_dir->i_sb);
4452b0143b5SDavid Howells 	struct inode *inode = d_inode(dentry);
44680c05846SMark Fasheh 
44780c05846SMark Fasheh 	/*
44880c05846SMark Fasheh 	 * Move within the same directory, so the actual lock info won't
44980c05846SMark Fasheh 	 * change.
45080c05846SMark Fasheh 	 *
45180c05846SMark Fasheh 	 * XXX: Is there any advantage to dropping the lock here?
45280c05846SMark Fasheh 	 */
45380c05846SMark Fasheh 	if (old_dir == new_dir)
4541ba9da2fSMark Fasheh 		goto out_move;
45580c05846SMark Fasheh 
45680c05846SMark Fasheh 	ocfs2_dentry_lock_put(osb, dentry->d_fsdata);
45780c05846SMark Fasheh 
45880c05846SMark Fasheh 	dentry->d_fsdata = NULL;
4590027dd5bSMark Fasheh 	ret = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(new_dir)->ip_blkno);
46080c05846SMark Fasheh 	if (ret)
46180c05846SMark Fasheh 		mlog_errno(ret);
4621ba9da2fSMark Fasheh 
4631ba9da2fSMark Fasheh out_move:
4641ba9da2fSMark Fasheh 	d_move(dentry, target);
46580c05846SMark Fasheh }
46680c05846SMark Fasheh 
467d8fba0ffSAl Viro const struct dentry_operations ocfs2_dentry_ops = {
468ccd979bdSMark Fasheh 	.d_revalidate		= ocfs2_dentry_revalidate,
46980c05846SMark Fasheh 	.d_iput			= ocfs2_dentry_iput,
470ccd979bdSMark Fasheh };
471