diff options
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 75 |
1 files changed, 75 insertions, 0 deletions
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; |