Re: nfs client probs 2.1.* (Patch attached)

Bill Hawes (whawes@star.net)
Fri, 20 Feb 1998 17:50:27 -0500


This is a multi-part message in MIME format.
--------------B4B39ABEB46B90A3E1C58EFA
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hans-Christoph Rohland wrote:

> I get the following syslog entries (2.1.87)
>
> Feb 19 18:46:41 kernel: NFS: short readdir reply! nr=170, slots=3, len=7
> Feb 19 18:46:52 kernel: NFS: short readdir reply! nr=170, slots=3, len=7
> Feb 20 03:37:00 kernel: NFS: short readdir reply! nr=170, slots=3, len=7
> Feb 20 09:30:04 kernel: RPC: garbage, retrying 33342
> Feb 20 09:30:04 kernel: RPC: garbage, retrying 33342
> Feb 20 09:30:04 kernel: RPC: garbage, exit EIO
>
> The first three did not show up in an interactive program, but the
> last three are xemacs trying to save a file, which failes with EIO.
>
> The server is a HP-UX box. I do not know the release.

Hi Hans,

I've attached a patch for 2.1.87 NFS client that will probably fix the "short
reply" problem, and possibly the other problem as well. A similar problem was
reported by another user with an HP-UX server and the patch works in that case.

I'm hoping to get in touch with the appropriate engineer at HP to discuss this
problem, as it appears to be a bug in their server. So if you have a tech
contact at HP who would like to improve the quality of their software, please
pass me an email address.

In the case of your "RPC garbage" problem, it this repeatable? Does it only
happen with xemacs, and can you copy files OK? The patch includes a fix to pad
writes to a longword length, which fixes garbage args problems with some
servers. You'll have to enable it by hand though by uncommenting the #define at
the top.

Please let me know if this helps out with the problems.

Regards,
Bill
--------------B4B39ABEB46B90A3E1C58EFA
Content-Type: text/plain; charset=us-ascii; name="nfs_87-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="nfs_87-patch"

--- linux-2.1.87/include/linux/nfs_fs.h.old Tue Jan 27 09:36:36 1998
+++ linux-2.1.87/include/linux/nfs_fs.h Wed Feb 18 12:26:11 1998
@@ -85,6 +85,9 @@
*/
#define NFS_RPC_SWAPFLAGS (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS)

+/* Flags in the RPC client structure */
+#define NFS_CLNTF_BUFSIZE 0x0001 /* readdir buffer in longwords */
+
#ifdef __KERNEL__

/*
--- linux-2.1.87/fs/nfs/nfs2xdr.c.old Tue Jan 27 09:36:34 1998
+++ linux-2.1.87/fs/nfs/nfs2xdr.c Wed Feb 18 12:49:59 1998
@@ -22,6 +22,9 @@
#include <linux/sunrpc/clnt.h>
#include <linux/nfs_fs.h>

+/* Uncomment this to support servers requiring longword lengths */
+/* #define NFS_PAD_WRITES 1 */
+
#define NFSDBG_FACILITY NFSDBG_XDR
/* #define NFS_PARANOIA 1 */

@@ -181,7 +184,7 @@
/*
* Arguments to a READ call. Since we read data directly into the page
* cache, we also set up the reply iovec here so that iov[1] points
- * exactly to the page wewant to fetch.
+ * exactly to the page we want to fetch.
*/
static int
nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
@@ -258,18 +261,34 @@
static int
nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
{
+ u32 count = args->count;
+
p = xdr_encode_fhandle(p, args->fh);
*p++ = htonl(args->offset);
*p++ = htonl(args->offset);
- *p++ = htonl(args->count);
- *p++ = htonl(args->count);
+ *p++ = htonl(count);
+ *p++ = htonl(count);
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);

req->rq_svec[1].iov_base = (void *) args->buffer;
- req->rq_svec[1].iov_len = args->count;
- req->rq_slen += args->count;
+ req->rq_svec[1].iov_len = count;
+ req->rq_slen += count;
req->rq_snr = 2;

