diff options
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 116 |
1 files changed, 104 insertions, 12 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index c8c2edccad7e..282a9a2ec90c 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -62,6 +62,9 @@ static inline void do_xprt_reserve(struct rpc_task *); | |||
62 | static void xprt_connect_status(struct rpc_task *task); | 62 | static void xprt_connect_status(struct rpc_task *task); |
63 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | 63 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); |
64 | 64 | ||
65 | static spinlock_t xprt_list_lock = SPIN_LOCK_UNLOCKED; | ||
66 | static LIST_HEAD(xprt_list); | ||
67 | |||
65 | /* | 68 | /* |
66 | * The transport code maintains an estimate on the maximum number of out- | 69 | * The transport code maintains an estimate on the maximum number of out- |
67 | * standing RPC requests, using a smoothed version of the congestion | 70 | * standing RPC requests, using a smoothed version of the congestion |
@@ -81,6 +84,78 @@ static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | |||
81 | #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd) | 84 | #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd) |
82 | 85 | ||
83 | /** | 86 | /** |
87 | * xprt_register_transport - register a transport implementation | ||
88 | * @transport: transport to register | ||
89 | * | ||
90 | * If a transport implementation is loaded as a kernel module, it can | ||
91 | * call this interface to make itself known to the RPC client. | ||
92 | * | ||
93 | * Returns: | ||
94 | * 0: transport successfully registered | ||
95 | * -EEXIST: transport already registered | ||
96 | * -EINVAL: transport module being unloaded | ||
97 | */ | ||
98 | int xprt_register_transport(struct xprt_class *transport) | ||
99 | { | ||
100 | struct xprt_class *t; | ||
101 | int result; | ||
102 | |||
103 | result = -EEXIST; | ||
104 | spin_lock(&xprt_list_lock); | ||
105 | list_for_each_entry(t, &xprt_list, list) { | ||
106 | /* don't register the same transport class twice */ | ||
107 | if (t->ident == transport->ident) | ||
108 | goto out; | ||
109 | } | ||
110 | |||
111 | result = -EINVAL; | ||
112 | if (try_module_get(THIS_MODULE)) { | ||
113 | list_add_tail(&transport->list, &xprt_list); | ||
114 | printk(KERN_INFO "RPC: Registered %s transport module.\n", | ||
115 | transport->name); | ||
116 | result = 0; | ||
117 | } | ||
118 | |||
119 | out: | ||
120 | spin_unlock(&xprt_list_lock); | ||
121 | return result; | ||
122 | } | ||
123 | EXPORT_SYMBOL_GPL(xprt_register_transport); | ||
124 | |||
125 | /** | ||
126 | * xprt_unregister_transport - unregister a transport implementation | ||
127 | * transport: transport to unregister | ||
128 | * | ||
129 | * Returns: | ||
130 | * 0: transport successfully unregistered | ||
131 | * -ENOENT: transport never registered | ||
132 | */ | ||
133 | int xprt_unregister_transport(struct xprt_class *transport) | ||
134 | { | ||
135 | struct xprt_class *t; | ||
136 | int result; | ||
137 | |||
138 | result = 0; | ||
139 | spin_lock(&xprt_list_lock); | ||
140 | list_for_each_entry(t, &xprt_list, list) { | ||
141 | if (t == transport) { | ||
142 | printk(KERN_INFO | ||
143 | "RPC: Unregistered %s transport module.\n", | ||
144 | transport->name); | ||
145 | list_del_init(&transport->list); | ||
146 | module_put(THIS_MODULE); | ||
147 | goto out; | ||
148 | } | ||
149 | } | ||
150 | result = -ENOENT; | ||
151 | |||
152 | out: | ||
153 | spin_unlock(&xprt_list_lock); | ||
154 | return result; | ||
155 | } | ||
156 | EXPORT_SYMBOL_GPL(xprt_unregister_transport); | ||
157 | |||
158 | /** | ||
84 | * xprt_reserve_xprt - serialize write access to transports | 159 | * xprt_reserve_xprt - serialize write access to transports |
85 | * @task: task that is requesting access to the transport | 160 | * @task: task that is requesting access to the transport |
86 | * | 161 | * |
@@ -118,6 +193,7 @@ out_sleep: | |||
118 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 193 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); |
119 | return 0; | 194 | return 0; |
120 | } | 195 | } |
196 | EXPORT_SYMBOL_GPL(xprt_reserve_xprt); | ||
121 | 197 | ||
122 | static void xprt_clear_locked(struct rpc_xprt *xprt) | 198 | static void xprt_clear_locked(struct rpc_xprt *xprt) |
123 | { | 199 | { |
@@ -167,6 +243,7 @@ out_sleep: | |||
167 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 243 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); |
168 | return 0; | 244 | return 0; |
169 | } | 245 | } |
246 | EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong); | ||
170 | 247 | ||
171 | static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) | 248 | static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) |
172 | { | 249 | { |
@@ -246,6 +323,7 @@ void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | |||
246 | __xprt_lock_write_next(xprt); | 323 | __xprt_lock_write_next(xprt); |
247 | } | 324 | } |
248 | } | 325 | } |
326 | EXPORT_SYMBOL_GPL(xprt_release_xprt); | ||
249 | 327 | ||
250 | /** | 328 | /** |
251 | * xprt_release_xprt_cong - allow other requests to use a transport | 329 | * xprt_release_xprt_cong - allow other requests to use a transport |
@@ -262,6 +340,7 @@ void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) | |||
262 | __xprt_lock_write_next_cong(xprt); | 340 | __xprt_lock_write_next_cong(xprt); |
263 | } | 341 | } |
264 | } | 342 | } |
343 | EXPORT_SYMBOL_GPL(xprt_release_xprt_cong); | ||
265 | 344 | ||
266 | static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task) | 345 | static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task) |
267 | { | 346 | { |
@@ -314,6 +393,7 @@ void xprt_release_rqst_cong(struct rpc_task *task) | |||
314 | { | 393 | { |
315 | __xprt_put_cong(task->tk_xprt, task->tk_rqstp); | 394 | __xprt_put_cong(task->tk_xprt, task->tk_rqstp); |
316 | } | 395 | } |
396 | EXPORT_SYMBOL_GPL(xprt_release_rqst_cong); | ||
317 | 397 | ||
318 | /** | 398 | /** |
319 | * xprt_adjust_cwnd - adjust transport congestion window | 399 | * xprt_adjust_cwnd - adjust transport congestion window |
@@ -345,6 +425,7 @@ void xprt_adjust_cwnd(struct rpc_task *task, int result) | |||
345 | xprt->cwnd = cwnd; | 425 | xprt->cwnd = cwnd; |
346 | __xprt_put_cong(xprt, req); | 426 | __xprt_put_cong(xprt, req); |
347 | } | 427 | } |
428 | EXPORT_SYMBOL_GPL(xprt_adjust_cwnd); | ||
348 | 429 | ||
349 | /** | 430 | /** |
350 | * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue | 431 | * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue |
@@ -359,6 +440,7 @@ void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status) | |||
359 | else | 440 | else |
360 | rpc_wake_up(&xprt->pending); | 441 | rpc_wake_up(&xprt->pending); |
361 | } | 442 | } |
443 | EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks); | ||
362 | 444 | ||
363 | /** | 445 | /** |
364 | * xprt_wait_for_buffer_space - wait for transport output buffer to clear | 446 | * xprt_wait_for_buffer_space - wait for transport output buffer to clear |
@@ -373,6 +455,7 @@ void xprt_wait_for_buffer_space(struct rpc_task *task) | |||
373 | task->tk_timeout = req->rq_timeout; | 455 | task->tk_timeout = req->rq_timeout; |
374 | rpc_sleep_on(&xprt->pending, task, NULL, NULL); | 456 | rpc_sleep_on(&xprt->pending, task, NULL, NULL); |
375 | } | 457 | } |
458 | EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space); | ||
376 | 459 | ||
377 | /** | 460 | /** |
378 | * xprt_write_space - wake the task waiting for transport output buffer space | 461 | * xprt_write_space - wake the task waiting for transport output buffer space |
@@ -393,6 +476,7 @@ void xprt_write_space(struct rpc_xprt *xprt) | |||
393 | } | 476 | } |
394 | spin_unlock_bh(&xprt->transport_lock); | 477 | spin_unlock_bh(&xprt->transport_lock); |
395 | } | 478 | } |
479 | EXPORT_SYMBOL_GPL(xprt_write_space); | ||
396 | 480 | ||
397 | /** | 481 | /** |
398 | * xprt_set_retrans_timeout_def - set a request's retransmit timeout | 482 | * xprt_set_retrans_timeout_def - set a request's retransmit timeout |
@@ -406,6 +490,7 @@ void xprt_set_retrans_timeout_def(struct rpc_task *task) | |||
406 | { | 490 | { |
407 | task->tk_timeout = task->tk_rqstp->rq_timeout; | 491 | task->tk_timeout = task->tk_rqstp->rq_timeout; |
408 | } | 492 | } |
493 | EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_def); | ||
409 | 494 | ||
410 | /* | 495 | /* |
411 | * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout | 496 | * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout |
@@ -425,6 +510,7 @@ void xprt_set_retrans_timeout_rtt(struct rpc_task *task) | |||
425 | if (task->tk_timeout > max_timeout || task->tk_timeout == 0) | 510 | if (task->tk_timeout > max_timeout || task->tk_timeout == 0) |
426 | task->tk_timeout = max_timeout; | 511 | task->tk_timeout = max_timeout; |
427 | } | 512 | } |
513 | EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_rtt); | ||
428 | 514 | ||
429 | static void xprt_reset_majortimeo(struct rpc_rqst *req) | 515 | static void xprt_reset_majortimeo(struct rpc_rqst *req) |
430 | { | 516 | { |
@@ -500,6 +586,7 @@ void xprt_disconnect(struct rpc_xprt *xprt) | |||
500 | xprt_wake_pending_tasks(xprt, -ENOTCONN); | 586 | xprt_wake_pending_tasks(xprt, -ENOTCONN); |
501 | spin_unlock_bh(&xprt->transport_lock); | 587 | spin_unlock_bh(&xprt->transport_lock); |
502 | } | 588 | } |
589 | EXPORT_SYMBOL_GPL(xprt_disconnect); | ||
503 | 590 | ||
504 | static void | 591 | static void |
505 | xprt_init_autodisconnect(unsigned long data) | 592 | xprt_init_autodisconnect(unsigned long data) |
@@ -610,6 +697,7 @@ struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid) | |||
610 | xprt->stat.bad_xids++; | 697 | xprt->stat.bad_xids++; |
611 | return NULL; | 698 | return NULL; |
612 | } | 699 | } |
700 | EXPORT_SYMBOL_GPL(xprt_lookup_rqst); | ||
613 | 701 | ||
614 | /** | 702 | /** |
615 | * xprt_update_rtt - update an RPC client's RTT state after receiving a reply | 703 | * xprt_update_rtt - update an RPC client's RTT state after receiving a reply |
@@ -629,6 +717,7 @@ void xprt_update_rtt(struct rpc_task *task) | |||
629 | rpc_set_timeo(rtt, timer, req->rq_ntrans - 1); | 717 | rpc_set_timeo(rtt, timer, req->rq_ntrans - 1); |
630 | } | 718 | } |
631 | } | 719 | } |
720 | EXPORT_SYMBOL_GPL(xprt_update_rtt); | ||
632 | 721 | ||
633 | /** | 722 | /** |
634 | * xprt_complete_rqst - called when reply processing is complete | 723 | * xprt_complete_rqst - called when reply processing is complete |
@@ -653,6 +742,7 @@ void xprt_complete_rqst(struct rpc_task *task, int copied) | |||
653 | req->rq_received = req->rq_private_buf.len = copied; | 742 | req->rq_received = req->rq_private_buf.len = copied; |
654 | rpc_wake_up_task(task); | 743 | rpc_wake_up_task(task); |
655 | } | 744 | } |
745 | EXPORT_SYMBOL_GPL(xprt_complete_rqst); | ||
656 | 746 | ||
657 | static void xprt_timer(struct rpc_task *task) | 747 | static void xprt_timer(struct rpc_task *task) |
658 | { | 748 | { |
@@ -889,23 +979,25 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i | |||
889 | * @args: rpc transport creation arguments | 979 | * @args: rpc transport creation arguments |
890 | * | 980 | * |
891 | */ | 981 | */ |
892 | struct rpc_xprt *xprt_create_transport(struct rpc_xprtsock_create *args) | 982 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args) |
893 | { | 983 | { |
894 | struct rpc_xprt *xprt; | 984 | struct rpc_xprt *xprt; |
895 | struct rpc_rqst *req; | 985 | struct rpc_rqst *req; |
986 | struct xprt_class *t; | ||
896 | 987 | ||
897 | switch (args->proto) { | 988 | spin_lock(&xprt_list_lock); |
898 | case IPPROTO_UDP: | 989 | list_for_each_entry(t, &xprt_list, list) { |
899 | xprt = xs_setup_udp(args); | 990 | if (t->ident == args->ident) { |
900 | break; | 991 | spin_unlock(&xprt_list_lock); |
901 | case IPPROTO_TCP: | 992 | goto found; |
902 | xprt = xs_setup_tcp(args); | 993 | } |
903 | break; | ||
904 | default: | ||
905 | printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n", | ||
906 | args->proto); | ||
907 | return ERR_PTR(-EIO); | ||
908 | } | 994 | } |
995 | spin_unlock(&xprt_list_lock); | ||
996 | printk(KERN_ERR "RPC: transport (%d) not supported\n", args->ident); | ||
997 | return ERR_PTR(-EIO); | ||
998 | |||
999 | found: | ||
1000 | xprt = t->setup(args); | ||
909 | if (IS_ERR(xprt)) { | 1001 | if (IS_ERR(xprt)) { |
910 | dprintk("RPC: xprt_create_transport: failed, %ld\n", | 1002 | dprintk("RPC: xprt_create_transport: failed, %ld\n", |
911 | -PTR_ERR(xprt)); | 1003 | -PTR_ERR(xprt)); |