patch-2.1.90 linux/fs/nfs/nfs2xdr.c
Next file: linux/fs/nls/nls_base.c
Previous file: linux/fs/nfs/inode.c
Back to the patch index
Back to the overall index
- Lines: 128
- Date:
Tue Mar 10 13:26:56 1998
- Orig file:
v2.1.89/linux/fs/nfs/nfs2xdr.c
- Orig date:
Fri Jan 30 11:28:08 1998
diff -u --recursive --new-file v2.1.89/linux/fs/nfs/nfs2xdr.c linux/fs/nfs/nfs2xdr.c
@@ -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,38 @@
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) {
+#if 0
+printk("nfs_writeargs: padding write, len=%d, slen=%d, pad=%d\n",
+req->rq_svec[1].iov_len, req->rq_slen, count);
+#endif
+ 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 +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) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov