patch-2.2.18 linux/net/sunrpc/xdr.c

Next file: linux/net/sunrpc/xprt.c
Previous file: linux/net/sunrpc/sysctl.c
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/net/sunrpc/xdr.c linux/net/sunrpc/xdr.c
@@ -9,9 +9,11 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/string.h>
+#include <linux/kernel.h>
 #include <linux/in.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/msg_prot.h>
+#include <linux/nfs2.h>
 
 u32	rpc_success, rpc_prog_unavail, rpc_prog_mismatch, rpc_proc_unavail,
 	rpc_garbage_args, rpc_system_err;
@@ -84,11 +86,13 @@
 }
 
 u32 *
-xdr_encode_string(u32 *p, const char *string)
+xdr_encode_string(u32 *p, const char *string, int len)
 {
-	int len = strlen(string);
-	int quadlen = XDR_QUADLEN(len);
+	int quadlen;
 
+	if (len < 0)
+		len = strlen(string);
+	quadlen = XDR_QUADLEN(len);
 	p[quadlen] = 0;
 	*p++ = htonl(len);
 	memcpy(p, string, len);
@@ -116,3 +120,51 @@
 	return p + XDR_QUADLEN(len);
 }
 
+/*
+ * Realign the iovec if the server missed out some reply elements
+ * (such as post-op attributes,...)
+ * Note: This is a simple implementation that assumes that
+ *            len <= iov->iov_len !!!
+ *       The RPC header (assumed to be the 1st element in the iov array)
+ *            is not shifted.
+ */
+void xdr_shift_iovec(struct iovec *iov, int nr, size_t len)
+{
+	struct iovec *pvec;
+
+	for (pvec = iov + nr - 1; nr > 1; nr--, pvec--) {
+		struct iovec *svec = pvec - 1;
+
+		if (len > pvec->iov_len) {
+			printk(KERN_DEBUG "RPC: Urk! Large shift of short iovec.\n");
+			return;
+		}
+		memmove((char *)pvec->iov_base + len, pvec->iov_base,
+			pvec->iov_len - len);
+
+		if (len > svec->iov_len) {
+			printk(KERN_DEBUG "RPC: Urk! Large shift of short iovec.\n");
+			return;
+		}
+		memcpy(pvec->iov_base,
+		       (char *)svec->iov_base + svec->iov_len - len, len);
+	}
+}
+
+/*
+ * Zero the last n bytes in an iovec array of 'nr' elements
+ */
+void xdr_zero_iovec(struct iovec *iov, int nr, size_t n)
+{
+	struct iovec *pvec;
+
+	for (pvec = iov + nr - 1; n && nr > 0; nr--, pvec--) {
+		if (n < pvec->iov_len) {
+			memset((char *)pvec->iov_base + pvec->iov_len - n, 0, n);
+			n = 0;
+		} else {
+			memset(pvec->iov_base, 0, pvec->iov_len);
+			n -= pvec->iov_len;
+		}
+	}
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)