diff options
Diffstat (limited to 'fs/jfs/jfs_dtree.c')
-rw-r--r-- | fs/jfs/jfs_dtree.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 8743ba9c6742..984c2bbf4f61 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c | |||
@@ -3047,6 +3047,14 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) | |||
3047 | 3047 | ||
3048 | dir_index = (u32) ctx->pos; | 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 | 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 *file, struct dir_context *ctx) | |||
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 | ctx->pos = -1; | 3097 | ctx->pos = DIREND; |
3090 | return 0; | 3098 | return 0; |
3091 | } | 3099 | } |
3092 | } else { | 3100 | } else { |
@@ -3094,14 +3102,14 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) | |||
3094 | /* | 3102 | /* |
3095 | * self "." | 3103 | * self "." |
3096 | */ | 3104 | */ |
3097 | ctx->pos = 0; | 3105 | ctx->pos = 1; |
3098 | if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR)) | 3106 | if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR)) |
3099 | return 0; | 3107 | return 0; |
3100 | } | 3108 | } |
3101 | /* | 3109 | /* |
3102 | * parent ".." | 3110 | * parent ".." |
3103 | */ | 3111 | */ |
3104 | ctx->pos = 1; | 3112 | ctx->pos = 2; |
3105 | if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) | 3113 | if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) |
3106 | return 0; | 3114 | return 0; |
3107 | 3115 | ||
@@ -3122,22 +3130,23 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) | |||
3122 | /* | 3130 | /* |
3123 | * Legacy filesystem - OS/2 & Linux JFS < 0.3.6 | 3131 | * Legacy filesystem - OS/2 & Linux JFS < 0.3.6 |
3124 | * | 3132 | * |
3125 | * pn = index = 0: First entry "." | 3133 | * pn = 0; index = 1: First entry "." |
3126 | * pn = 0; index = 1: Second entry ".." | 3134 | * pn = 0; index = 2: Second entry ".." |
3127 | * pn > 0: Real entries, pn=1 -> leftmost page | 3135 | * pn > 0: Real entries, pn=1 -> leftmost page |
3128 | * pn = index = -1: No more entries | 3136 | * pn = index = -1: No more entries |
3129 | */ | 3137 | */ |
3130 | dtpos = ctx->pos; | 3138 | dtpos = ctx->pos; |
3131 | if (dtpos == 0) { | 3139 | if (dtpos < 2) { |
3132 | /* build "." entry */ | 3140 | /* build "." entry */ |
3141 | ctx->pos = 1; | ||
3133 | if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR)) | 3142 | if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR)) |
3134 | return 0; | 3143 | return 0; |
3135 | dtoffset->index = 1; | 3144 | dtoffset->index = 2; |
3136 | ctx->pos = dtpos; | 3145 | ctx->pos = dtpos; |
3137 | } | 3146 | } |
3138 | 3147 | ||
3139 | if (dtoffset->pn == 0) { | 3148 | if (dtoffset->pn == 0) { |
3140 | if (dtoffset->index == 1) { | 3149 | if (dtoffset->index == 2) { |
3141 | /* build ".." entry */ | 3150 | /* build ".." entry */ |
3142 | if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) | 3151 | if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) |
3143 | return 0; | 3152 | return 0; |
@@ -3228,6 +3237,12 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) | |||
3228 | } | 3237 | } |
3229 | jfs_dirent->position = unique_pos++; | 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 | } else { | 3246 | } else { |
3232 | jfs_dirent->position = dtpos; | 3247 | jfs_dirent->position = dtpos; |
3233 | len = min(d_namleft, DTLHDRDATALEN_LEGACY); | 3248 | len = min(d_namleft, DTLHDRDATALEN_LEGACY); |