From patchwork Sat Aug 17 20:01:31 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Hutchings X-Patchwork-Id: 2846037 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 52598BF546 for ; Sat, 17 Aug 2013 20:02:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4D37320240 for ; Sat, 17 Aug 2013 20:02:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D7F0120136 for ; Sat, 17 Aug 2013 20:02:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754442Ab3HQUCD (ORCPT ); Sat, 17 Aug 2013 16:02:03 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:59897 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754409Ab3HQUCC (ORCPT ); Sat, 17 Aug 2013 16:02:02 -0400 Received: from 80-83-48-229.wifi.dc13.debconf.org ([80.83.48.229] helo=deadeye.wl.decadent.org.uk) by shadbolt.decadent.org.uk with esmtps (TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1VAmgr-0005gh-Sh; Sat, 17 Aug 2013 21:01:38 +0100 Received: from ben by deadeye.wl.decadent.org.uk with local (Exim 4.80) (envelope-from ) id 1VAmgq-0005P4-Lr; Sat, 17 Aug 2013 22:01:36 +0200 Message-ID: <1376769691.2544.4.camel@deadeye.wl.decadent.org.uk> Subject: Re: [PATCH] jfs: fix readdir cookie incompatibility with NFSv4 From: Ben Hutchings To: Karl Schmidt , Jonathan McDowell Cc: Dave Kleikamp , "J. Bruce Fields" , jfs-discussion@lists.sourceforge.net, 714974@bugs.debian.org, linux-nfs@vger.kernel.org, Christian Kujau Date: Sat, 17 Aug 2013 22:01:31 +0200 In-Reply-To: References: <1373245980.3428.46.camel@deadeye.wl.decadent.org.uk> <520554A5.3060401@xtronics.com> <20130812162924.GB2395@fieldses.org> <520C50F7.3010209@oracle.com> <520D3EA7.1010109@oracle.com> X-Mailer: Evolution 3.4.4-3 Mime-Version: 1.0 X-SA-Exim-Connect-IP: 80.83.48.229 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_TVD_MIME_EPI, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Thu, 2013-08-15 at 14:26 -0700, Christian Kujau wrote: > On Thu, 15 Aug 2013 at 15:48, Dave Kleikamp wrote: > > This patch replaces the one I posted yesterday. I like this better since > > it doesn't require fixing existing on-disk cookies or skipping a > > position in the in-inode index table. > > Thanks. Applied to 3.11-rc5 and tested, no more "readdir loop" messages > and with unique inode numbers, great! > > Tested-by: Christian Kujau Karl and Jonathan, could you test the attached backport to 3.2? (Instructions for rebuilding the Debian kernel package are at: ) Ben. Date: Thu, 15 Aug 2013 15:48:39 -0500 From: Dave Kleikamp Subject: jfs: fix readdir cookie incompatibility with NFSv4 This patch replaces the one I posted yesterday. I like this better since it doesn't require fixing existing on-disk cookies or skipping a position in the in-inode index table. 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 [bwh: Backported to 3.2: - Adjust context - s/ctx->pos/filp->f_pos/] Signed-off-by: Ben Hutchings --- 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);