Commit 44512449 authored by Dave Kleikamp's avatar Dave Kleikamp

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: default avatarDave Kleikamp <dave.kleikamp@oracle.com>
Tested-by: default avatarChristian Kujau <lists@nerdbynature.de>
parent f1d6e17f
...@@ -3047,6 +3047,14 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -3047,6 +3047,14 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
dir_index = (u32) ctx->pos; dir_index = (u32) ctx->pos;
/*
* NFSv4 reserves cookies 1 and 2 for . and .. so the value
* we return to the vfs is one greater than the one we use
* internally.
*/
if (dir_index)
dir_index--;
if (dir_index > 1) { if (dir_index > 1) {
struct dir_table_slot dirtab_slot; struct dir_table_slot dirtab_slot;
...@@ -3086,7 +3094,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -3086,7 +3094,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
if (p->header.flag & BT_INTERNAL) { if (p->header.flag & BT_INTERNAL) {
jfs_err("jfs_readdir: bad index table"); jfs_err("jfs_readdir: bad index table");
DT_PUTPAGE(mp); DT_PUTPAGE(mp);
ctx->pos = -1; ctx->pos = DIREND;
return 0; return 0;
} }
} else { } else {
...@@ -3094,14 +3102,14 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -3094,14 +3102,14 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
/* /*
* self "." * self "."
*/ */
ctx->pos = 0; ctx->pos = 1;
if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR)) if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR))
return 0; return 0;
} }
/* /*
* parent ".." * parent ".."
*/ */
ctx->pos = 1; ctx->pos = 2;
if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR))
return 0; return 0;
...@@ -3122,22 +3130,23 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -3122,22 +3130,23 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
/* /*
* Legacy filesystem - OS/2 & Linux JFS < 0.3.6 * Legacy filesystem - OS/2 & Linux JFS < 0.3.6
* *
* pn = index = 0: First entry "." * pn = 0; index = 1: First entry "."
* pn = 0; index = 1: Second entry ".." * pn = 0; index = 2: Second entry ".."
* pn > 0: Real entries, pn=1 -> leftmost page * pn > 0: Real entries, pn=1 -> leftmost page
* pn = index = -1: No more entries * pn = index = -1: No more entries
*/ */
dtpos = ctx->pos; dtpos = ctx->pos;
if (dtpos == 0) { if (dtpos < 2) {
/* build "." entry */ /* build "." entry */
ctx->pos = 1;
if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR)) if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR))
return 0; return 0;
dtoffset->index = 1; dtoffset->index = 2;
ctx->pos = dtpos; ctx->pos = dtpos;
} }
if (dtoffset->pn == 0) { if (dtoffset->pn == 0) {
if (dtoffset->index == 1) { if (dtoffset->index == 2) {
/* build ".." entry */ /* build ".." entry */
if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR))
return 0; return 0;
...@@ -3228,6 +3237,12 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -3228,6 +3237,12 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
} }
jfs_dirent->position = unique_pos++; jfs_dirent->position = unique_pos++;
} }
/*
* We add 1 to the index because we may
* use a value of 2 internally, and NFSv4
* doesn't like that.
*/
jfs_dirent->position++;
} else { } else {
jfs_dirent->position = dtpos; jfs_dirent->position = dtpos;
len = min(d_namleft, DTLHDRDATALEN_LEGACY); len = min(d_namleft, DTLHDRDATALEN_LEGACY);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment