diff options
Diffstat (limited to 'fs/ceph/dir.c')
-rw-r--r-- | fs/ceph/dir.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 6bfaa6a4ec47..f0aef787a102 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -42,11 +42,11 @@ int ceph_init_dentry(struct dentry *dentry) | |||
42 | 42 | ||
43 | if (dentry->d_parent == NULL || /* nfs fh_to_dentry */ | 43 | if (dentry->d_parent == NULL || /* nfs fh_to_dentry */ |
44 | ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP) | 44 | ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP) |
45 | dentry->d_op = &ceph_dentry_ops; | 45 | d_set_d_op(dentry, &ceph_dentry_ops); |
46 | else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR) | 46 | else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR) |
47 | dentry->d_op = &ceph_snapdir_dentry_ops; | 47 | d_set_d_op(dentry, &ceph_snapdir_dentry_ops); |
48 | else | 48 | else |
49 | dentry->d_op = &ceph_snap_dentry_ops; | 49 | d_set_d_op(dentry, &ceph_snap_dentry_ops); |
50 | 50 | ||
51 | di = kmem_cache_alloc(ceph_dentry_cachep, GFP_NOFS | __GFP_ZERO); | 51 | di = kmem_cache_alloc(ceph_dentry_cachep, GFP_NOFS | __GFP_ZERO); |
52 | if (!di) | 52 | if (!di) |
@@ -113,7 +113,7 @@ static int __dcache_readdir(struct file *filp, | |||
113 | dout("__dcache_readdir %p at %llu (last %p)\n", dir, filp->f_pos, | 113 | dout("__dcache_readdir %p at %llu (last %p)\n", dir, filp->f_pos, |
114 | last); | 114 | last); |
115 | 115 | ||
116 | spin_lock(&dcache_lock); | 116 | spin_lock(&parent->d_lock); |
117 | 117 | ||
118 | /* start at beginning? */ | 118 | /* start at beginning? */ |
119 | if (filp->f_pos == 2 || last == NULL || | 119 | if (filp->f_pos == 2 || last == NULL || |
@@ -137,6 +137,7 @@ more: | |||
137 | fi->at_end = 1; | 137 | fi->at_end = 1; |
138 | goto out_unlock; | 138 | goto out_unlock; |
139 | } | 139 | } |
140 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); | ||
140 | if (!d_unhashed(dentry) && dentry->d_inode && | 141 | if (!d_unhashed(dentry) && dentry->d_inode && |
141 | ceph_snap(dentry->d_inode) != CEPH_SNAPDIR && | 142 | ceph_snap(dentry->d_inode) != CEPH_SNAPDIR && |
142 | ceph_ino(dentry->d_inode) != CEPH_INO_CEPH && | 143 | ceph_ino(dentry->d_inode) != CEPH_INO_CEPH && |
@@ -146,13 +147,15 @@ more: | |||
146 | dentry->d_name.len, dentry->d_name.name, di->offset, | 147 | dentry->d_name.len, dentry->d_name.name, di->offset, |
147 | filp->f_pos, d_unhashed(dentry) ? " unhashed" : "", | 148 | filp->f_pos, d_unhashed(dentry) ? " unhashed" : "", |
148 | !dentry->d_inode ? " null" : ""); | 149 | !dentry->d_inode ? " null" : ""); |
150 | spin_unlock(&dentry->d_lock); | ||
149 | p = p->prev; | 151 | p = p->prev; |
150 | dentry = list_entry(p, struct dentry, d_u.d_child); | 152 | dentry = list_entry(p, struct dentry, d_u.d_child); |
151 | di = ceph_dentry(dentry); | 153 | di = ceph_dentry(dentry); |
152 | } | 154 | } |
153 | 155 | ||
154 | atomic_inc(&dentry->d_count); | 156 | dget_dlock(dentry); |
155 | spin_unlock(&dcache_lock); | 157 | spin_unlock(&dentry->d_lock); |
158 | spin_unlock(&parent->d_lock); | ||
156 | 159 | ||
157 | dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos, | 160 | dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos, |
158 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); | 161 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); |
@@ -178,19 +181,19 @@ more: | |||
178 | 181 | ||
179 | filp->f_pos++; | 182 | filp->f_pos++; |
180 | 183 | ||
181 | /* make sure a dentry wasn't dropped while we didn't have dcache_lock */ | 184 | /* make sure a dentry wasn't dropped while we didn't have parent lock */ |
182 | if (!ceph_i_test(dir, CEPH_I_COMPLETE)) { | 185 | if (!ceph_i_test(dir, CEPH_I_COMPLETE)) { |
183 | dout(" lost I_COMPLETE on %p; falling back to mds\n", dir); | 186 | dout(" lost I_COMPLETE on %p; falling back to mds\n", dir); |
184 | err = -EAGAIN; | 187 | err = -EAGAIN; |
185 | goto out; | 188 | goto out; |
186 | } | 189 | } |
187 | 190 | ||
188 | spin_lock(&dcache_lock); | 191 | spin_lock(&parent->d_lock); |
189 | p = p->prev; /* advance to next dentry */ | 192 | p = p->prev; /* advance to next dentry */ |
190 | goto more; | 193 | goto more; |
191 | 194 | ||
192 | out_unlock: | 195 | out_unlock: |
193 | spin_unlock(&dcache_lock); | 196 | spin_unlock(&parent->d_lock); |
194 | out: | 197 | out: |
195 | if (last) | 198 | if (last) |
196 | dput(last); | 199 | dput(last); |
@@ -988,7 +991,12 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry) | |||
988 | */ | 991 | */ |
989 | static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) | 992 | static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) |
990 | { | 993 | { |
991 | struct inode *dir = dentry->d_parent->d_inode; | 994 | struct inode *dir; |
995 | |||
996 | if (nd->flags & LOOKUP_RCU) | ||
997 | return -ECHILD; | ||
998 | |||
999 | dir = dentry->d_parent->d_inode; | ||
992 | 1000 | ||
993 | dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, | 1001 | dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, |
994 | dentry->d_name.len, dentry->d_name.name, dentry->d_inode, | 1002 | dentry->d_name.len, dentry->d_name.name, dentry->d_inode, |