+#ifdef NFS_PAD_WRITES
+ /*
+ * Some old servers require that the message length
+ * be a multiple of 4, so we pad it here if needed.
+ */
+ count = ((count + 3) & ~3) - count;
+ if (count) {
+ req->rq_svec[2].iov_base = (void *) "\0\0\0";
+ req->rq_svec[2].iov_len = count;
+ req->rq_slen += count;
+ req->rq_snr = 3;
+ }
+#endif
+
return 0;
}

@@ -334,12 +353,21 @@
static int
nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_task *task = req->rq_task;
+ struct rpc_auth *auth = task->tk_auth;
+ u32 bufsiz = args->bufsiz;
int replen;

+ /*
+ * Some servers (e.g. HP OS 9.5) seem to expect the buffer size
+ * to be in longwords ... check whether to convert the size.
+ */
+ if (task->tk_client->cl_flags & NFS_CLNTF_BUFSIZE)
+ bufsiz = bufsiz >> 2;
+
p = xdr_encode_fhandle(p, args->fh);
*p++ = htonl(args->cookie);
- *p++ = htonl(args->bufsiz);
+ *p++ = htonl(bufsiz); /* see above */
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);

/* set up reply iovec */
@@ -380,10 +408,9 @@
nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs_readdirres *res)
{
struct iovec *iov = req->rq_rvec;
- int status, nr, len;
+ int status, nr;
char *string, *start;
- u32 *end;
- __u32 fileid, cookie, *entry;
+ u32 *end, *entry, len, fileid, cookie;

if ((status = ntohl(*p++)))
return -nfs_stat_to_errno(status);
@@ -398,17 +425,25 @@
end = (u32 *) ((u8 *) p + iov[1].iov_len);

/* Get start and end of dirent buffer */
- entry = (__u32 *) res->buffer;
+ entry = (u32 *) res->buffer;
start = (char *) res->buffer;
string = (char *) res->buffer + res->bufsiz;
for (nr = 0; *p++; nr++) {
fileid = ntohl(*p++);

len = ntohl(*p++);
+ /*
+ * Check whether the server has exceeded our reply buffer,
+ * and set a flag to convert the size to longwords.
+ */
if ((p + QUADLEN(len) + 3) > end) {
- printk(KERN_WARNING "NFS: short readdir reply! "
- "nr=%d, slots=%d, len=%d\n",
+ struct rpc_clnt *clnt = req->rq_task->tk_client;
+ printk(KERN_WARNING
+ "NFS: server %s, readdir reply truncated\n",
+ clnt->cl_server);
+ printk(KERN_WARNING "NFS: nr=%d, slots=%d, len=%d\n",
nr, (end - p), len);
+ clnt->cl_flags |= NFS_CLNTF_BUFSIZE;
break;
}
if (len > NFS_MAXNAMLEN) {
--- linux-2.1.87/include/linux/sunrpc/clnt.h.old Tue Feb 17 11:26:40 1998
+++ linux-2.1.87/include/linux/sunrpc/clnt.h Wed Feb 18 12:39:39 1998
@@ -30,6 +30,7 @@
* The high-level client handle
*/
struct rpc_clnt {
+ unsigned int cl_users; /* number of references */
struct rpc_xprt * cl_xprt; /* transport */
struct rpc_procinfo * cl_procinfo; /* procedure info */
u32 cl_maxproc; /* max procedure number */
@@ -37,7 +38,6 @@
char * cl_server; /* server machine name */
char * cl_protname; /* protocol name */
struct rpc_auth * cl_auth; /* authenticator */
- struct rpc_portmap cl_pmap; /* port mapping */
struct rpc_stat * cl_stats; /* statistics */

unsigned int cl_softrtry : 1,/* soft timeouts */
@@ -47,10 +47,11 @@
cl_binding : 1,/* doing a getport() */
cl_oneshot : 1,/* dispose after use */
cl_dead : 1;/* abandoned */
+ unsigned int cl_flags; /* misc client flags */
unsigned long cl_hardmax; /* max hard timeout */

+ struct rpc_portmap cl_pmap; /* port mapping */
struct rpc_wait_queue cl_bindwait; /* waiting on getport() */
- unsigned int cl_users; /* number of references */
};
#define cl_timeout cl_xprt->timeout
#define cl_prog cl_pmap.pm_prog

--------------B4B39ABEB46B90A3E1C58EFA--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu