xref: /openbmc/linux/fs/gfs2/dentry.c (revision fe15ce44)
1b1e71b06SSteven Whitehouse /*
2b1e71b06SSteven Whitehouse  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3b1e71b06SSteven Whitehouse  * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
4b1e71b06SSteven Whitehouse  *
5b1e71b06SSteven Whitehouse  * This copyrighted material is made available to anyone wishing to use,
6b1e71b06SSteven Whitehouse  * modify, copy, or redistribute it subject to the terms and conditions
7b1e71b06SSteven Whitehouse  * of the GNU General Public License version 2.
8b1e71b06SSteven Whitehouse  */
9b1e71b06SSteven Whitehouse 
10b1e71b06SSteven Whitehouse #include <linux/spinlock.h>
11b1e71b06SSteven Whitehouse #include <linux/completion.h>
12b1e71b06SSteven Whitehouse #include <linux/buffer_head.h>
13b1e71b06SSteven Whitehouse #include <linux/gfs2_ondisk.h>
14b1e71b06SSteven Whitehouse #include <linux/crc32.h>
15b1e71b06SSteven Whitehouse 
16b1e71b06SSteven Whitehouse #include "gfs2.h"
17b1e71b06SSteven Whitehouse #include "incore.h"
18b1e71b06SSteven Whitehouse #include "dir.h"
19b1e71b06SSteven Whitehouse #include "glock.h"
20b1e71b06SSteven Whitehouse #include "super.h"
21b1e71b06SSteven Whitehouse #include "util.h"
22b1e71b06SSteven Whitehouse #include "inode.h"
23b1e71b06SSteven Whitehouse 
24b1e71b06SSteven Whitehouse /**
25b1e71b06SSteven Whitehouse  * gfs2_drevalidate - Check directory lookup consistency
26b1e71b06SSteven Whitehouse  * @dentry: the mapping to check
27b1e71b06SSteven Whitehouse  * @nd:
28b1e71b06SSteven Whitehouse  *
29b1e71b06SSteven Whitehouse  * Check to make sure the lookup necessary to arrive at this inode from its
30b1e71b06SSteven Whitehouse  * parent is still good.
31b1e71b06SSteven Whitehouse  *
32b1e71b06SSteven Whitehouse  * Returns: 1 if the dentry is ok, 0 if it isn't
33b1e71b06SSteven Whitehouse  */
34b1e71b06SSteven Whitehouse 
35b1e71b06SSteven Whitehouse static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
36b1e71b06SSteven Whitehouse {
37b1e71b06SSteven Whitehouse 	struct dentry *parent = dget_parent(dentry);
38b1e71b06SSteven Whitehouse 	struct gfs2_sbd *sdp = GFS2_SB(parent->d_inode);
39b1e71b06SSteven Whitehouse 	struct gfs2_inode *dip = GFS2_I(parent->d_inode);
40b1e71b06SSteven Whitehouse 	struct inode *inode = dentry->d_inode;
41b1e71b06SSteven Whitehouse 	struct gfs2_holder d_gh;
42b1e71b06SSteven Whitehouse 	struct gfs2_inode *ip = NULL;
43b1e71b06SSteven Whitehouse 	int error;
44b1e71b06SSteven Whitehouse 	int had_lock = 0;
45b1e71b06SSteven Whitehouse 
46b1e71b06SSteven Whitehouse 	if (inode) {
47b1e71b06SSteven Whitehouse 		if (is_bad_inode(inode))
48b1e71b06SSteven Whitehouse 			goto invalid;
49b1e71b06SSteven Whitehouse 		ip = GFS2_I(inode);
50b1e71b06SSteven Whitehouse 	}
51b1e71b06SSteven Whitehouse 
52c2048b00SSteven Whitehouse 	if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
53b1e71b06SSteven Whitehouse 		goto valid;
54b1e71b06SSteven Whitehouse 
55b1e71b06SSteven Whitehouse 	had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
56b1e71b06SSteven Whitehouse 	if (!had_lock) {
57b1e71b06SSteven Whitehouse 		error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
58b1e71b06SSteven Whitehouse 		if (error)
59b1e71b06SSteven Whitehouse 			goto fail;
60b1e71b06SSteven Whitehouse 	}
61b1e71b06SSteven Whitehouse 
62b1e71b06SSteven Whitehouse 	error = gfs2_dir_check(parent->d_inode, &dentry->d_name, ip);
63b1e71b06SSteven Whitehouse 	switch (error) {
64b1e71b06SSteven Whitehouse 	case 0:
65b1e71b06SSteven Whitehouse 		if (!inode)
66b1e71b06SSteven Whitehouse 			goto invalid_gunlock;
67b1e71b06SSteven Whitehouse 		break;
68b1e71b06SSteven Whitehouse 	case -ENOENT:
69b1e71b06SSteven Whitehouse 		if (!inode)
70b1e71b06SSteven Whitehouse 			goto valid_gunlock;
71b1e71b06SSteven Whitehouse 		goto invalid_gunlock;
72b1e71b06SSteven Whitehouse 	default:
73b1e71b06SSteven Whitehouse 		goto fail_gunlock;
74b1e71b06SSteven Whitehouse 	}
75b1e71b06SSteven Whitehouse 
76b1e71b06SSteven Whitehouse valid_gunlock:
77b1e71b06SSteven Whitehouse 	if (!had_lock)
78b1e71b06SSteven Whitehouse 		gfs2_glock_dq_uninit(&d_gh);
79b1e71b06SSteven Whitehouse valid:
80b1e71b06SSteven Whitehouse 	dput(parent);
81b1e71b06SSteven Whitehouse 	return 1;
82b1e71b06SSteven Whitehouse 
83b1e71b06SSteven Whitehouse invalid_gunlock:
84b1e71b06SSteven Whitehouse 	if (!had_lock)
85b1e71b06SSteven Whitehouse 		gfs2_glock_dq_uninit(&d_gh);
86b1e71b06SSteven Whitehouse invalid:
87b1e71b06SSteven Whitehouse 	if (inode && S_ISDIR(inode->i_mode)) {
88b1e71b06SSteven Whitehouse 		if (have_submounts(dentry))
89b1e71b06SSteven Whitehouse 			goto valid;
90b1e71b06SSteven Whitehouse 		shrink_dcache_parent(dentry);
91b1e71b06SSteven Whitehouse 	}
92b1e71b06SSteven Whitehouse 	d_drop(dentry);
93b1e71b06SSteven Whitehouse 	dput(parent);
94b1e71b06SSteven Whitehouse 	return 0;
95b1e71b06SSteven Whitehouse 
96b1e71b06SSteven Whitehouse fail_gunlock:
97b1e71b06SSteven Whitehouse 	gfs2_glock_dq_uninit(&d_gh);
98b1e71b06SSteven Whitehouse fail:
99b1e71b06SSteven Whitehouse 	dput(parent);
100b1e71b06SSteven Whitehouse 	return 0;
101b1e71b06SSteven Whitehouse }
102b1e71b06SSteven Whitehouse 
103b1e71b06SSteven Whitehouse static int gfs2_dhash(struct dentry *dentry, struct qstr *str)
104b1e71b06SSteven Whitehouse {
105b1e71b06SSteven Whitehouse 	str->hash = gfs2_disk_hash(str->name, str->len);
106b1e71b06SSteven Whitehouse 	return 0;
107b1e71b06SSteven Whitehouse }
108b1e71b06SSteven Whitehouse 
109fe15ce44SNick Piggin static int gfs2_dentry_delete(const struct dentry *dentry)
110970343cdSWengang Wang {
111970343cdSWengang Wang 	struct gfs2_inode *ginode;
112970343cdSWengang Wang 
113970343cdSWengang Wang 	if (!dentry->d_inode)
114970343cdSWengang Wang 		return 0;
115970343cdSWengang Wang 
116970343cdSWengang Wang 	ginode = GFS2_I(dentry->d_inode);
117970343cdSWengang Wang 	if (!ginode->i_iopen_gh.gh_gl)
118970343cdSWengang Wang 		return 0;
119970343cdSWengang Wang 
120970343cdSWengang Wang 	if (test_bit(GLF_DEMOTE, &ginode->i_iopen_gh.gh_gl->gl_flags))
121970343cdSWengang Wang 		return 1;
122970343cdSWengang Wang 
123970343cdSWengang Wang 	return 0;
124970343cdSWengang Wang }
125970343cdSWengang Wang 
126b1e71b06SSteven Whitehouse const struct dentry_operations gfs2_dops = {
127b1e71b06SSteven Whitehouse 	.d_revalidate = gfs2_drevalidate,
128b1e71b06SSteven Whitehouse 	.d_hash = gfs2_dhash,
129970343cdSWengang Wang 	.d_delete = gfs2_dentry_delete,
130b1e71b06SSteven Whitehouse };
131b1e71b06SSteven Whitehouse 
132