From: NeilBrown <neilb@cse.unsw.edu.au>

No sensible client is ever going to request only the RDATTR_ERROR attribute, so
there's no point optimizing for that case.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/nfsd/nfs4xdr.c |  106 ++++++++++++++++++++--------------------------
 1 files changed, 47 insertions(+), 59 deletions(-)

diff -puN fs/nfsd/nfs4xdr.c~knfsd-nfsd4-encode_dirent-cleanup fs/nfsd/nfs4xdr.c
--- 25/fs/nfsd/nfs4xdr.c~knfsd-nfsd4-encode_dirent-cleanup	2004-11-15 22:07:10.230033800 -0800
+++ 25-akpm/fs/nfsd/nfs4xdr.c	2004-11-15 22:07:10.248031064 -0800
@@ -1805,73 +1805,62 @@ nfsd4_encode_dirent(struct readdir_cd *c
 	 */
 	bmval0 = cd->rd_bmval[0];
 	bmval1 = cd->rd_bmval[1];
-	if ((bmval0 & ~(FATTR4_WORD0_RDATTR_ERROR)) || bmval1)  {
-		/*
-		 * "Heavyweight" case: we have no choice except to
-		 * call nfsd4_encode_fattr(). 
-		 */
-		dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
-		if (IS_ERR(dentry)) {
-			nfserr = nfserrno(PTR_ERR(dentry));
-			goto error;
-		}
-
-		exp_get(exp);
-		if (d_mountpoint(dentry)) {
-			if ((nfserr = nfsd_cross_mnt(cd->rd_rqstp, &dentry, 
-					 &exp))) {	
-			/* 
-			 * -EAGAIN is the only error returned from 
-			 * nfsd_cross_mnt() and it indicates that an 
-			 * up-call has  been initiated to fill in the export 
-			 * options on exp.  When the answer comes back,
-			 * this call will be retried.
-			 */
-				dput(dentry);
-				exp_put(exp);
-				nfserr = nfserr_dropit;
-				goto error;
-			}
 
-		}
-
-		nfserr = nfsd4_encode_fattr(NULL, exp,
-				dentry, p, &buflen, cd->rd_bmval,
-				cd->rd_rqstp);
-		dput(dentry);
-		exp_put(exp);
-		if (!nfserr) {
-			p += buflen;
-			goto out;
-		}
-		if (nfserr == nfserr_resource)
-			goto nospc;
+	dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
+	if (IS_ERR(dentry)) {
+		nfserr = nfserrno(PTR_ERR(dentry));
+		goto error;
+	}
 
-error:
+	exp_get(exp);
+	if (d_mountpoint(dentry)) {
+		if ((nfserr = nfsd_cross_mnt(cd->rd_rqstp, &dentry,
+				 &exp))) {
 		/*
-		 * If we get here, we experienced a miscellaneous
-		 * failure while writing the attributes.  If the
-		 * client requested the RDATTR_ERROR attribute,
-		 * we stuff the error code into this attribute
-		 * and continue.  If this attribute was not requested,
-		 * then in accordance with the spec, we fail the
-		 * entire READDIR operation(!)
+		 * -EAGAIN is the only error returned from
+		 * nfsd_cross_mnt() and it indicates that an
+		 * up-call has  been initiated to fill in the export
+		 * options on exp.  When the answer comes back,
+		 * this call will be retried.
 		 */
-		if (!(bmval0 & FATTR4_WORD0_RDATTR_ERROR)) {
-			cd->common.err = nfserr;
-			return -EINVAL;
+			dput(dentry);
+			exp_put(exp);
+			nfserr = nfserr_dropit;
+			goto error;
 		}
 
-		bmval0 = FATTR4_WORD0_RDATTR_ERROR;
-		bmval1 = 0;
-		/* falling through here will do the right thing... */
 	}
 
+	nfserr = nfsd4_encode_fattr(NULL, exp,
+			dentry, p, &buflen, cd->rd_bmval,
+			cd->rd_rqstp);
+	dput(dentry);
+	exp_put(exp);
+	if (!nfserr) {
+		p += buflen;
+		goto out;
+	}
+	if (nfserr == nfserr_resource)
+		goto nospc;
+
+error:
 	/*
-	 * In the common "lightweight" case, we avoid
-	 * the overhead of nfsd4_encode_fattr() by assembling
-	 * a small fattr by hand.
+	 * If we get here, we experienced a miscellaneous
+	 * failure while writing the attributes.  If the
+	 * client requested the RDATTR_ERROR attribute,
+	 * we stuff the error code into this attribute
+	 * and continue.  If this attribute was not requested,
+	 * then in accordance with the spec, we fail the
+	 * entire READDIR operation(!)
 	 */
+	if (!(bmval0 & FATTR4_WORD0_RDATTR_ERROR)) {
+		cd->common.err = nfserr;
+		return -EINVAL;
+	}
+
+	bmval0 = FATTR4_WORD0_RDATTR_ERROR;
+	bmval1 = 0;
+
 	if (buflen < 6)
 		goto nospc;
 	*p++ = htonl(2);
@@ -1879,8 +1868,7 @@ error:
 	*p++ = htonl(bmval1);
 
 	attrlenp = p++;
-	if (bmval0 & FATTR4_WORD0_RDATTR_ERROR)
-		*p++ = nfserr;       /* no htonl */
+	*p++ = nfserr;       /* no htonl */
 	*attrlenp = htonl((char *)p - (char *)attrlenp - 4);
 
 out:
_