+static int
+nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ const char *name, int namlen, u32 *p, int *buflen)
+{
+ struct svc_export *exp = cd->rd_fhp->fh_export;
+ struct dentry *dentry;
+ int nfserr;
+
+ dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
+ if (IS_ERR(dentry))
+ return nfserrno(PTR_ERR(dentry));
+
+ exp_get(exp);
+ if (d_mountpoint(dentry)) {
+ if (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.
+ */
+ nfserr = nfserr_dropit;
+ goto out_put;
+ }
+
+ }
+ nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
+ cd->rd_rqstp);
+out_put:
+ dput(dentry);
+ exp_put(exp);
+ return nfserr;
+}
+
+static u32 *
+nfsd4_encode_rdattr_error(u32 *p, int buflen, int nfserr)
+{
+ u32 *attrlenp;
+
+ if (buflen < 6)
+ return NULL;
+ *p++ = htonl(2);
+ *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */
+ *p++ = htonl(0); /* bmval1 */
+
+ attrlenp = p++;
+ *p++ = nfserr; /* no htonl */
+ *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
+ return p;
+}
+