xref: /openbmc/linux/fs/ocfs2/dcache.c (revision 8ed6b23709b346f7bfc1edab47003a205a6a9f69)
1ccd979bdSMark Fasheh /* -*- mode: c; c-basic-offset: 8; -*-
2ccd979bdSMark Fasheh  * vim: noexpandtab sw=8 ts=8 sts=0:
3ccd979bdSMark Fasheh  *
4ccd979bdSMark Fasheh  * dcache.c
5ccd979bdSMark Fasheh  *
6ccd979bdSMark Fasheh  * dentry cache handling code
7ccd979bdSMark Fasheh  *
8ccd979bdSMark Fasheh  * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
9ccd979bdSMark Fasheh  *
10ccd979bdSMark Fasheh  * This program is free software; you can redistribute it and/or
11ccd979bdSMark Fasheh  * modify it under the terms of the GNU General Public
12ccd979bdSMark Fasheh  * License as published by the Free Software Foundation; either
13ccd979bdSMark Fasheh  * version 2 of the License, or (at your option) any later version.
14ccd979bdSMark Fasheh  *
15ccd979bdSMark Fasheh  * This program is distributed in the hope that it will be useful,
16ccd979bdSMark Fasheh  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17ccd979bdSMark Fasheh  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18ccd979bdSMark Fasheh  * General Public License for more details.
19ccd979bdSMark Fasheh  *
20ccd979bdSMark Fasheh  * You should have received a copy of the GNU General Public
21ccd979bdSMark Fasheh  * License along with this program; if not, write to the
22ccd979bdSMark Fasheh  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23ccd979bdSMark Fasheh  * Boston, MA 021110-1307, USA.
24ccd979bdSMark Fasheh  */
25ccd979bdSMark Fasheh 
26ccd979bdSMark Fasheh #include <linux/fs.h>
27ccd979bdSMark Fasheh #include <linux/types.h>
28ccd979bdSMark Fasheh #include <linux/slab.h>
29ccd979bdSMark Fasheh #include <linux/namei.h>
30ccd979bdSMark Fasheh 
31ccd979bdSMark Fasheh #include <cluster/masklog.h>
32ccd979bdSMark Fasheh 
33ccd979bdSMark Fasheh #include "ocfs2.h"
34ccd979bdSMark Fasheh 
35ccd979bdSMark Fasheh #include "alloc.h"
36ccd979bdSMark Fasheh #include "dcache.h"
3780c05846SMark Fasheh #include "dlmglue.h"
38ccd979bdSMark Fasheh #include "file.h"
39ccd979bdSMark Fasheh #include "inode.h"
40a5b8443bSTao Ma #include "ocfs2_trace.h"
41ccd979bdSMark Fasheh 
425e98d492SGoldwyn Rodrigues void ocfs2_dentry_attach_gen(struct dentry *dentry)
435e98d492SGoldwyn Rodrigues {
445e98d492SGoldwyn Rodrigues 	unsigned long gen =
455e98d492SGoldwyn Rodrigues 		OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen;
465e98d492SGoldwyn Rodrigues 	BUG_ON(dentry->d_inode);
475e98d492SGoldwyn Rodrigues 	dentry->d_fsdata = (void *)gen;
485e98d492SGoldwyn Rodrigues }
495e98d492SGoldwyn Rodrigues 
5080c05846SMark Fasheh 
510b728e19SAl Viro static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags)
52ccd979bdSMark Fasheh {
5334286d66SNick Piggin 	struct inode *inode;
54ccd979bdSMark Fasheh 	int ret = 0;    /* if all else fails, just return false */
5534286d66SNick Piggin 	struct ocfs2_super *osb;
5634286d66SNick Piggin 
570b728e19SAl Viro 	if (flags & LOOKUP_RCU)
5834286d66SNick Piggin 		return -ECHILD;
5934286d66SNick Piggin 
6034286d66SNick Piggin 	inode = dentry->d_inode;
6134286d66SNick Piggin 	osb = OCFS2_SB(dentry->d_sb);
62ccd979bdSMark Fasheh 
63a5b8443bSTao Ma 	trace_ocfs2_dentry_revalidate(dentry, dentry->d_name.len,
64a5b8443bSTao Ma 				      dentry->d_name.name);
65ccd979bdSMark Fasheh 
665e98d492SGoldwyn Rodrigues 	/* For a negative dentry -
675e98d492SGoldwyn Rodrigues 	 * check the generation number of the parent and compare with the
685e98d492SGoldwyn Rodrigues 	 * one stored in the inode.
695e98d492SGoldwyn Rodrigues 	 */
70ccd979bdSMark Fasheh 	if (inode == NULL) {
715e98d492SGoldwyn Rodrigues 		unsigned long gen = (unsigned long) dentry->d_fsdata;
727b9a2378SAl Viro 		unsigned long pgen;
737b9a2378SAl Viro 		spin_lock(&dentry->d_lock);
747b9a2378SAl Viro 		pgen = OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen;
757b9a2378SAl Viro 		spin_unlock(&dentry->d_lock);
76a5b8443bSTao Ma 		trace_ocfs2_dentry_revalidate_negative(dentry->d_name.len,
77a5b8443bSTao Ma 						       dentry->d_name.name,
78a5b8443bSTao Ma 						       pgen, gen);
795e98d492SGoldwyn Rodrigues 		if (gen != pgen)
80ccd979bdSMark Fasheh 			goto bail;
815e98d492SGoldwyn Rodrigues 		goto valid;
82ccd979bdSMark Fasheh 	}
83ccd979bdSMark Fasheh 
84ccd979bdSMark Fasheh 	BUG_ON(!osb);
85ccd979bdSMark Fasheh 
8680c05846SMark Fasheh 	if (inode == osb->root_inode || is_bad_inode(inode))
8780c05846SMark Fasheh 		goto bail;
8880c05846SMark Fasheh 
89ccd979bdSMark Fasheh 	spin_lock(&OCFS2_I(inode)->ip_lock);
90ccd979bdSMark Fasheh 	/* did we or someone else delete this inode? */
91ccd979bdSMark Fasheh 	if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {
92ccd979bdSMark Fasheh 		spin_unlock(&OCFS2_I(inode)->ip_lock);
93a5b8443bSTao Ma 		trace_ocfs2_dentry_revalidate_delete(
94b0697053SMark Fasheh 				(unsigned long long)OCFS2_I(inode)->ip_blkno);
95ccd979bdSMark Fasheh 		goto bail;
96ccd979bdSMark Fasheh 	}
97ccd979bdSMark Fasheh 	spin_unlock(&OCFS2_I(inode)->ip_lock);
98ccd979bdSMark Fasheh 
9980c05846SMark Fasheh 	/*
10080c05846SMark Fasheh 	 * We don't need a cluster lock to test this because once an
10180c05846SMark Fasheh 	 * inode nlink hits zero, it never goes back.
10280c05846SMark Fasheh 	 */
10380c05846SMark Fasheh 	if (inode->i_nlink == 0) {
104a5b8443bSTao Ma 		trace_ocfs2_dentry_revalidate_orphaned(
105b0697053SMark Fasheh 			(unsigned long long)OCFS2_I(inode)->ip_blkno,
106ccd979bdSMark Fasheh 			S_ISDIR(inode->i_mode));
107ccd979bdSMark Fasheh 		goto bail;
108ccd979bdSMark Fasheh 	}
109ccd979bdSMark Fasheh 
110a1b08e75STao Ma 	/*
111a1b08e75STao Ma 	 * If the last lookup failed to create dentry lock, let us
112a1b08e75STao Ma 	 * redo it.
113a1b08e75STao Ma 	 */
114a1b08e75STao Ma 	if (!dentry->d_fsdata) {
115a5b8443bSTao Ma 		trace_ocfs2_dentry_revalidate_nofsdata(
116a1b08e75STao Ma 				(unsigned long long)OCFS2_I(inode)->ip_blkno);
117a1b08e75STao Ma 		goto bail;
118a1b08e75STao Ma 	}
119a1b08e75STao Ma 
1205e98d492SGoldwyn Rodrigues valid:
121ccd979bdSMark Fasheh 	ret = 1;
122ccd979bdSMark Fasheh 
123ccd979bdSMark Fasheh bail:
124a5b8443bSTao Ma 	trace_ocfs2_dentry_revalidate_ret(ret);
125ccd979bdSMark Fasheh 	return ret;
126ccd979bdSMark Fasheh }
127ccd979bdSMark Fasheh 
12880c05846SMark Fasheh static int ocfs2_match_dentry(struct dentry *dentry,
12980c05846SMark Fasheh 			      u64 parent_blkno,
13080c05846SMark Fasheh 			      int skip_unhashed)
13180c05846SMark Fasheh {
13280c05846SMark Fasheh 	struct inode *parent;
13380c05846SMark Fasheh 
13480c05846SMark Fasheh 	/*
13580c05846SMark Fasheh 	 * ocfs2_lookup() does a d_splice_alias() _before_ attaching
13680c05846SMark Fasheh 	 * to the lock data, so we skip those here, otherwise
13780c05846SMark Fasheh 	 * ocfs2_dentry_attach_lock() will get its original dentry
13880c05846SMark Fasheh 	 * back.
13980c05846SMark Fasheh 	 */
14080c05846SMark Fasheh 	if (!dentry->d_fsdata)
14180c05846SMark Fasheh 		return 0;
14280c05846SMark Fasheh 
14380c05846SMark Fasheh 	if (!dentry->d_parent)
14480c05846SMark Fasheh 		return 0;
14580c05846SMark Fasheh 
14680c05846SMark Fasheh 	if (skip_unhashed && d_unhashed(dentry))
14780c05846SMark Fasheh 		return 0;
14880c05846SMark Fasheh 
14980c05846SMark Fasheh 	parent = dentry->d_parent->d_inode;
15080c05846SMark Fasheh 	/* Negative parent dentry? */
15180c05846SMark Fasheh 	if (!parent)
15280c05846SMark Fasheh 		return 0;
15380c05846SMark Fasheh 
15480c05846SMark Fasheh 	/* Name is in a different directory. */
15580c05846SMark Fasheh 	if (OCFS2_I(parent)->ip_blkno != parent_blkno)
15680c05846SMark Fasheh 		return 0;
15780c05846SMark Fasheh 
15880c05846SMark Fasheh 	return 1;
15980c05846SMark Fasheh }
16080c05846SMark Fasheh 
16180c05846SMark Fasheh /*
16280c05846SMark Fasheh  * Walk the inode alias list, and find a dentry which has a given
16380c05846SMark Fasheh  * parent. ocfs2_dentry_attach_lock() wants to find _any_ alias as it
16434d024f8SMark Fasheh  * is looking for a dentry_lock reference. The downconvert thread is
16534d024f8SMark Fasheh  * looking to unhash aliases, so we allow it to skip any that already
16634d024f8SMark Fasheh  * have that property.
16780c05846SMark Fasheh  */
16880c05846SMark Fasheh struct dentry *ocfs2_find_local_alias(struct inode *inode,
16980c05846SMark Fasheh 				      u64 parent_blkno,
17080c05846SMark Fasheh 				      int skip_unhashed)
17180c05846SMark Fasheh {
172a614a092SAl Viro 	struct dentry *dentry;
17380c05846SMark Fasheh 
174873feea0SNick Piggin 	spin_lock(&inode->i_lock);
175b67bfe0dSSasha Levin 	hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
176da502956SNick Piggin 		spin_lock(&dentry->d_lock);
17780c05846SMark Fasheh 		if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
178a5b8443bSTao Ma 			trace_ocfs2_find_local_alias(dentry->d_name.len,
179a5b8443bSTao Ma 						     dentry->d_name.name);
18080c05846SMark Fasheh 
181dc0474beSNick Piggin 			dget_dlock(dentry);
182da502956SNick Piggin 			spin_unlock(&dentry->d_lock);
183a614a092SAl Viro 			spin_unlock(&inode->i_lock);
184a614a092SAl Viro 			return dentry;
18580c05846SMark Fasheh 		}
186da502956SNick Piggin 		spin_unlock(&dentry->d_lock);
18780c05846SMark Fasheh 	}
188873feea0SNick Piggin 	spin_unlock(&inode->i_lock);
189a614a092SAl Viro 	return NULL;
19080c05846SMark Fasheh }
19180c05846SMark Fasheh 
192d680efe9SMark Fasheh DEFINE_SPINLOCK(dentry_attach_lock);
193d680efe9SMark Fasheh 
19480c05846SMark Fasheh /*
19580c05846SMark Fasheh  * Attach this dentry to a cluster lock.
19680c05846SMark Fasheh  *
19780c05846SMark Fasheh  * Dentry locks cover all links in a given directory to a particular
19880c05846SMark Fasheh  * inode. We do this so that ocfs2 can build a lock name which all
19980c05846SMark Fasheh  * nodes in the cluster can agree on at all times. Shoving full names
20080c05846SMark Fasheh  * in the cluster lock won't work due to size restrictions. Covering
20180c05846SMark Fasheh  * links inside of a directory is a good compromise because it still
20280c05846SMark Fasheh  * allows us to use the parent directory lock to synchronize
20380c05846SMark Fasheh  * operations.
20480c05846SMark Fasheh  *
20580c05846SMark Fasheh  * Call this function with the parent dir semaphore and the parent dir
20680c05846SMark Fasheh  * cluster lock held.
20780c05846SMark Fasheh  *
20880c05846SMark Fasheh  * The dir semaphore will protect us from having to worry about
20980c05846SMark Fasheh  * concurrent processes on our node trying to attach a lock at the
21080c05846SMark Fasheh  * same time.
21180c05846SMark Fasheh  *
21280c05846SMark Fasheh  * The dir cluster lock (held at either PR or EX mode) protects us
21380c05846SMark Fasheh  * from unlink and rename on other nodes.
21480c05846SMark Fasheh  *
21580c05846SMark Fasheh  * A dput() can happen asynchronously due to pruning, so we cover
21680c05846SMark Fasheh  * attaching and detaching the dentry lock with a
21780c05846SMark Fasheh  * dentry_attach_lock.
21880c05846SMark Fasheh  *
21980c05846SMark Fasheh  * A node which has done lookup on a name retains a protected read
22080c05846SMark Fasheh  * lock until final dput. If the user requests and unlink or rename,
22180c05846SMark Fasheh  * the protected read is upgraded to an exclusive lock. Other nodes
22280c05846SMark Fasheh  * who have seen the dentry will then be informed that they need to
22380c05846SMark Fasheh  * downgrade their lock, which will involve d_delete on the
22480c05846SMark Fasheh  * dentry. This happens in ocfs2_dentry_convert_worker().
22580c05846SMark Fasheh  */
22680c05846SMark Fasheh int ocfs2_dentry_attach_lock(struct dentry *dentry,
22780c05846SMark Fasheh 			     struct inode *inode,
2280027dd5bSMark Fasheh 			     u64 parent_blkno)
22980c05846SMark Fasheh {
23080c05846SMark Fasheh 	int ret;
23180c05846SMark Fasheh 	struct dentry *alias;
23280c05846SMark Fasheh 	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
23380c05846SMark Fasheh 
234a5b8443bSTao Ma 	trace_ocfs2_dentry_attach_lock(dentry->d_name.len, dentry->d_name.name,
2350027dd5bSMark Fasheh 				       (unsigned long long)parent_blkno, dl);
23680c05846SMark Fasheh 
23780c05846SMark Fasheh 	/*
23880c05846SMark Fasheh 	 * Negative dentry. We ignore these for now.
23980c05846SMark Fasheh 	 *
24080c05846SMark Fasheh 	 * XXX: Could we can improve ocfs2_dentry_revalidate() by
24180c05846SMark Fasheh 	 * tracking these?
24280c05846SMark Fasheh 	 */
24380c05846SMark Fasheh 	if (!inode)
24480c05846SMark Fasheh 		return 0;
24580c05846SMark Fasheh 
2465e98d492SGoldwyn Rodrigues 	if (!dentry->d_inode && dentry->d_fsdata) {
2475e98d492SGoldwyn Rodrigues 		/* Converting a negative dentry to positive
2485e98d492SGoldwyn Rodrigues 		   Clear dentry->d_fsdata */
2495e98d492SGoldwyn Rodrigues 		dentry->d_fsdata = dl = NULL;
2505e98d492SGoldwyn Rodrigues 	}
2515e98d492SGoldwyn Rodrigues 
25280c05846SMark Fasheh 	if (dl) {
25380c05846SMark Fasheh 		mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno,
25480c05846SMark Fasheh 				" \"%.*s\": old parent: %llu, new: %llu\n",
25580c05846SMark Fasheh 				dentry->d_name.len, dentry->d_name.name,
25680c05846SMark Fasheh 				(unsigned long long)parent_blkno,
25780c05846SMark Fasheh 				(unsigned long long)dl->dl_parent_blkno);
25880c05846SMark Fasheh 		return 0;
25980c05846SMark Fasheh 	}
26080c05846SMark Fasheh 
26180c05846SMark Fasheh 	alias = ocfs2_find_local_alias(inode, parent_blkno, 0);
26280c05846SMark Fasheh 	if (alias) {
26380c05846SMark Fasheh 		/*
26480c05846SMark Fasheh 		 * Great, an alias exists, which means we must have a
26580c05846SMark Fasheh 		 * dentry lock already. We can just grab the lock off
26680c05846SMark Fasheh 		 * the alias and add it to the list.
26780c05846SMark Fasheh 		 *
26880c05846SMark Fasheh 		 * We're depending here on the fact that this dentry
26980c05846SMark Fasheh 		 * was found and exists in the dcache and so must have
27080c05846SMark Fasheh 		 * a reference to the dentry_lock because we can't
27180c05846SMark Fasheh 		 * race creates. Final dput() cannot happen on it
27280c05846SMark Fasheh 		 * since we have it pinned, so our reference is safe.
27380c05846SMark Fasheh 		 */
27480c05846SMark Fasheh 		dl = alias->d_fsdata;
2750027dd5bSMark Fasheh 		mlog_bug_on_msg(!dl, "parent %llu, ino %llu\n",
27680c05846SMark Fasheh 				(unsigned long long)parent_blkno,
2770027dd5bSMark Fasheh 				(unsigned long long)OCFS2_I(inode)->ip_blkno);
27880c05846SMark Fasheh 
27980c05846SMark Fasheh 		mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno,
28080c05846SMark Fasheh 				" \"%.*s\": old parent: %llu, new: %llu\n",
28180c05846SMark Fasheh 				dentry->d_name.len, dentry->d_name.name,
28280c05846SMark Fasheh 				(unsigned long long)parent_blkno,
28380c05846SMark Fasheh 				(unsigned long long)dl->dl_parent_blkno);
28480c05846SMark Fasheh 
285a5b8443bSTao Ma 		trace_ocfs2_dentry_attach_lock_found(dl->dl_lockres.l_name,
286a5b8443bSTao Ma 				(unsigned long long)parent_blkno,
287a5b8443bSTao Ma 				(unsigned long long)OCFS2_I(inode)->ip_blkno);
28880c05846SMark Fasheh 
28980c05846SMark Fasheh 		goto out_attach;
29080c05846SMark Fasheh 	}
29180c05846SMark Fasheh 
29280c05846SMark Fasheh 	/*
29380c05846SMark Fasheh 	 * There are no other aliases
29480c05846SMark Fasheh 	 */
29580c05846SMark Fasheh 	dl = kmalloc(sizeof(*dl), GFP_NOFS);
29680c05846SMark Fasheh 	if (!dl) {
29780c05846SMark Fasheh 		ret = -ENOMEM;
29880c05846SMark Fasheh 		mlog_errno(ret);
29980c05846SMark Fasheh 		return ret;
30080c05846SMark Fasheh 	}
30180c05846SMark Fasheh 
30280c05846SMark Fasheh 	dl->dl_count = 0;
30380c05846SMark Fasheh 	/*
30480c05846SMark Fasheh 	 * Does this have to happen below, for all attaches, in case
30534d024f8SMark Fasheh 	 * the struct inode gets blown away by the downconvert thread?
30680c05846SMark Fasheh 	 */
30780c05846SMark Fasheh 	dl->dl_inode = igrab(inode);
30880c05846SMark Fasheh 	dl->dl_parent_blkno = parent_blkno;
30980c05846SMark Fasheh 	ocfs2_dentry_lock_res_init(dl, parent_blkno, inode);
31080c05846SMark Fasheh 
31180c05846SMark Fasheh out_attach:
31280c05846SMark Fasheh 	spin_lock(&dentry_attach_lock);
31380c05846SMark Fasheh 	dentry->d_fsdata = dl;
31480c05846SMark Fasheh 	dl->dl_count++;
31580c05846SMark Fasheh 	spin_unlock(&dentry_attach_lock);
31680c05846SMark Fasheh 
31780c05846SMark Fasheh 	/*
31880c05846SMark Fasheh 	 * This actually gets us our PRMODE level lock. From now on,
31980c05846SMark Fasheh 	 * we'll have a notification if one of these names is
32080c05846SMark Fasheh 	 * destroyed on another node.
32180c05846SMark Fasheh 	 */
32280c05846SMark Fasheh 	ret = ocfs2_dentry_lock(dentry, 0);
3230027dd5bSMark Fasheh 	if (!ret)
32480c05846SMark Fasheh 		ocfs2_dentry_unlock(dentry, 0);
3250027dd5bSMark Fasheh 	else
3260027dd5bSMark Fasheh 		mlog_errno(ret);
32780c05846SMark Fasheh 
328a5a0a630SSunil Mushran 	/*
329a5a0a630SSunil Mushran 	 * In case of error, manually free the allocation and do the iput().
330a5a0a630SSunil Mushran 	 * We need to do this because error here means no d_instantiate(),
331a5a0a630SSunil Mushran 	 * which means iput() will not be called during dput(dentry).
332a5a0a630SSunil Mushran 	 */
333a5a0a630SSunil Mushran 	if (ret < 0 && !alias) {
334a5a0a630SSunil Mushran 		ocfs2_lock_res_free(&dl->dl_lockres);
335a5a0a630SSunil Mushran 		BUG_ON(dl->dl_count != 1);
336a5a0a630SSunil Mushran 		spin_lock(&dentry_attach_lock);
337a5a0a630SSunil Mushran 		dentry->d_fsdata = NULL;
338a5a0a630SSunil Mushran 		spin_unlock(&dentry_attach_lock);
339a5a0a630SSunil Mushran 		kfree(dl);
340a5a0a630SSunil Mushran 		iput(inode);
341a5a0a630SSunil Mushran 	}
342a5a0a630SSunil Mushran 
34380c05846SMark Fasheh 	dput(alias);
34480c05846SMark Fasheh 
34580c05846SMark Fasheh 	return ret;
34680c05846SMark Fasheh }
34780c05846SMark Fasheh 
34880c05846SMark Fasheh /*
34980c05846SMark Fasheh  * ocfs2_dentry_iput() and friends.
35080c05846SMark Fasheh  *
35180c05846SMark Fasheh  * At this point, our particular dentry is detached from the inodes
35280c05846SMark Fasheh  * alias list, so there's no way that the locking code can find it.
35380c05846SMark Fasheh  *
35480c05846SMark Fasheh  * The interesting stuff happens when we determine that our lock needs
35580c05846SMark Fasheh  * to go away because this is the last subdir alias in the
35680c05846SMark Fasheh  * system. This function needs to handle a couple things:
35780c05846SMark Fasheh  *
35880c05846SMark Fasheh  * 1) Synchronizing lock shutdown with the downconvert threads. This
35980c05846SMark Fasheh  *    is already handled for us via the lockres release drop function
36080c05846SMark Fasheh  *    called in ocfs2_release_dentry_lock()
36180c05846SMark Fasheh  *
36280c05846SMark Fasheh  * 2) A race may occur when we're doing our lock shutdown and
36380c05846SMark Fasheh  *    another process wants to create a new dentry lock. Right now we
36480c05846SMark Fasheh  *    let them race, which means that for a very short while, this
36580c05846SMark Fasheh  *    node might have two locks on a lock resource. This should be a
36680c05846SMark Fasheh  *    problem though because one of them is in the process of being
36780c05846SMark Fasheh  *    thrown out.
36880c05846SMark Fasheh  */
36980c05846SMark Fasheh static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
37080c05846SMark Fasheh 				   struct ocfs2_dentry_lock *dl)
37180c05846SMark Fasheh {
372*8ed6b237SGoldwyn Rodrigues 	iput(dl->dl_inode);
37380c05846SMark Fasheh 	ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
37480c05846SMark Fasheh 	ocfs2_lock_res_free(&dl->dl_lockres);
375*8ed6b237SGoldwyn Rodrigues 	kfree(dl);
37680c05846SMark Fasheh }
37780c05846SMark Fasheh 
37880c05846SMark Fasheh void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
37980c05846SMark Fasheh 			   struct ocfs2_dentry_lock *dl)
38080c05846SMark Fasheh {
381*8ed6b237SGoldwyn Rodrigues 	int unlock = 0;
38280c05846SMark Fasheh 
38380c05846SMark Fasheh 	BUG_ON(dl->dl_count == 0);
38480c05846SMark Fasheh 
38580c05846SMark Fasheh 	spin_lock(&dentry_attach_lock);
38680c05846SMark Fasheh 	dl->dl_count--;
38780c05846SMark Fasheh 	unlock = !dl->dl_count;
38880c05846SMark Fasheh 	spin_unlock(&dentry_attach_lock);
38980c05846SMark Fasheh 
39080c05846SMark Fasheh 	if (unlock)
39180c05846SMark Fasheh 		ocfs2_drop_dentry_lock(osb, dl);
39280c05846SMark Fasheh }
39380c05846SMark Fasheh 
39480c05846SMark Fasheh static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode)
39580c05846SMark Fasheh {
39680c05846SMark Fasheh 	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
39780c05846SMark Fasheh 
398bccb9dadSMark Fasheh 	if (!dl) {
399bccb9dadSMark Fasheh 		/*
400bccb9dadSMark Fasheh 		 * No dentry lock is ok if we're disconnected or
401bccb9dadSMark Fasheh 		 * unhashed.
402bccb9dadSMark Fasheh 		 */
403bccb9dadSMark Fasheh 		if (!(dentry->d_flags & DCACHE_DISCONNECTED) &&
404bccb9dadSMark Fasheh 		    !d_unhashed(dentry)) {
405bccb9dadSMark Fasheh 			unsigned long long ino = 0ULL;
406bccb9dadSMark Fasheh 			if (inode)
407bccb9dadSMark Fasheh 				ino = (unsigned long long)OCFS2_I(inode)->ip_blkno;
408bccb9dadSMark Fasheh 			mlog(ML_ERROR, "Dentry is missing cluster lock. "
409bccb9dadSMark Fasheh 			     "inode: %llu, d_flags: 0x%x, d_name: %.*s\n",
410bccb9dadSMark Fasheh 			     ino, dentry->d_flags, dentry->d_name.len,
41180c05846SMark Fasheh 			     dentry->d_name.name);
412bccb9dadSMark Fasheh 		}
41380c05846SMark Fasheh 
41480c05846SMark Fasheh 		goto out;
415bccb9dadSMark Fasheh 	}
41680c05846SMark Fasheh 
41780c05846SMark Fasheh 	mlog_bug_on_msg(dl->dl_count == 0, "dentry: %.*s, count: %u\n",
41880c05846SMark Fasheh 			dentry->d_name.len, dentry->d_name.name,
41980c05846SMark Fasheh 			dl->dl_count);
42080c05846SMark Fasheh 
42180c05846SMark Fasheh 	ocfs2_dentry_lock_put(OCFS2_SB(dentry->d_sb), dl);
42280c05846SMark Fasheh 
42380c05846SMark Fasheh out:
42480c05846SMark Fasheh 	iput(inode);
42580c05846SMark Fasheh }
42680c05846SMark Fasheh 
42780c05846SMark Fasheh /*
42880c05846SMark Fasheh  * d_move(), but keep the locks in sync.
42980c05846SMark Fasheh  *
43080c05846SMark Fasheh  * When we are done, "dentry" will have the parent dir and name of
43180c05846SMark Fasheh  * "target", which will be thrown away.
43280c05846SMark Fasheh  *
43380c05846SMark Fasheh  * We manually update the lock of "dentry" if need be.
43480c05846SMark Fasheh  *
43580c05846SMark Fasheh  * "target" doesn't have it's dentry lock touched - we allow the later
43680c05846SMark Fasheh  * dput() to handle this for us.
43780c05846SMark Fasheh  *
43880c05846SMark Fasheh  * This is called during ocfs2_rename(), while holding parent
43980c05846SMark Fasheh  * directory locks. The dentries have already been deleted on other
44080c05846SMark Fasheh  * nodes via ocfs2_remote_dentry_delete().
44180c05846SMark Fasheh  *
4423a4fa0a2SRobert P. J. Day  * Normally, the VFS handles the d_move() for the file system, after
44380c05846SMark Fasheh  * the ->rename() callback. OCFS2 wants to handle this internally, so
44480c05846SMark Fasheh  * the new lock can be created atomically with respect to the cluster.
44580c05846SMark Fasheh  */
44680c05846SMark Fasheh void ocfs2_dentry_move(struct dentry *dentry, struct dentry *target,
44780c05846SMark Fasheh 		       struct inode *old_dir, struct inode *new_dir)
44880c05846SMark Fasheh {
44980c05846SMark Fasheh 	int ret;
45080c05846SMark Fasheh 	struct ocfs2_super *osb = OCFS2_SB(old_dir->i_sb);
45180c05846SMark Fasheh 	struct inode *inode = dentry->d_inode;
45280c05846SMark Fasheh 
45380c05846SMark Fasheh 	/*
45480c05846SMark Fasheh 	 * Move within the same directory, so the actual lock info won't
45580c05846SMark Fasheh 	 * change.
45680c05846SMark Fasheh 	 *
45780c05846SMark Fasheh 	 * XXX: Is there any advantage to dropping the lock here?
45880c05846SMark Fasheh 	 */
45980c05846SMark Fasheh 	if (old_dir == new_dir)
4601ba9da2fSMark Fasheh 		goto out_move;
46180c05846SMark Fasheh 
46280c05846SMark Fasheh 	ocfs2_dentry_lock_put(osb, dentry->d_fsdata);
46380c05846SMark Fasheh 
46480c05846SMark Fasheh 	dentry->d_fsdata = NULL;
4650027dd5bSMark Fasheh 	ret = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(new_dir)->ip_blkno);
46680c05846SMark Fasheh 	if (ret)
46780c05846SMark Fasheh 		mlog_errno(ret);
4681ba9da2fSMark Fasheh 
4691ba9da2fSMark Fasheh out_move:
4701ba9da2fSMark Fasheh 	d_move(dentry, target);
47180c05846SMark Fasheh }
47280c05846SMark Fasheh 
473d8fba0ffSAl Viro const struct dentry_operations ocfs2_dentry_ops = {
474ccd979bdSMark Fasheh 	.d_revalidate		= ocfs2_dentry_revalidate,
47580c05846SMark Fasheh 	.d_iput			= ocfs2_dentry_iput,
476ccd979bdSMark Fasheh };
477