The attached patch takes care of a server-specific problem leading to "short
readdir reply" messages. So far all reported cases of problems (on HP UX 9.5,
10.10, and 10.20 servers) are fixed by these changes.
The patch works by setting a flag in the RPC client structure if a problem is
detected, and then subsequent readdir calls pass the buffer size in longwords.
The patch will therefore have no effect with servers not exhibiting the problem.
I've separated the write-padding changes originally included in this patch, as
that problem is still being worked on.
Regards,
Bill
--------------CB7AC95BF41D15D829A88058
Content-Type: text/plain; charset=us-ascii; name="nfs_readdir89-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="nfs_readdir89-patch"
--- linux-2.1.89/include/linux/nfs_fs.h.old Sat Mar 7 15:10:41 1998
+++ linux-2.1.89/include/linux/nfs_fs.h Sat Mar 7 15:20:57 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.89/fs/nfs/nfs2xdr.c.old Tue Jan 27 09:36:34 1998
+++ linux-2.1.89/fs/nfs/nfs2xdr.c Sat Mar 7 15:20:58 1998
@@ -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)
@@ -334,12 +357,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 +412,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 +429,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.89/include/linux/sunrpc/clnt.h.old Sat Mar 7 11:54:02 1998
+++ linux-2.1.89/include/linux/sunrpc/clnt.h Sat Mar 7 15:23:35 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
--------------CB7AC95BF41D15D829A88058--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu