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.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index e0a2dc6fcafc..d902948a90d8 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -40,7 +40,8 @@ int ceph_init_dentry(struct dentry *dentry)
40 if (dentry->d_fsdata) 40 if (dentry->d_fsdata)
41 return 0; 41 return 0;
42 42
43 if (ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP) 43 if (dentry->d_parent == NULL || /* nfs fh_to_dentry */
44 ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
44 dentry->d_op = &ceph_dentry_ops; 45 dentry->d_op = &ceph_dentry_ops;
45 else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR) 46 else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
46 dentry->d_op = &ceph_snapdir_dentry_ops; 47 dentry->d_op = &ceph_snapdir_dentry_ops;
@@ -114,8 +115,8 @@ static int __dcache_readdir(struct file *filp,
114 spin_lock(&dcache_lock); 115 spin_lock(&dcache_lock);
115 116
116 /* start at beginning? */ 117 /* start at beginning? */
117 if (filp->f_pos == 2 || (last && 118 if (filp->f_pos == 2 || last == NULL ||
118 filp->f_pos < ceph_dentry(last)->offset)) { 119 filp->f_pos < ceph_dentry(last)->offset) {
119 if (list_empty(&parent->d_subdirs)) 120 if (list_empty(&parent->d_subdirs))
120 goto out_unlock; 121 goto out_unlock;
121 p = parent->d_subdirs.prev; 122 p = parent->d_subdirs.prev;
@@ -336,7 +337,10 @@ more:
336 if (req->r_reply_info.dir_end) { 337 if (req->r_reply_info.dir_end) {
337 kfree(fi->last_name); 338 kfree(fi->last_name);
338 fi->last_name = NULL; 339 fi->last_name = NULL;
339 fi->next_offset = 2; 340 if (ceph_frag_is_rightmost(frag))
341 fi->next_offset = 2;
342 else
343 fi->next_offset = 0;
340 } else { 344 } else {
341 rinfo = &req->r_reply_info; 345 rinfo = &req->r_reply_info;
342 err = note_last_dentry(fi, 346 err = note_last_dentry(fi,
@@ -355,18 +359,22 @@ more:
355 u64 pos = ceph_make_fpos(frag, off); 359 u64 pos = ceph_make_fpos(frag, off);
356 struct ceph_mds_reply_inode *in = 360 struct ceph_mds_reply_inode *in =
357 rinfo->dir_in[off - fi->offset].in; 361 rinfo->dir_in[off - fi->offset].in;
362 struct ceph_vino vino;
363 ino_t ino;
364
358 dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n", 365 dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n",
359 off, off - fi->offset, rinfo->dir_nr, pos, 366 off, off - fi->offset, rinfo->dir_nr, pos,
360 rinfo->dir_dname_len[off - fi->offset], 367 rinfo->dir_dname_len[off - fi->offset],
361 rinfo->dir_dname[off - fi->offset], in); 368 rinfo->dir_dname[off - fi->offset], in);
362 BUG_ON(!in); 369 BUG_ON(!in);
363 ftype = le32_to_cpu(in->mode) >> 12; 370 ftype = le32_to_cpu(in->mode) >> 12;
371 vino.ino = le64_to_cpu(in->ino);
372 vino.snap = le64_to_cpu(in->snapid);
373 ino = ceph_vino_to_ino(vino);
364 if (filldir(dirent, 374 if (filldir(dirent,
365 rinfo->dir_dname[off - fi->offset], 375 rinfo->dir_dname[off - fi->offset],
366 rinfo->dir_dname_len[off - fi->offset], 376 rinfo->dir_dname_len[off - fi->offset],
367 pos, 377 pos, ino, ftype) < 0) {
368 le64_to_cpu(in->ino),
369 ftype) < 0) {
370 dout("filldir stopping us...\n"); 378 dout("filldir stopping us...\n");
371 return 0; 379 return 0;
372 } 380 }
@@ -414,6 +422,7 @@ static void reset_readdir(struct ceph_file_info *fi)
414 fi->last_readdir = NULL; 422 fi->last_readdir = NULL;
415 } 423 }
416 kfree(fi->last_name); 424 kfree(fi->last_name);
425 fi->last_name = NULL;
417 fi->next_offset = 2; /* compensate for . and .. */ 426 fi->next_offset = 2; /* compensate for . and .. */
418 if (fi->dentry) { 427 if (fi->dentry) {
419 dput(fi->dentry); 428 dput(fi->dentry);