--- /dev/null
+From 44512449c0ab368889dd13ae0031fba74ee7e1d2 Mon Sep 17 00:00:00 2001
+From: Dave Kleikamp <dave.kleikamp@oracle.com>
+Date: Thu, 15 Aug 2013 15:36:49 -0500
+Subject: jfs: fix readdir cookie incompatibility with NFSv4
+
+From: Dave Kleikamp <dave.kleikamp@oracle.com>
+
+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>
+---
+ fs/jfs/jfs_dtree.c | 31 +++++++++++++++++++++++--------
+ 1 file changed, 23 insertions(+), 8 deletions(-)
+
+--- a/fs/jfs/jfs_dtree.c
++++ b/fs/jfs/jfs_dtree.c
+@@ -3047,6 +3047,14 @@ int jfs_readdir(struct file *filp, void
+
+ 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 *filp, void
+ 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,7 +3102,7 @@ int jfs_readdir(struct file *filp, void
+ /*
+ * self "."
+ */
+- filp->f_pos = 0;
++ filp->f_pos = 1;
+ if (filldir(dirent, ".", 1, 0, ip->i_ino,
+ DT_DIR))
+ return 0;
+@@ -3102,7 +3110,7 @@ int jfs_readdir(struct file *filp, void
+ /*
+ * 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 *filp, void
+ /*
+ * 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 *filp, void
+ }
+ 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);