lkml.org 
[lkml]   [1998]   [Mar]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subjectupdated patch for 2.1.89 nfs write padding
Based on further analysis of the iovec copy/checksum code, I think the attached
patch may correct the problem with adding pad bytes to NFS writes. The iovec
code was incorrectly exiting too soon in the case where a short non-longword
multiple iovec was followed by another iovec, leading to an incorrect checksum
(and truncated data, for that matter.)

This would occur frequently when a padding iovec was added, and the incorrect
checksums were then being reported as "RPC task timed out" errors on the client
side.

I'd appreciate it if the people who can trigger the "task timed out" messages
could give this a test and see if both the original 'garbage args" and checksum
problems are fixed.

Regards,
Bill--- 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
@@ -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 */

@@ -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;
}

--- linux-2.1.89/net/core/iovec.c.old Sat Mar 7 11:32:22 1998
+++ linux-2.1.89/net/core/iovec.c Sat Mar 7 15:28:17 1998
@@ -80,6 +80,8 @@

/*
* Copy kernel to iovec.
+ *
+ * Note: this modifies the original iovec.
*/

int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
@@ -107,6 +109,8 @@

/*
* Copy iovec to kernel.
+ *
+ * Note: this modifies the original iovec.
*/

int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
@@ -187,9 +191,8 @@
* call to this function will be unaligned also.
*/

-int csum_partial_copy_fromiovecend(unsigned char *kdata,
- struct iovec *iov, int offset,
- unsigned int len, int *csump)
+int csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov,
+ int offset, unsigned int len, int *csump)
{
int partial_cnt = 0;
int err = 0;
@@ -246,9 +249,9 @@
if (copy_from_user(kdata, base, copy))
goto out_fault;
kdata += copy;
- base += copy;
+ base += copy;
partial_cnt += copy;
- len -= copy;
+ len -= copy;
iov++;
if (len)
continue;
@@ -260,9 +263,9 @@
goto out_fault;
csum = csum_partial(kdata - partial_cnt, 4, csum);
kdata += par_len;
- base += par_len;
- copy -= par_len;
- len -= par_len;
+ base += par_len;
+ copy -= par_len;
+ len -= par_len;
partial_cnt = 0;
}

@@ -278,16 +281,12 @@
}
}

- /* Why do we want to break?? There may be more to copy ... */
- if (copy == 0) {
-if (len > partial_cnt)
-printk("csum_iovec: early break? len=%d, partial=%d\n", len, partial_cnt);
- break;
+ if (copy) {
+ csum = csum_and_copy_from_user(base, kdata, copy,
+ csum, &err);
+ if (err)
+ goto out;
}
-
- csum = csum_and_copy_from_user(base, kdata, copy, csum, &err);
- if (err)
- goto out;
len -= copy + partial_cnt;
kdata += copy + partial_cnt;
iov++;
\
 
 \ /
  Last update: 2005-03-22 13:41    [W:0.720 / U:0.084 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site