2 * linux/net/sunrpc/svc_xprt.c
4 * Author: Tom Tucker <tom@opengridcomputing.com>
7 #include <linux/sched.h>
8 #include <linux/errno.h>
9 #include <linux/fcntl.h>
10 #include <linux/net.h>
12 #include <linux/inet.h>
13 #include <linux/udp.h>
14 #include <linux/tcp.h>
15 #include <linux/unistd.h>
16 #include <linux/slab.h>
17 #include <linux/netdevice.h>
18 #include <linux/skbuff.h>
19 #include <linux/file.h>
20 #include <linux/freezer.h>
22 #include <net/checksum.h>
25 #include <net/tcp_states.h>
26 #include <linux/uaccess.h>
27 #include <asm/ioctls.h>
29 #include <linux/sunrpc/types.h>
30 #include <linux/sunrpc/clnt.h>
31 #include <linux/sunrpc/xdr.h>
32 #include <linux/sunrpc/svcsock.h>
33 #include <linux/sunrpc/stats.h>
34 #include <linux/sunrpc/svc_xprt.h>
36 #define RPCDBG_FACILITY RPCDBG_SVCXPRT
38 /* List of registered transport classes */
39 static DEFINE_SPINLOCK(svc_xprt_class_lock);
40 static LIST_HEAD(svc_xprt_class_list);
42 int svc_reg_xprt_class(struct svc_xprt_class *xcl)
44 struct svc_xprt_class *cl;
47 dprintk("svc: Adding svc transport class '%s'\n", xcl->xcl_name);
49 INIT_LIST_HEAD(&xcl->xcl_list);
50 spin_lock(&svc_xprt_class_lock);
51 /* Make sure there isn't already a class with the same name */
52 list_for_each_entry(cl, &svc_xprt_class_list, xcl_list) {
53 if (strcmp(xcl->xcl_name, cl->xcl_name) == 0)
56 list_add_tail(&xcl->xcl_list, &svc_xprt_class_list);
59 spin_unlock(&svc_xprt_class_lock);
62 EXPORT_SYMBOL_GPL(svc_reg_xprt_class);
64 void svc_unreg_xprt_class(struct svc_xprt_class *xcl)
66 dprintk("svc: Removing svc transport class '%s'\n", xcl->xcl_name);
67 spin_lock(&svc_xprt_class_lock);
68 list_del_init(&xcl->xcl_list);
69 spin_unlock(&svc_xprt_class_lock);
71 EXPORT_SYMBOL_GPL(svc_unreg_xprt_class);
73 static void svc_xprt_free(struct kref *kref)
75 struct svc_xprt *xprt =
76 container_of(kref, struct svc_xprt, xpt_ref);
77 struct module *owner = xprt->xpt_class->xcl_owner;
78 if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)
79 && xprt->xpt_auth_cache != NULL)
80 svcauth_unix_info_release(xprt->xpt_auth_cache);
81 xprt->xpt_ops->xpo_free(xprt);
85 void svc_xprt_put(struct svc_xprt *xprt)
87 kref_put(&xprt->xpt_ref, svc_xprt_free);
89 EXPORT_SYMBOL_GPL(svc_xprt_put);
92 * Called by transport drivers to initialize the transport independent
93 * portion of the transport instance.
95 void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt,
96 struct svc_serv *serv)
98 memset(xprt, 0, sizeof(*xprt));
99 xprt->xpt_class = xcl;
100 xprt->xpt_ops = xcl->xcl_ops;
101 kref_init(&xprt->xpt_ref);
102 xprt->xpt_server = serv;
103 INIT_LIST_HEAD(&xprt->xpt_list);
104 INIT_LIST_HEAD(&xprt->xpt_ready);
105 mutex_init(&xprt->xpt_mutex);
106 spin_lock_init(&xprt->xpt_lock);
108 EXPORT_SYMBOL_GPL(svc_xprt_init);
110 int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
113 struct svc_xprt_class *xcl;
115 struct sockaddr_in sin = {
116 .sin_family = AF_INET,
117 .sin_addr.s_addr = INADDR_ANY,
118 .sin_port = htons(port),
120 dprintk("svc: creating transport %s[%d]\n", xprt_name, port);
121 spin_lock(&svc_xprt_class_lock);
122 list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
123 if (strcmp(xprt_name, xcl->xcl_name) == 0) {
124 spin_unlock(&svc_xprt_class_lock);
125 if (try_module_get(xcl->xcl_owner)) {
126 struct svc_xprt *newxprt;
128 newxprt = xcl->xcl_ops->xpo_create
130 (struct sockaddr *)&sin, sizeof(sin),
132 if (IS_ERR(newxprt)) {
133 module_put(xcl->xcl_owner);
134 ret = PTR_ERR(newxprt);
140 spin_unlock(&svc_xprt_class_lock);
141 dprintk("svc: transport %s not found\n", xprt_name);
145 EXPORT_SYMBOL_GPL(svc_create_xprt);