aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph/dir.c')
-rw-r--r--fs/ceph/dir.c28
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
192out_unlock: 195out_unlock:
193 spin_unlock(&dcache_lock); 196 spin_unlock(&parent->d_lock);
194out: 197out:
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 */
989static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) 992static 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,