patch-2.4.21 linux-2.4.21/net/sunrpc/xdr.c
Next file: linux-2.4.21/net/sunrpc/xprt.c
Previous file: linux-2.4.21/net/sunrpc/sysctl.c
Back to the patch index
Back to the overall index
- Lines: 95
- Date:
2003-06-13 07:51:39.000000000 -0700
- Orig file:
linux-2.4.20/net/sunrpc/xdr.c
- Orig date:
2002-11-28 15:53:16.000000000 -0800
diff -urN linux-2.4.20/net/sunrpc/xdr.c linux-2.4.21/net/sunrpc/xdr.c
@@ -180,7 +180,7 @@
{
struct iovec *iov = iov_base;
struct page **ppage = xdr->pages;
- unsigned int len, pglen = xdr->page_len;
+ unsigned int len, pglen = xdr->page_len, first_kmap;
len = xdr->head[0].iov_len;
if (base < len) {
@@ -203,9 +203,17 @@
ppage += base >> PAGE_CACHE_SHIFT;
base &= ~PAGE_CACHE_MASK;
}
+ first_kmap = 1;
do {
len = PAGE_CACHE_SIZE;
- iov->iov_base = kmap(*ppage);
+ if (first_kmap) {
+ first_kmap = 0;
+ iov->iov_base = kmap(*ppage);
+ } else {
+ iov->iov_base = kmap_nonblock(*ppage);
+ if (!iov->iov_base)
+ goto out;
+ }
if (base) {
iov->iov_base += base;
len -= base;
@@ -223,20 +231,23 @@
iov->iov_base = (char *)xdr->tail[0].iov_base + base;
iov++;
}
+ out:
return (iov - iov_base);
}
-void xdr_kunmap(struct xdr_buf *xdr, unsigned int base)
+void xdr_kunmap(struct xdr_buf *xdr, unsigned int base, int niov)
{
struct page **ppage = xdr->pages;
unsigned int pglen = xdr->page_len;
if (!pglen)
return;
- if (base > xdr->head[0].iov_len)
+ if (base >= xdr->head[0].iov_len)
base -= xdr->head[0].iov_len;
- else
+ else {
+ niov--;
base = 0;
+ }
if (base >= pglen)
return;
@@ -250,7 +261,11 @@
* we bump pglen here, and just subtract PAGE_CACHE_SIZE... */
pglen += base & ~PAGE_CACHE_MASK;
}
- for (;;) {
+ /*
+ * In case we could only do a partial xdr_kmap, all remaining iovecs
+ * refer to pages. Otherwise we detect the end through pglen.
+ */
+ for (; niov; niov--) {
flush_dcache_page(*ppage);
kunmap(*ppage);
if (pglen <= PAGE_CACHE_SIZE)
@@ -322,9 +337,22 @@
xdr_shift_buf(struct xdr_buf *xdr, size_t len)
{
struct iovec iov[MAX_IOVEC];
- unsigned int nr;
+ unsigned int nr, len_part, n, skip;
+
+ skip = 0;
+ do {
+
+ nr = xdr_kmap(iov, xdr, skip);
+
+ len_part = 0;
+ for (n = 0; n < nr; n++)
+ len_part += iov[n].iov_len;
+
+ xdr_shift_iovec(iov, nr, len_part);
+
+ xdr_kunmap(xdr, skip, nr);
- nr = xdr_kmap(iov, xdr, 0);
- xdr_shift_iovec(iov, nr, len);
- xdr_kunmap(xdr, 0);
+ skip += len_part;
+ len -= len_part;
+ } while (len);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)