diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 22:16:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 22:16:57 -0400 |
commit | 1fad1e9a747687a7399bf58e87974f9b1bbcae06 (patch) | |
tree | fde2dc9a35321e21c99e06d4b79d5fa06fd34679 /net/sunrpc | |
parent | bbeb0af25f493261c15ceee176c99b7fd6fd5479 (diff) | |
parent | f44106e2173f08ccb1c9195d85a6c22388b461c1 (diff) |
Merge tag 'nfs-for-3.6-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust:
"Features include:
- More preparatory patches for modularising NFSv2/v3/v4. Split out
the various NFSv2/v3/v4-specific code into separate files
- More preparation for the NFSv4 migration code
- Ensure that OPEN(O_CREATE) observes the pNFS mds threshold
parameters
- pNFS fast failover when the data servers are down
- Various cleanups and debugging patches"
* tag 'nfs-for-3.6-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (67 commits)
nfs: fix fl_type tests in NFSv4 code
NFS: fix pnfs regression with directio writes
NFS: fix pnfs regression with directio reads
sunrpc: clnt: Add missing braces
nfs: fix stub return type warnings
NFS: exit_nfs_v4() shouldn't be an __exit function
SUNRPC: Add a missing spin_unlock to gss_mech_list_pseudoflavors
NFS: Split out NFS v4 client functions
NFS: Split out the NFS v4 filesystem types
NFS: Create a single nfs_clone_super() function
NFS: Split out NFS v4 server creating code
NFS: Initialize the NFS v4 client from init_nfs_v4()
NFS: Move the v4 getroot code to nfs4getroot.c
NFS: Split out NFS v4 file operations
NFS: Initialize v4 sysctls from nfs_init_v4()
NFS: Create an init_nfs_v4() function
NFS: Split out NFS v4 inode operations
NFS: Split out NFS v3 inode operations
NFS: Split out NFS v2 inode operations
NFS: Clean up nfs4_proc_setclientid() and friends
...
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth.c | 54 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 1 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_mech_switch.c | 20 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 3 | ||||
-rw-r--r-- | net/sunrpc/xdr.c | 127 |
5 files changed, 142 insertions, 63 deletions
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 727e506cacda..b5c067bccc45 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/hash.h> | 14 | #include <linux/hash.h> |
15 | #include <linux/sunrpc/clnt.h> | 15 | #include <linux/sunrpc/clnt.h> |
16 | #include <linux/sunrpc/gss_api.h> | ||
16 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
17 | 18 | ||
18 | #ifdef RPC_DEBUG | 19 | #ifdef RPC_DEBUG |
@@ -122,6 +123,59 @@ rpcauth_unregister(const struct rpc_authops *ops) | |||
122 | } | 123 | } |
123 | EXPORT_SYMBOL_GPL(rpcauth_unregister); | 124 | EXPORT_SYMBOL_GPL(rpcauth_unregister); |
124 | 125 | ||
126 | /** | ||
127 | * rpcauth_list_flavors - discover registered flavors and pseudoflavors | ||
128 | * @array: array to fill in | ||
129 | * @size: size of "array" | ||
130 | * | ||
131 | * Returns the number of array items filled in, or a negative errno. | ||
132 | * | ||
133 | * The returned array is not sorted by any policy. Callers should not | ||
134 | * rely on the order of the items in the returned array. | ||
135 | */ | ||
136 | int | ||
137 | rpcauth_list_flavors(rpc_authflavor_t *array, int size) | ||
138 | { | ||
139 | rpc_authflavor_t flavor; | ||
140 | int result = 0; | ||
141 | |||
142 | spin_lock(&rpc_authflavor_lock); | ||
143 | for (flavor = 0; flavor < RPC_AUTH_MAXFLAVOR; flavor++) { | ||
144 | const struct rpc_authops *ops = auth_flavors[flavor]; | ||
145 | rpc_authflavor_t pseudos[4]; | ||
146 | int i, len; | ||
147 | |||
148 | if (result >= size) { | ||
149 | result = -ENOMEM; | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | if (ops == NULL) | ||
154 | continue; | ||
155 | if (ops->list_pseudoflavors == NULL) { | ||
156 | array[result++] = ops->au_flavor; | ||
157 | continue; | ||
158 | } | ||
159 | len = ops->list_pseudoflavors(pseudos, ARRAY_SIZE(pseudos)); | ||
160 | if (len < 0) { | ||
161 | result = len; | ||
162 | break; | ||
163 | } | ||
164 | for (i = 0; i < len; i++) { | ||
165 | if (result >= size) { | ||
166 | result = -ENOMEM; | ||
167 | break; | ||
168 | } | ||
169 | array[result++] = pseudos[i]; | ||
170 | } | ||
171 | } | ||
172 | spin_unlock(&rpc_authflavor_lock); | ||
173 | |||
174 | dprintk("RPC: %s returns %d\n", __func__, result); | ||
175 | return result; | ||
176 | } | ||
177 | EXPORT_SYMBOL_GPL(rpcauth_list_flavors); | ||
178 | |||
125 | struct rpc_auth * | 179 | struct rpc_auth * |
126 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) | 180 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) |
127 | { | 181 | { |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index d3ad81f8da5b..34c522021004 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -1619,6 +1619,7 @@ static const struct rpc_authops authgss_ops = { | |||
1619 | .crcreate = gss_create_cred, | 1619 | .crcreate = gss_create_cred, |
1620 | .pipes_create = gss_pipes_dentries_create, | 1620 | .pipes_create = gss_pipes_dentries_create, |
1621 | .pipes_destroy = gss_pipes_dentries_destroy, | 1621 | .pipes_destroy = gss_pipes_dentries_destroy, |
1622 | .list_pseudoflavors = gss_mech_list_pseudoflavors, | ||
1622 | }; | 1623 | }; |
1623 | 1624 | ||
1624 | static const struct rpc_credops gss_credops = { | 1625 | static const struct rpc_credops gss_credops = { |
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index 782bfe1b6465..b174fcd9ff4c 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c | |||
@@ -239,14 +239,28 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor) | |||
239 | 239 | ||
240 | EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); | 240 | EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); |
241 | 241 | ||
242 | int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr) | 242 | /** |
243 | * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors | ||
244 | * @array: array to fill in | ||
245 | * @size: size of "array" | ||
246 | * | ||
247 | * Returns the number of array items filled in, or a negative errno. | ||
248 | * | ||
249 | * The returned array is not sorted by any policy. Callers should not | ||
250 | * rely on the order of the items in the returned array. | ||
251 | */ | ||
252 | int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr, int size) | ||
243 | { | 253 | { |
244 | struct gss_api_mech *pos = NULL; | 254 | struct gss_api_mech *pos = NULL; |
245 | int j, i = 0; | 255 | int j, i = 0; |
246 | 256 | ||
247 | spin_lock(®istered_mechs_lock); | 257 | spin_lock(®istered_mechs_lock); |
248 | list_for_each_entry(pos, ®istered_mechs, gm_list) { | 258 | list_for_each_entry(pos, ®istered_mechs, gm_list) { |
249 | for (j=0; j < pos->gm_pf_num; j++) { | 259 | for (j = 0; j < pos->gm_pf_num; j++) { |
260 | if (i >= size) { | ||
261 | spin_unlock(®istered_mechs_lock); | ||
262 | return -ENOMEM; | ||
263 | } | ||
250 | array_ptr[i++] = pos->gm_pfs[j].pseudoflavor; | 264 | array_ptr[i++] = pos->gm_pfs[j].pseudoflavor; |
251 | } | 265 | } |
252 | } | 266 | } |
@@ -254,8 +268,6 @@ int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr) | |||
254 | return i; | 268 | return i; |
255 | } | 269 | } |
256 | 270 | ||
257 | EXPORT_SYMBOL_GPL(gss_mech_list_pseudoflavors); | ||
258 | |||
259 | u32 | 271 | u32 |
260 | gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) | 272 | gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) |
261 | { | 273 | { |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 00eb859b7de5..b05df36692ff 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -1844,12 +1844,13 @@ call_timeout(struct rpc_task *task) | |||
1844 | return; | 1844 | return; |
1845 | } | 1845 | } |
1846 | if (RPC_IS_SOFT(task)) { | 1846 | if (RPC_IS_SOFT(task)) { |
1847 | if (clnt->cl_chatty) | 1847 | if (clnt->cl_chatty) { |
1848 | rcu_read_lock(); | 1848 | rcu_read_lock(); |
1849 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | 1849 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
1850 | clnt->cl_protname, | 1850 | clnt->cl_protname, |
1851 | rcu_dereference(clnt->cl_xprt)->servername); | 1851 | rcu_dereference(clnt->cl_xprt)->servername); |
1852 | rcu_read_unlock(); | 1852 | rcu_read_unlock(); |
1853 | } | ||
1853 | if (task->tk_flags & RPC_TASK_TIMEOUT) | 1854 | if (task->tk_flags & RPC_TASK_TIMEOUT) |
1854 | rpc_exit(task, -ETIMEDOUT); | 1855 | rpc_exit(task, -ETIMEDOUT); |
1855 | else | 1856 | else |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 0cf165580d8d..0afba1b4b656 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -129,34 +129,6 @@ xdr_terminate_string(struct xdr_buf *buf, const u32 len) | |||
129 | EXPORT_SYMBOL_GPL(xdr_terminate_string); | 129 | EXPORT_SYMBOL_GPL(xdr_terminate_string); |
130 | 130 | ||
131 | void | 131 | void |
132 | xdr_encode_pages(struct xdr_buf *xdr, struct page **pages, unsigned int base, | ||
133 | unsigned int len) | ||
134 | { | ||
135 | struct kvec *tail = xdr->tail; | ||
136 | u32 *p; | ||
137 | |||
138 | xdr->pages = pages; | ||
139 | xdr->page_base = base; | ||
140 | xdr->page_len = len; | ||
141 | |||
142 | p = (u32 *)xdr->head[0].iov_base + XDR_QUADLEN(xdr->head[0].iov_len); | ||
143 | tail->iov_base = p; | ||
144 | tail->iov_len = 0; | ||
145 | |||
146 | if (len & 3) { | ||
147 | unsigned int pad = 4 - (len & 3); | ||
148 | |||
149 | *p = 0; | ||
150 | tail->iov_base = (char *)p + (len & 3); | ||
151 | tail->iov_len = pad; | ||
152 | len += pad; | ||
153 | } | ||
154 | xdr->buflen += len; | ||
155 | xdr->len += len; | ||
156 | } | ||
157 | EXPORT_SYMBOL_GPL(xdr_encode_pages); | ||
158 | |||
159 | void | ||
160 | xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, | 132 | xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, |
161 | struct page **pages, unsigned int base, unsigned int len) | 133 | struct page **pages, unsigned int base, unsigned int len) |
162 | { | 134 | { |
@@ -457,6 +429,16 @@ xdr_shift_buf(struct xdr_buf *buf, size_t len) | |||
457 | EXPORT_SYMBOL_GPL(xdr_shift_buf); | 429 | EXPORT_SYMBOL_GPL(xdr_shift_buf); |
458 | 430 | ||
459 | /** | 431 | /** |
432 | * xdr_stream_pos - Return the current offset from the start of the xdr_stream | ||
433 | * @xdr: pointer to struct xdr_stream | ||
434 | */ | ||
435 | unsigned int xdr_stream_pos(const struct xdr_stream *xdr) | ||
436 | { | ||
437 | return (unsigned int)(XDR_QUADLEN(xdr->buf->len) - xdr->nwords) << 2; | ||
438 | } | ||
439 | EXPORT_SYMBOL_GPL(xdr_stream_pos); | ||
440 | |||
441 | /** | ||
460 | * xdr_init_encode - Initialize a struct xdr_stream for sending data. | 442 | * xdr_init_encode - Initialize a struct xdr_stream for sending data. |
461 | * @xdr: pointer to xdr_stream struct | 443 | * @xdr: pointer to xdr_stream struct |
462 | * @buf: pointer to XDR buffer in which to encode data | 444 | * @buf: pointer to XDR buffer in which to encode data |
@@ -556,13 +538,11 @@ void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, unsigned int b | |||
556 | EXPORT_SYMBOL_GPL(xdr_write_pages); | 538 | EXPORT_SYMBOL_GPL(xdr_write_pages); |
557 | 539 | ||
558 | static void xdr_set_iov(struct xdr_stream *xdr, struct kvec *iov, | 540 | static void xdr_set_iov(struct xdr_stream *xdr, struct kvec *iov, |
559 | __be32 *p, unsigned int len) | 541 | unsigned int len) |
560 | { | 542 | { |
561 | if (len > iov->iov_len) | 543 | if (len > iov->iov_len) |
562 | len = iov->iov_len; | 544 | len = iov->iov_len; |
563 | if (p == NULL) | 545 | xdr->p = (__be32*)iov->iov_base; |
564 | p = (__be32*)iov->iov_base; | ||
565 | xdr->p = p; | ||
566 | xdr->end = (__be32*)(iov->iov_base + len); | 546 | xdr->end = (__be32*)(iov->iov_base + len); |
567 | xdr->iov = iov; | 547 | xdr->iov = iov; |
568 | xdr->page_ptr = NULL; | 548 | xdr->page_ptr = NULL; |
@@ -609,7 +589,7 @@ static void xdr_set_next_page(struct xdr_stream *xdr) | |||
609 | newbase -= xdr->buf->page_base; | 589 | newbase -= xdr->buf->page_base; |
610 | 590 | ||
611 | if (xdr_set_page_base(xdr, newbase, PAGE_SIZE) < 0) | 591 | if (xdr_set_page_base(xdr, newbase, PAGE_SIZE) < 0) |
612 | xdr_set_iov(xdr, xdr->buf->tail, NULL, xdr->buf->len); | 592 | xdr_set_iov(xdr, xdr->buf->tail, xdr->buf->len); |
613 | } | 593 | } |
614 | 594 | ||
615 | static bool xdr_set_next_buffer(struct xdr_stream *xdr) | 595 | static bool xdr_set_next_buffer(struct xdr_stream *xdr) |
@@ -618,7 +598,7 @@ static bool xdr_set_next_buffer(struct xdr_stream *xdr) | |||
618 | xdr_set_next_page(xdr); | 598 | xdr_set_next_page(xdr); |
619 | else if (xdr->iov == xdr->buf->head) { | 599 | else if (xdr->iov == xdr->buf->head) { |
620 | if (xdr_set_page_base(xdr, 0, PAGE_SIZE) < 0) | 600 | if (xdr_set_page_base(xdr, 0, PAGE_SIZE) < 0) |
621 | xdr_set_iov(xdr, xdr->buf->tail, NULL, xdr->buf->len); | 601 | xdr_set_iov(xdr, xdr->buf->tail, xdr->buf->len); |
622 | } | 602 | } |
623 | return xdr->p != xdr->end; | 603 | return xdr->p != xdr->end; |
624 | } | 604 | } |
@@ -634,10 +614,15 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p) | |||
634 | xdr->buf = buf; | 614 | xdr->buf = buf; |
635 | xdr->scratch.iov_base = NULL; | 615 | xdr->scratch.iov_base = NULL; |
636 | xdr->scratch.iov_len = 0; | 616 | xdr->scratch.iov_len = 0; |
617 | xdr->nwords = XDR_QUADLEN(buf->len); | ||
637 | if (buf->head[0].iov_len != 0) | 618 | if (buf->head[0].iov_len != 0) |
638 | xdr_set_iov(xdr, buf->head, p, buf->len); | 619 | xdr_set_iov(xdr, buf->head, buf->len); |
639 | else if (buf->page_len != 0) | 620 | else if (buf->page_len != 0) |
640 | xdr_set_page_base(xdr, 0, buf->len); | 621 | xdr_set_page_base(xdr, 0, buf->len); |
622 | if (p != NULL && p > xdr->p && xdr->end >= p) { | ||
623 | xdr->nwords -= p - xdr->p; | ||
624 | xdr->p = p; | ||
625 | } | ||
641 | } | 626 | } |
642 | EXPORT_SYMBOL_GPL(xdr_init_decode); | 627 | EXPORT_SYMBOL_GPL(xdr_init_decode); |
643 | 628 | ||
@@ -662,12 +647,14 @@ EXPORT_SYMBOL_GPL(xdr_init_decode_pages); | |||
662 | 647 | ||
663 | static __be32 * __xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) | 648 | static __be32 * __xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) |
664 | { | 649 | { |
650 | unsigned int nwords = XDR_QUADLEN(nbytes); | ||
665 | __be32 *p = xdr->p; | 651 | __be32 *p = xdr->p; |
666 | __be32 *q = p + XDR_QUADLEN(nbytes); | 652 | __be32 *q = p + nwords; |
667 | 653 | ||
668 | if (unlikely(q > xdr->end || q < p)) | 654 | if (unlikely(nwords > xdr->nwords || q > xdr->end || q < p)) |
669 | return NULL; | 655 | return NULL; |
670 | xdr->p = q; | 656 | xdr->p = q; |
657 | xdr->nwords -= nwords; | ||
671 | return p; | 658 | return p; |
672 | } | 659 | } |
673 | 660 | ||
@@ -734,6 +721,31 @@ __be32 * xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) | |||
734 | } | 721 | } |
735 | EXPORT_SYMBOL_GPL(xdr_inline_decode); | 722 | EXPORT_SYMBOL_GPL(xdr_inline_decode); |
736 | 723 | ||
724 | static unsigned int xdr_align_pages(struct xdr_stream *xdr, unsigned int len) | ||
725 | { | ||
726 | struct xdr_buf *buf = xdr->buf; | ||
727 | struct kvec *iov; | ||
728 | unsigned int nwords = XDR_QUADLEN(len); | ||
729 | unsigned int cur = xdr_stream_pos(xdr); | ||
730 | |||
731 | if (xdr->nwords == 0) | ||
732 | return 0; | ||
733 | if (nwords > xdr->nwords) { | ||
734 | nwords = xdr->nwords; | ||
735 | len = nwords << 2; | ||
736 | } | ||
737 | /* Realign pages to current pointer position */ | ||
738 | iov = buf->head; | ||
739 | if (iov->iov_len > cur) | ||
740 | xdr_shrink_bufhead(buf, iov->iov_len - cur); | ||
741 | |||
742 | /* Truncate page data and move it into the tail */ | ||
743 | if (buf->page_len > len) | ||
744 | xdr_shrink_pagelen(buf, buf->page_len - len); | ||
745 | xdr->nwords = XDR_QUADLEN(buf->len - cur); | ||
746 | return len; | ||
747 | } | ||
748 | |||
737 | /** | 749 | /** |
738 | * xdr_read_pages - Ensure page-based XDR data to decode is aligned at current pointer position | 750 | * xdr_read_pages - Ensure page-based XDR data to decode is aligned at current pointer position |
739 | * @xdr: pointer to xdr_stream struct | 751 | * @xdr: pointer to xdr_stream struct |
@@ -742,39 +754,37 @@ EXPORT_SYMBOL_GPL(xdr_inline_decode); | |||
742 | * Moves data beyond the current pointer position from the XDR head[] buffer | 754 | * Moves data beyond the current pointer position from the XDR head[] buffer |
743 | * into the page list. Any data that lies beyond current position + "len" | 755 | * into the page list. Any data that lies beyond current position + "len" |
744 | * bytes is moved into the XDR tail[]. | 756 | * bytes is moved into the XDR tail[]. |
757 | * | ||
758 | * Returns the number of XDR encoded bytes now contained in the pages | ||
745 | */ | 759 | */ |
746 | void xdr_read_pages(struct xdr_stream *xdr, unsigned int len) | 760 | unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len) |
747 | { | 761 | { |
748 | struct xdr_buf *buf = xdr->buf; | 762 | struct xdr_buf *buf = xdr->buf; |
749 | struct kvec *iov; | 763 | struct kvec *iov; |
750 | ssize_t shift; | 764 | unsigned int nwords; |
751 | unsigned int end; | 765 | unsigned int end; |
752 | int padding; | 766 | unsigned int padding; |
753 | 767 | ||
754 | /* Realign pages to current pointer position */ | 768 | len = xdr_align_pages(xdr, len); |
755 | iov = buf->head; | 769 | if (len == 0) |
756 | shift = iov->iov_len + (char *)iov->iov_base - (char *)xdr->p; | 770 | return 0; |
757 | if (shift > 0) | 771 | nwords = XDR_QUADLEN(len); |
758 | xdr_shrink_bufhead(buf, shift); | 772 | padding = (nwords << 2) - len; |
759 | |||
760 | /* Truncate page data and move it into the tail */ | ||
761 | if (buf->page_len > len) | ||
762 | xdr_shrink_pagelen(buf, buf->page_len - len); | ||
763 | padding = (XDR_QUADLEN(len) << 2) - len; | ||
764 | xdr->iov = iov = buf->tail; | 773 | xdr->iov = iov = buf->tail; |
765 | /* Compute remaining message length. */ | 774 | /* Compute remaining message length. */ |
766 | end = iov->iov_len; | 775 | end = ((xdr->nwords - nwords) << 2) + padding; |
767 | shift = buf->buflen - buf->len; | 776 | if (end > iov->iov_len) |
768 | if (shift < end) | 777 | end = iov->iov_len; |
769 | end -= shift; | 778 | |
770 | else if (shift > 0) | ||
771 | end = 0; | ||
772 | /* | 779 | /* |
773 | * Position current pointer at beginning of tail, and | 780 | * Position current pointer at beginning of tail, and |
774 | * set remaining message length. | 781 | * set remaining message length. |
775 | */ | 782 | */ |
776 | xdr->p = (__be32 *)((char *)iov->iov_base + padding); | 783 | xdr->p = (__be32 *)((char *)iov->iov_base + padding); |
777 | xdr->end = (__be32 *)((char *)iov->iov_base + end); | 784 | xdr->end = (__be32 *)((char *)iov->iov_base + end); |
785 | xdr->page_ptr = NULL; | ||
786 | xdr->nwords = XDR_QUADLEN(end - padding); | ||
787 | return len; | ||
778 | } | 788 | } |
779 | EXPORT_SYMBOL_GPL(xdr_read_pages); | 789 | EXPORT_SYMBOL_GPL(xdr_read_pages); |
780 | 790 | ||
@@ -790,12 +800,13 @@ EXPORT_SYMBOL_GPL(xdr_read_pages); | |||
790 | */ | 800 | */ |
791 | void xdr_enter_page(struct xdr_stream *xdr, unsigned int len) | 801 | void xdr_enter_page(struct xdr_stream *xdr, unsigned int len) |
792 | { | 802 | { |
793 | xdr_read_pages(xdr, len); | 803 | len = xdr_align_pages(xdr, len); |
794 | /* | 804 | /* |
795 | * Position current pointer at beginning of tail, and | 805 | * Position current pointer at beginning of tail, and |
796 | * set remaining message length. | 806 | * set remaining message length. |
797 | */ | 807 | */ |
798 | xdr_set_page_base(xdr, 0, len); | 808 | if (len != 0) |
809 | xdr_set_page_base(xdr, 0, len); | ||
799 | } | 810 | } |
800 | EXPORT_SYMBOL_GPL(xdr_enter_page); | 811 | EXPORT_SYMBOL_GPL(xdr_enter_page); |
801 | 812 | ||