Blame view
fs/gfs2/dentry.c
2.71 KB
b3b94faa5
|
1 2 |
/* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3a8a9a103
|
3 |
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
b3b94faa5
|
4 5 6 |
* * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions |
e9fc2aa09
|
7 |
* of the GNU General Public License version 2. |
b3b94faa5
|
8 |
*/ |
b3b94faa5
|
9 10 11 |
#include <linux/spinlock.h> #include <linux/completion.h> #include <linux/buffer_head.h> |
5c676f6d3
|
12 |
#include <linux/gfs2_ondisk.h> |
34286d666
|
13 |
#include <linux/namei.h> |
71b86f562
|
14 |
#include <linux/crc32.h> |
b3b94faa5
|
15 16 |
#include "gfs2.h" |
5c676f6d3
|
17 |
#include "incore.h" |
b3b94faa5
|
18 19 |
#include "dir.h" #include "glock.h" |
b27605837
|
20 |
#include "super.h" |
5c676f6d3
|
21 |
#include "util.h" |
dbb7cae2a
|
22 |
#include "inode.h" |
b3b94faa5
|
23 24 25 26 |
/** * gfs2_drevalidate - Check directory lookup consistency * @dentry: the mapping to check |
0b728e191
|
27 |
* @flags: lookup flags |
b3b94faa5
|
28 29 30 31 32 33 |
* * Check to make sure the lookup necessary to arrive at this inode from its * parent is still good. * * Returns: 1 if the dentry is ok, 0 if it isn't */ |
0b728e191
|
34 |
static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags) |
b3b94faa5
|
35 |
{ |
34286d666
|
36 37 38 39 |
struct dentry *parent; struct gfs2_sbd *sdp; struct gfs2_inode *dip; struct inode *inode; |
b3b94faa5
|
40 |
struct gfs2_holder d_gh; |
dbb7cae2a
|
41 |
struct gfs2_inode *ip = NULL; |
b3b94faa5
|
42 |
int error; |
7afd88d91
|
43 |
int had_lock = 0; |
b3b94faa5
|
44 |
|
0b728e191
|
45 |
if (flags & LOOKUP_RCU) |
34286d666
|
46 47 48 |
return -ECHILD; parent = dget_parent(dentry); |
2b0143b5c
|
49 50 51 |
sdp = GFS2_SB(d_inode(parent)); dip = GFS2_I(d_inode(parent)); inode = d_inode(dentry); |
34286d666
|
52 |
|
dbb7cae2a
|
53 54 55 56 57 |
if (inode) { if (is_bad_inode(inode)) goto invalid; ip = GFS2_I(inode); } |
b3b94faa5
|
58 |
|
c2048b003
|
59 |
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) |
c752666c1
|
60 |
goto valid; |
7afd88d91
|
61 |
had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL); |
549ae0ac3
|
62 63 64 65 66 |
if (!had_lock) { error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); if (error) goto fail; } |
b3b94faa5
|
67 |
|
2b0143b5c
|
68 |
error = gfs2_dir_check(d_inode(parent), &dentry->d_name, ip); |
b3b94faa5
|
69 70 71 72 73 74 75 76 77 78 79 80 |
switch (error) { case 0: if (!inode) goto invalid_gunlock; break; case -ENOENT: if (!inode) goto valid_gunlock; goto invalid_gunlock; default: goto fail_gunlock; } |
a91ea69ff
|
81 |
valid_gunlock: |
549ae0ac3
|
82 83 |
if (!had_lock) gfs2_glock_dq_uninit(&d_gh); |
a91ea69ff
|
84 |
valid: |
b3b94faa5
|
85 86 |
dput(parent); return 1; |
a91ea69ff
|
87 |
invalid_gunlock: |
549ae0ac3
|
88 89 |
if (!had_lock) gfs2_glock_dq_uninit(&d_gh); |
a91ea69ff
|
90 |
invalid: |
b3b94faa5
|
91 92 |
dput(parent); return 0; |
a91ea69ff
|
93 |
fail_gunlock: |
b3b94faa5
|
94 |
gfs2_glock_dq_uninit(&d_gh); |
a91ea69ff
|
95 |
fail: |
b3b94faa5
|
96 97 98 |
dput(parent); return 0; } |
da53be12b
|
99 |
static int gfs2_dhash(const struct dentry *dentry, struct qstr *str) |
c752666c1
|
100 101 102 103 |
{ str->hash = gfs2_disk_hash(str->name, str->len); return 0; } |
fe15ce446
|
104 |
static int gfs2_dentry_delete(const struct dentry *dentry) |
970343cd4
|
105 106 |
{ struct gfs2_inode *ginode; |
2b0143b5c
|
107 |
if (d_really_is_negative(dentry)) |
970343cd4
|
108 |
return 0; |
2b0143b5c
|
109 |
ginode = GFS2_I(d_inode(dentry)); |
970343cd4
|
110 111 112 113 114 115 116 117 |
if (!ginode->i_iopen_gh.gh_gl) return 0; if (test_bit(GLF_DEMOTE, &ginode->i_iopen_gh.gh_gl->gl_flags)) return 1; return 0; } |
92cecbbfa
|
118 |
const struct dentry_operations gfs2_dops = { |
b3b94faa5
|
119 |
.d_revalidate = gfs2_drevalidate, |
c752666c1
|
120 |
.d_hash = gfs2_dhash, |
970343cd4
|
121 |
.d_delete = gfs2_dentry_delete, |
b3b94faa5
|
122 |
}; |