aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 22:16:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 22:16:57 -0400
commit1fad1e9a747687a7399bf58e87974f9b1bbcae06 (patch)
treefde2dc9a35321e21c99e06d4b79d5fa06fd34679 /net/sunrpc
parentbbeb0af25f493261c15ceee176c99b7fd6fd5479 (diff)
parentf44106e2173f08ccb1c9195d85a6c22388b461c1 (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.c54
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c1
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c20
-rw-r--r--net/sunrpc/clnt.c3
-rw-r--r--net/sunrpc/xdr.c127
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}
123EXPORT_SYMBOL_GPL(rpcauth_unregister); 124EXPORT_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 */
136int
137rpcauth_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}
177EXPORT_SYMBOL_GPL(rpcauth_list_flavors);
178
125struct rpc_auth * 179struct rpc_auth *
126rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) 180rpcauth_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
1624static const struct rpc_credops gss_credops = { 1625static 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
240EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); 240EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor);
241 241
242int 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 */
252int 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(&registered_mechs_lock); 257 spin_lock(&registered_mechs_lock);
248 list_for_each_entry(pos, &registered_mechs, gm_list) { 258 list_for_each_entry(pos, &registered_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(&registered_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
257EXPORT_SYMBOL_GPL(gss_mech_list_pseudoflavors);
258
259u32 271u32
260gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) 272gss_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)
129EXPORT_SYMBOL_GPL(xdr_terminate_string); 129EXPORT_SYMBOL_GPL(xdr_terminate_string);
130 130
131void 131void
132xdr_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}
157EXPORT_SYMBOL_GPL(xdr_encode_pages);
158
159void
160xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, 132xdr_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)
457EXPORT_SYMBOL_GPL(xdr_shift_buf); 429EXPORT_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 */
435unsigned int xdr_stream_pos(const struct xdr_stream *xdr)
436{
437 return (unsigned int)(XDR_QUADLEN(xdr->buf->len) - xdr->nwords) << 2;
438}
439EXPORT_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
556EXPORT_SYMBOL_GPL(xdr_write_pages); 538EXPORT_SYMBOL_GPL(xdr_write_pages);
557 539
558static void xdr_set_iov(struct xdr_stream *xdr, struct kvec *iov, 540static 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
615static bool xdr_set_next_buffer(struct xdr_stream *xdr) 595static 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}
642EXPORT_SYMBOL_GPL(xdr_init_decode); 627EXPORT_SYMBOL_GPL(xdr_init_decode);
643 628
@@ -662,12 +647,14 @@ EXPORT_SYMBOL_GPL(xdr_init_decode_pages);
662 647
663static __be32 * __xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) 648static __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}
735EXPORT_SYMBOL_GPL(xdr_inline_decode); 722EXPORT_SYMBOL_GPL(xdr_inline_decode);
736 723
724static 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 */
746void xdr_read_pages(struct xdr_stream *xdr, unsigned int len) 760unsigned 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}
779EXPORT_SYMBOL_GPL(xdr_read_pages); 789EXPORT_SYMBOL_GPL(xdr_read_pages);
780 790
@@ -790,12 +800,13 @@ EXPORT_SYMBOL_GPL(xdr_read_pages);
790 */ 800 */
791void xdr_enter_page(struct xdr_stream *xdr, unsigned int len) 801void 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}
800EXPORT_SYMBOL_GPL(xdr_enter_page); 811EXPORT_SYMBOL_GPL(xdr_enter_page);
801 812