aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2006-08-22 20:06:20 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-09-22 23:24:49 -0400
commitc2866763b4029411d166040306691773c12d4caf (patch)
tree5b16b3a293843062234c5eaf377da2af93365266 /net
parent6ca948238724c945bd353f51d54ae7d285f3889f (diff)
SUNRPC: use sockaddr + size when creating remote transport endpoints
Prepare for more generic transport endpoint handling needed by transports that might use different forms of addressing, such as IPv6. Introduce a single function call to replace the two-call xprt_create_proto/rpc_create_client API. Define a new rpc_create_args structure that allows callers to pass in remote endpoint addresses of varying length. Test-plan: Compile kernel with CONFIG_NFS enabled. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/clnt.c61
-rw-r--r--net/sunrpc/xprt.c75
2 files changed, 136 insertions, 0 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index ff1e90fd81ab..dbb93bdf6cc9 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -192,6 +192,67 @@ out_no_xprt:
192 return ERR_PTR(err); 192 return ERR_PTR(err);
193} 193}
194 194
195/*
196 * rpc_create - create an RPC client and transport with one call
197 * @args: rpc_clnt create argument structure
198 *
199 * Creates and initializes an RPC transport and an RPC client.
200 *
201 * It can ping the server in order to determine if it is up, and to see if
202 * it supports this program and version. RPC_CLNT_CREATE_NOPING disables
203 * this behavior so asynchronous tasks can also use rpc_create.
204 */
205struct rpc_clnt *rpc_create(struct rpc_create_args *args)
206{
207 struct rpc_xprt *xprt;
208 struct rpc_clnt *clnt;
209
210 xprt = xprt_create_transport(args->protocol, args->address,
211 args->addrsize, args->timeout);
212 if (IS_ERR(xprt))
213 return (struct rpc_clnt *)xprt;
214
215 /*
216 * By default, kernel RPC client connects from a reserved port.
217 * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters,
218 * but it is always enabled for rpciod, which handles the connect
219 * operation.
220 */
221 xprt->resvport = 1;
222 if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT)
223 xprt->resvport = 0;
224
225 dprintk("RPC: creating %s client for %s (xprt %p)\n",
226 args->program->name, args->servername, xprt);
227
228 clnt = rpc_new_client(xprt, args->servername, args->program,
229 args->version, args->authflavor);
230 if (IS_ERR(clnt))
231 return clnt;
232
233 if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
234 int err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR);
235 if (err != 0) {
236 rpc_shutdown_client(clnt);
237 return ERR_PTR(err);
238 }
239 }
240
241 clnt->cl_softrtry = 1;
242 if (args->flags & RPC_CLNT_CREATE_HARDRTRY)
243 clnt->cl_softrtry = 0;
244
245 if (args->flags & RPC_CLNT_CREATE_INTR)
246 clnt->cl_intr = 1;
247 if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
248 clnt->cl_autobind = 1;
249 if (args->flags & RPC_CLNT_CREATE_ONESHOT)
250 clnt->cl_oneshot = 1;
251
252 return clnt;
253}
254EXPORT_SYMBOL(rpc_create);
255
195/** 256/**
196 * Create an RPC client 257 * Create an RPC client
197 * @xprt - pointer to xprt struct 258 * @xprt - pointer to xprt struct
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 4987517cc74b..17f56cfe2412 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -887,6 +887,81 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i
887 to->to_exponential = 0; 887 to->to_exponential = 0;
888} 888}
889 889
890/**
891 * xprt_create_transport - create an RPC transport
892 * @proto: requested transport protocol
893 * @ap: remote peer address
894 * @size: length of address
895 * @to: timeout parameters
896 *
897 */
898struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to)
899{
900 int result;
901 struct rpc_xprt *xprt;
902 struct rpc_rqst *req;
903
904 if ((xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL) {
905 dprintk("RPC: xprt_create_transport: no memory\n");
906 return ERR_PTR(-ENOMEM);
907 }
908 if (size <= sizeof(xprt->addr)) {
909 memcpy(&xprt->addr, ap, size);
910 xprt->addrlen = size;
911 } else {
912 kfree(xprt);
913 dprintk("RPC: xprt_create_transport: address too large\n");
914 return ERR_PTR(-EBADF);
915 }
916
917 switch (proto) {
918 case IPPROTO_UDP:
919 result = xs_setup_udp(xprt, to);
920 break;
921 case IPPROTO_TCP:
922 result = xs_setup_tcp(xprt, to);
923 break;
924 default:
925 printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
926 proto);
927 return ERR_PTR(-EIO);
928 }
929 if (result) {
930 kfree(xprt);
931 dprintk("RPC: xprt_create_transport: failed, %d\n", result);
932 return ERR_PTR(result);
933 }
934
935 spin_lock_init(&xprt->transport_lock);
936 spin_lock_init(&xprt->reserve_lock);
937
938 INIT_LIST_HEAD(&xprt->free);
939 INIT_LIST_HEAD(&xprt->recv);
940 INIT_WORK(&xprt->task_cleanup, xprt_autoclose, xprt);
941 init_timer(&xprt->timer);
942 xprt->timer.function = xprt_init_autodisconnect;
943 xprt->timer.data = (unsigned long) xprt;
944 xprt->last_used = jiffies;
945 xprt->cwnd = RPC_INITCWND;
946
947 rpc_init_wait_queue(&xprt->binding, "xprt_binding");
948 rpc_init_wait_queue(&xprt->pending, "xprt_pending");
949 rpc_init_wait_queue(&xprt->sending, "xprt_sending");
950 rpc_init_wait_queue(&xprt->resend, "xprt_resend");
951 rpc_init_priority_wait_queue(&xprt->backlog, "xprt_backlog");
952
953 /* initialize free list */
954 for (req = &xprt->slot[xprt->max_reqs-1]; req >= &xprt->slot[0]; req--)
955 list_add(&req->rq_list, &xprt->free);
956
957 xprt_init_xid(xprt);
958
959 dprintk("RPC: created transport %p with %u slots\n", xprt,
960 xprt->max_reqs);
961
962 return xprt;
963}
964
890static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to) 965static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
891{ 966{
892 int result; 967 int result;