Commit 44512449c0ab368889dd13ae0031fba74ee7e1d2
1 parent
f1d6e17f54
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
jfs: fix readdir cookie incompatibility with NFSv4
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> Tested-by: Christian Kujau <lists@nerdbynature.de>
Showing 1 changed file with 23 additions and 8 deletions Side-by-side Diff
fs/jfs/jfs_dtree.c
... | ... | @@ -3047,6 +3047,14 @@ |
3047 | 3047 | |
3048 | 3048 | dir_index = (u32) ctx->pos; |
3049 | 3049 | |
3050 | + /* | |
3051 | + * NFSv4 reserves cookies 1 and 2 for . and .. so the value | |
3052 | + * we return to the vfs is one greater than the one we use | |
3053 | + * internally. | |
3054 | + */ | |
3055 | + if (dir_index) | |
3056 | + dir_index--; | |
3057 | + | |
3050 | 3058 | if (dir_index > 1) { |
3051 | 3059 | struct dir_table_slot dirtab_slot; |
3052 | 3060 | |
... | ... | @@ -3086,7 +3094,7 @@ |
3086 | 3094 | if (p->header.flag & BT_INTERNAL) { |
3087 | 3095 | jfs_err("jfs_readdir: bad index table"); |
3088 | 3096 | DT_PUTPAGE(mp); |
3089 | - ctx->pos = -1; | |
3097 | + ctx->pos = DIREND; | |
3090 | 3098 | return 0; |
3091 | 3099 | } |
3092 | 3100 | } else { |
3093 | 3101 | |
... | ... | @@ -3094,14 +3102,14 @@ |
3094 | 3102 | /* |
3095 | 3103 | * self "." |
3096 | 3104 | */ |
3097 | - ctx->pos = 0; | |
3105 | + ctx->pos = 1; | |
3098 | 3106 | if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR)) |
3099 | 3107 | return 0; |
3100 | 3108 | } |
3101 | 3109 | /* |
3102 | 3110 | * parent ".." |
3103 | 3111 | */ |
3104 | - ctx->pos = 1; | |
3112 | + ctx->pos = 2; | |
3105 | 3113 | if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) |
3106 | 3114 | return 0; |
3107 | 3115 | |
3108 | 3116 | |
3109 | 3117 | |
3110 | 3118 | |
3111 | 3119 | |
... | ... | @@ -3122,22 +3130,23 @@ |
3122 | 3130 | /* |
3123 | 3131 | * Legacy filesystem - OS/2 & Linux JFS < 0.3.6 |
3124 | 3132 | * |
3125 | - * pn = index = 0: First entry "." | |
3126 | - * pn = 0; index = 1: Second entry ".." | |
3133 | + * pn = 0; index = 1: First entry "." | |
3134 | + * pn = 0; index = 2: Second entry ".." | |
3127 | 3135 | * pn > 0: Real entries, pn=1 -> leftmost page |
3128 | 3136 | * pn = index = -1: No more entries |
3129 | 3137 | */ |
3130 | 3138 | dtpos = ctx->pos; |
3131 | - if (dtpos == 0) { | |
3139 | + if (dtpos < 2) { | |
3132 | 3140 | /* build "." entry */ |
3141 | + ctx->pos = 1; | |
3133 | 3142 | if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR)) |
3134 | 3143 | return 0; |
3135 | - dtoffset->index = 1; | |
3144 | + dtoffset->index = 2; | |
3136 | 3145 | ctx->pos = dtpos; |
3137 | 3146 | } |
3138 | 3147 | |
3139 | 3148 | if (dtoffset->pn == 0) { |
3140 | - if (dtoffset->index == 1) { | |
3149 | + if (dtoffset->index == 2) { | |
3141 | 3150 | /* build ".." entry */ |
3142 | 3151 | if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) |
3143 | 3152 | return 0; |
... | ... | @@ -3228,6 +3237,12 @@ |
3228 | 3237 | } |
3229 | 3238 | jfs_dirent->position = unique_pos++; |
3230 | 3239 | } |
3240 | + /* | |
3241 | + * We add 1 to the index because we may | |
3242 | + * use a value of 2 internally, and NFSv4 | |
3243 | + * doesn't like that. | |
3244 | + */ | |
3245 | + jfs_dirent->position++; | |
3231 | 3246 | } else { |
3232 | 3247 | jfs_dirent->position = dtpos; |
3233 | 3248 | len = min(d_namleft, DTLHDRDATALEN_LEGACY); |