Dave Kleikamp <dave.kleikamp@xxxxxxxxxx> writes: > Ben Hutchings backported this patch that has just been picked up in the > mainline kernel for 3.11. It is relevant to and should apply to any > stable kernel between 2.6.32.x and 3.10.x. (Possibly further back, but > does anyone care?) > > Upstream commit: 44512449c0ab368889dd13ae0031fba74ee7e1d2 Thanks. I'm queuing it for the 3.5 kernel. Cheers, -- Luis > > 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 readdir method. > > Signed-off-by: Dave Kleikamp <dave.kleikamp@xxxxxxxxxx> > [bwh: Backported to 3.2: > - Adjust context > - s/ctx->pos/filp->f_pos/] > Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> > --- > fs/jfs/jfs_dtree.c | 31 +++++++++++++++++++++++-------- > 1 file changed, 23 insertions(+), 8 deletions(-) > > diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c > index 8743ba9..0ec767e 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) > > dir_index = (u32) filp->f_pos; > > + /* > + * NFSv4 reserves cookies 1 and 2 for . and .. so we add > + * 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) { > struct dir_table_slot dirtab_slot; > > @@ -3086,7 +3094,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) > if (p->header.flag & BT_INTERNAL) { > jfs_err("jfs_readdir: bad index table"); > DT_PUTPAGE(mp); > - filp->f_pos = -1; > + filp->f_pos = DIREND; > return 0; > } > } else { > @@ -3094,15 +3102,15 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) > /* > * self "." > */ > - filp->f_pos = 0; > + filp->f_pos = 1; > if (filldir(dirent, ".", 1, 0, ip->i_ino, > DT_DIR)) > return 0; > } > /* > * parent ".." > */ > - filp->f_pos = 1; > + filp->f_pos = 2; > if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR)) > return 0; > > @@ -3123,24 +3131,25 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) > /* > * Legacy filesystem - OS/2 & Linux JFS < 0.3.6 > * > - * pn = index = 0: First entry "." > - * pn = 0; index = 1: Second entry ".." > + * pn = 0; index = 1: First entry "." > + * pn = 0; index = 2: Second entry ".." > * pn > 0: Real entries, pn=1 -> leftmost page > * pn = index = -1: No more entries > */ > dtpos = filp->f_pos; > - if (dtpos == 0) { > + if (dtpos < 2) { > /* build "." entry */ > > + filp->f_pos = 1; > if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino, > DT_DIR)) > return 0; > - dtoffset->index = 1; > + dtoffset->index = 2; > filp->f_pos = dtpos; > } > > if (dtoffset->pn == 0) { > - if (dtoffset->index == 1) { > + if (dtoffset->index == 2) { > /* build ".." entry */ > > if (filldir(dirent, "..", 2, filp->f_pos, > @@ -3233,6 +3242,12 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) > } > 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 { > jfs_dirent->position = dtpos; > len = min(d_namleft, DTLHDRDATALEN_LEGACY); > -- > To unsubscribe from this list: send the line "unsubscribe stable" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html