From 5f15fa22167ff665d0db0159551eb90759683984 Mon Sep 17 00:00:00 2001 From: Andrey Vesnovaty Date: Tue, 8 Oct 2013 10:28:40 +0200 Subject: [PATCH] Fix readdir for .zfs/snapshot directory dmu_snapshot_list_next stores the index of the next snapshot entry to the offp argument, which zpl_snapdir_iterate then uses for the dir_emit. This result in an off-by-one error. Therefore a temporary variable should be used. This was a regression introduced in commit zfsonlinux/zfs@0f37d0c. Signed-off-by: Andrey Vesnovaty Signed-off-by: Brian Behlendorf Closes #2930 --- module/zfs/zpl_ctldir.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/module/zfs/zpl_ctldir.c b/module/zfs/zpl_ctldir.c index 9e587e3f0..c9f33716a 100644 --- a/module/zfs/zpl_ctldir.c +++ b/module/zfs/zpl_ctldir.c @@ -252,7 +252,7 @@ zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx) zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode); char snapname[MAXNAMELEN]; boolean_t case_conflict; - uint64_t id; + uint64_t id, cookie; int error = 0; ZFS_ENTER(zsb); @@ -260,10 +260,11 @@ zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx) if (!dir_emit_dots(filp, ctx)) goto out; + cookie = ctx->pos; while (error == 0) { dsl_pool_config_enter(dmu_objset_pool(zsb->z_os), FTAG); error = -dmu_snapshot_list_next(zsb->z_os, MAXNAMELEN, - snapname, &id, &ctx->pos, &case_conflict); + snapname, &id, &cookie, &case_conflict); dsl_pool_config_exit(dmu_objset_pool(zsb->z_os), FTAG); if (error) goto out; @@ -271,6 +272,8 @@ zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx) if (!dir_emit(ctx, snapname, strlen(snapname), ZFSCTL_INO_SHARES - id, DT_DIR)) goto out; + + ctx->pos = cookie; } out: ZFS_EXIT(zsb);