diff options
| -rw-r--r-- | include/linux/sunrpc/clnt.h | 22 | ||||
| -rw-r--r-- | include/linux/sunrpc/xprt.h | 1 | ||||
| -rw-r--r-- | net/sunrpc/clnt.c | 61 | ||||
| -rw-r--r-- | net/sunrpc/xprt.c | 75 |
4 files changed, 159 insertions, 0 deletions
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index a26d69583c7a..7817ba82f1b2 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
| @@ -97,6 +97,28 @@ struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname, | |||
| 97 | struct rpc_clnt *rpc_new_client(struct rpc_xprt *xprt, char *servname, | 97 | struct rpc_clnt *rpc_new_client(struct rpc_xprt *xprt, char *servname, |
| 98 | struct rpc_program *info, | 98 | struct rpc_program *info, |
| 99 | u32 version, rpc_authflavor_t authflavor); | 99 | u32 version, rpc_authflavor_t authflavor); |
| 100 | |||
| 101 | struct rpc_create_args { | ||
| 102 | int protocol; | ||
| 103 | struct sockaddr *address; | ||
| 104 | size_t addrsize; | ||
| 105 | struct rpc_timeout *timeout; | ||
| 106 | char *servername; | ||
| 107 | struct rpc_program *program; | ||
| 108 | u32 version; | ||
| 109 | rpc_authflavor_t authflavor; | ||
| 110 | unsigned long flags; | ||
| 111 | }; | ||
| 112 | |||
| 113 | /* Values for "flags" field */ | ||
| 114 | #define RPC_CLNT_CREATE_HARDRTRY (1UL << 0) | ||
| 115 | #define RPC_CLNT_CREATE_INTR (1UL << 1) | ||
| 116 | #define RPC_CLNT_CREATE_AUTOBIND (1UL << 2) | ||
| 117 | #define RPC_CLNT_CREATE_ONESHOT (1UL << 3) | ||
| 118 | #define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 4) | ||
| 119 | #define RPC_CLNT_CREATE_NOPING (1UL << 5) | ||
| 120 | |||
| 121 | struct rpc_clnt *rpc_create(struct rpc_create_args *args); | ||
| 100 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, | 122 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, |
| 101 | struct rpc_program *, int); | 123 | struct rpc_program *, int); |
| 102 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); | 124 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); |
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index fc05cfbd5805..bc80fcfdd892 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
| @@ -237,6 +237,7 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long | |||
| 237 | /* | 237 | /* |
| 238 | * Generic internal transport functions | 238 | * Generic internal transport functions |
| 239 | */ | 239 | */ |
| 240 | struct rpc_xprt * xprt_create_transport(int proto, struct sockaddr *addr, size_t size, struct rpc_timeout *toparms); | ||
| 240 | void xprt_connect(struct rpc_task *task); | 241 | void xprt_connect(struct rpc_task *task); |
| 241 | void xprt_reserve(struct rpc_task *task); | 242 | void xprt_reserve(struct rpc_task *task); |
| 242 | int xprt_reserve_xprt(struct rpc_task *task); | 243 | int xprt_reserve_xprt(struct rpc_task *task); |
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 | */ | ||
| 205 | struct 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 | } | ||
| 254 | EXPORT_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 | */ | ||
| 898 | struct 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 | |||
| 890 | static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to) | 965 | static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to) |
| 891 | { | 966 | { |
| 892 | int result; | 967 | int result; |
