aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Kleikamp <dave.kleikamp@oracle.com>2013-08-15 16:36:49 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-09-08 01:09:57 -0400
commit192caed2bfb7072b7f364dc909b43fd7604b991d (patch)
tree0b646c2a1e2bdcc32717909b7a73188c0a6dc0ce
parent3508b9b01638a5e73fcf913213e4692680a86507 (diff)
jfs: fix readdir cookie incompatibility with NFSv4
commit 44512449c0ab368889dd13ae0031fba74ee7e1d2 upstream. NFSv4 reserves readdir cookie values 0-2 for special entries (. and ..), but jfs allows a value of 2 for a non-special entry. This incompatibility can result in the nfs client reporting a readdir loop. This patch doesn't change the value stored internally, but adds one to the value exposed to the iterate method. Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com> [bwh: Backported to 3.2: - Adjust context - s/ctx->pos/filp->f_pos/] Tested-by: Christian Kujau <lists@nerdbynature.de> Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/jfs/jfs_dtree.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 0ddbeceafc62..c450fdb3d78d 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -3047,6 +3047,14 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
3047 3047
3048 dir_index = (u32) filp->f_pos; 3048 dir_index = (u32) filp->f_pos;
3049 3049
3050 /*
3051 * NFSv4 reserves cookies 1 and 2 for . and .. so we add
3052 * the value we return to the vfs is one greater than the
3053 * one we use internally.
3054 */
3055 if (dir_index)
3056 dir_index--;
3057
3050 if (dir_index > 1) { 3058 if (dir_index > 1) {
3051 struct dir_table_slot dirtab_slot; 3059 struct dir_table_slot dirtab_slot;
3052 3060
@@ -3086,7 +3094,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
3086 if (p->header.flag & BT_INTERNAL) { 3094 if (p->header.flag & BT_INTERNAL) {
3087 jfs_err("jfs_readdir: bad index table"); 3095 jfs_err("jfs_readdir: bad index table");
3088 DT_PUTPAGE(mp); 3096 DT_PUTPAGE(mp);
3089 filp->f_pos = -1; 3097 filp->f_pos = DIREND;
3090 return 0; 3098 return 0;
3091 } 3099 }
3092 } else { 3100 } else {
@@ -3094,7 +3102,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
3094 /* 3102 /*
3095 * self "." 3103 * self "."
3096 */ 3104 */
3097 filp->f_pos = 0; 3105 filp->f_pos = 1;
3098 if (filldir(dirent, ".", 1, 0, ip->i_ino, 3106 if (filldir(dirent, ".", 1, 0, ip->i_ino,
3099 DT_DIR)) 3107 DT_DIR))
3100 return 0; 3108 return 0;
@@ -3102,7 +3110,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
3102 /* 3110 /*
3103 * parent ".." 3111 * parent ".."
3104 */ 3112 */
3105 filp->f_pos = 1; 3113 filp->f_pos = 2;
3106 if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR)) 3114 if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR))
3107 return 0; 3115 return 0;
3108 3116
@@ -3123,24 +3131,25 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
3123 /* 3131 /*
3124 * Legacy filesystem - OS/2 & Linux JFS < 0.3.6 3132 * Legacy filesystem - OS/2 & Linux JFS < 0.3.6
3125 * 3133 *
3126 * pn = index = 0: First entry "." 3134 * pn = 0; index = 1: First entry "."
3127 * pn = 0; index = 1: Second entry ".." 3135 * pn = 0; index = 2: Second entry ".."
3128 * pn > 0: Real entries, pn=1 -> leftmost page 3136 * pn > 0: Real entries, pn=1 -> leftmost page
3129 * pn = index = -1: No more entries 3137 * pn = index = -1: No more entries
3130 */ 3138 */
3131 dtpos = filp->f_pos; 3139 dtpos = filp->f_pos;
3132 if (dtpos == 0) { 3140 if (dtpos < 2) {
3133 /* build "." entry */ 3141 /* build "." entry */
3134 3142
3143 filp->f_pos = 1;
3135 if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino, 3144 if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino,
3136 DT_DIR)) 3145 DT_DIR))
3137 return 0; 3146 return 0;
3138 dtoffset->index = 1; 3147 dtoffset->index = 2;
3139 filp->f_pos = dtpos; 3148 filp->f_pos = dtpos;
3140 } 3149 }
3141 3150
3142 if (dtoffset->pn == 0) { 3151 if (dtoffset->pn == 0) {
3143 if (dtoffset->index == 1) { 3152 if (dtoffset->index == 2) {
3144 /* build ".." entry */ 3153 /* build ".." entry */
3145 3154
3146 if (filldir(dirent, "..", 2, filp->f_pos, 3155 if (filldir(dirent, "..", 2, filp->f_pos,
@@ -3233,6 +3242,12 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
3233 } 3242 }
3234 jfs_dirent->position = unique_pos++; 3243 jfs_dirent->position = unique_pos++;
3235 } 3244 }
3245 /*
3246 * We add 1 to the index because we may
3247 * use a value of 2 internally, and NFSv4
3248 * doesn't like that.
3249 */
3250 jfs_dirent->position++;
3236 } else { 3251 } else {
3237 jfs_dirent->position = dtpos; 3252 jfs_dirent->position = dtpos;
3238 len = min(d_namleft, DTLHDRDATALEN_LEGACY); 3253 len = min(d_namleft, DTLHDRDATALEN_LEGACY);