.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * linux/net/sunrpc/svc_xprt.c |
---|
3 | 4 | * |
---|
.. | .. |
---|
34 | 35 | /* apparently the "standard" is that clients close |
---|
35 | 36 | * idle connections after 5 minutes, servers after |
---|
36 | 37 | * 6 minutes |
---|
37 | | - * http://www.connectathon.org/talks96/nfstcp.pdf |
---|
| 38 | + * http://nfsv4bat.org/Documents/ConnectAThon/1996/nfstcp.pdf |
---|
38 | 39 | */ |
---|
39 | 40 | static int svc_conn_age_period = 6*60; |
---|
40 | 41 | |
---|
.. | .. |
---|
145 | 146 | struct module *owner = xprt->xpt_class->xcl_owner; |
---|
146 | 147 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) |
---|
147 | 148 | svcauth_unix_info_release(xprt); |
---|
| 149 | + put_cred(xprt->xpt_cred); |
---|
148 | 150 | put_net(xprt->xpt_net); |
---|
149 | 151 | /* See comment on corresponding get in xs_setup_bc_tcp(): */ |
---|
150 | 152 | if (xprt->xpt_bc_xprt) |
---|
151 | 153 | xprt_put(xprt->xpt_bc_xprt); |
---|
152 | 154 | if (xprt->xpt_bc_xps) |
---|
153 | 155 | xprt_switch_put(xprt->xpt_bc_xps); |
---|
| 156 | + trace_svc_xprt_free(xprt); |
---|
154 | 157 | xprt->xpt_ops->xpo_free(xprt); |
---|
155 | 158 | module_put(owner); |
---|
156 | 159 | } |
---|
.. | .. |
---|
180 | 183 | mutex_init(&xprt->xpt_mutex); |
---|
181 | 184 | spin_lock_init(&xprt->xpt_lock); |
---|
182 | 185 | set_bit(XPT_BUSY, &xprt->xpt_flags); |
---|
183 | | - rpc_init_wait_queue(&xprt->xpt_bc_pending, "xpt_bc_pending"); |
---|
184 | 186 | xprt->xpt_net = get_net(net); |
---|
185 | 187 | strcpy(xprt->xpt_remotebuf, "uninitialized"); |
---|
186 | 188 | } |
---|
.. | .. |
---|
205 | 207 | .sin6_port = htons(port), |
---|
206 | 208 | }; |
---|
207 | 209 | #endif |
---|
| 210 | + struct svc_xprt *xprt; |
---|
208 | 211 | struct sockaddr *sap; |
---|
209 | 212 | size_t len; |
---|
210 | 213 | |
---|
.. | .. |
---|
223 | 226 | return ERR_PTR(-EAFNOSUPPORT); |
---|
224 | 227 | } |
---|
225 | 228 | |
---|
226 | | - return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); |
---|
| 229 | + xprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); |
---|
| 230 | + if (IS_ERR(xprt)) |
---|
| 231 | + trace_svc_xprt_create_err(serv->sv_program->pg_name, |
---|
| 232 | + xcl->xcl_name, sap, xprt); |
---|
| 233 | + return xprt; |
---|
227 | 234 | } |
---|
228 | 235 | |
---|
229 | 236 | /* |
---|
.. | .. |
---|
262 | 269 | |
---|
263 | 270 | static int _svc_create_xprt(struct svc_serv *serv, const char *xprt_name, |
---|
264 | 271 | struct net *net, const int family, |
---|
265 | | - const unsigned short port, int flags) |
---|
| 272 | + const unsigned short port, int flags, |
---|
| 273 | + const struct cred *cred) |
---|
266 | 274 | { |
---|
267 | 275 | struct svc_xprt_class *xcl; |
---|
268 | 276 | |
---|
.. | .. |
---|
283 | 291 | module_put(xcl->xcl_owner); |
---|
284 | 292 | return PTR_ERR(newxprt); |
---|
285 | 293 | } |
---|
| 294 | + newxprt->xpt_cred = get_cred(cred); |
---|
286 | 295 | svc_add_new_perm_xprt(serv, newxprt); |
---|
287 | 296 | newport = svc_xprt_local_port(newxprt); |
---|
288 | 297 | return newport; |
---|
.. | .. |
---|
296 | 305 | |
---|
297 | 306 | int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, |
---|
298 | 307 | struct net *net, const int family, |
---|
299 | | - const unsigned short port, int flags) |
---|
| 308 | + const unsigned short port, int flags, |
---|
| 309 | + const struct cred *cred) |
---|
300 | 310 | { |
---|
301 | 311 | int err; |
---|
302 | 312 | |
---|
303 | | - dprintk("svc: creating transport %s[%d]\n", xprt_name, port); |
---|
304 | | - err = _svc_create_xprt(serv, xprt_name, net, family, port, flags); |
---|
| 313 | + err = _svc_create_xprt(serv, xprt_name, net, family, port, flags, cred); |
---|
305 | 314 | if (err == -EPROTONOSUPPORT) { |
---|
306 | 315 | request_module("svc%s", xprt_name); |
---|
307 | | - err = _svc_create_xprt(serv, xprt_name, net, family, port, flags); |
---|
| 316 | + err = _svc_create_xprt(serv, xprt_name, net, family, port, flags, cred); |
---|
308 | 317 | } |
---|
309 | | - if (err) |
---|
310 | | - dprintk("svc: transport %s not found, err %d\n", |
---|
311 | | - xprt_name, err); |
---|
312 | 318 | return err; |
---|
313 | 319 | } |
---|
314 | 320 | EXPORT_SYMBOL_GPL(svc_create_xprt); |
---|
.. | .. |
---|
367 | 373 | struct svc_xprt *xprt = rqstp->rq_xprt; |
---|
368 | 374 | if (test_and_clear_bit(RQ_DATA, &rqstp->rq_flags)) { |
---|
369 | 375 | atomic_dec(&xprt->xpt_nr_rqsts); |
---|
| 376 | + smp_wmb(); /* See smp_rmb() in svc_xprt_ready() */ |
---|
370 | 377 | svc_xprt_enqueue(xprt); |
---|
371 | 378 | } |
---|
372 | 379 | } |
---|
373 | 380 | |
---|
374 | | -static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) |
---|
| 381 | +static bool svc_xprt_ready(struct svc_xprt *xprt) |
---|
375 | 382 | { |
---|
376 | | - if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE))) |
---|
| 383 | + unsigned long xpt_flags; |
---|
| 384 | + |
---|
| 385 | + /* |
---|
| 386 | + * If another cpu has recently updated xpt_flags, |
---|
| 387 | + * sk_sock->flags, xpt_reserved, or xpt_nr_rqsts, we need to |
---|
| 388 | + * know about it; otherwise it's possible that both that cpu and |
---|
| 389 | + * this one could call svc_xprt_enqueue() without either |
---|
| 390 | + * svc_xprt_enqueue() recognizing that the conditions below |
---|
| 391 | + * are satisfied, and we could stall indefinitely: |
---|
| 392 | + */ |
---|
| 393 | + smp_rmb(); |
---|
| 394 | + xpt_flags = READ_ONCE(xprt->xpt_flags); |
---|
| 395 | + |
---|
| 396 | + if (xpt_flags & (BIT(XPT_CONN) | BIT(XPT_CLOSE))) |
---|
377 | 397 | return true; |
---|
378 | | - if (xprt->xpt_flags & ((1<<XPT_DATA)|(1<<XPT_DEFERRED))) { |
---|
| 398 | + if (xpt_flags & (BIT(XPT_DATA) | BIT(XPT_DEFERRED))) { |
---|
379 | 399 | if (xprt->xpt_ops->xpo_has_wspace(xprt) && |
---|
380 | 400 | svc_xprt_slots_in_range(xprt)) |
---|
381 | 401 | return true; |
---|
.. | .. |
---|
391 | 411 | struct svc_rqst *rqstp = NULL; |
---|
392 | 412 | int cpu; |
---|
393 | 413 | |
---|
394 | | - if (!svc_xprt_has_something_to_do(xprt)) |
---|
| 414 | + if (!svc_xprt_ready(xprt)) |
---|
395 | 415 | return; |
---|
396 | 416 | |
---|
397 | 417 | /* Mark transport as busy. It will remain in this state until |
---|
.. | .. |
---|
402 | 422 | if (test_and_set_bit(XPT_BUSY, &xprt->xpt_flags)) |
---|
403 | 423 | return; |
---|
404 | 424 | |
---|
405 | | - cpu = get_cpu_light(); |
---|
| 425 | + cpu = get_cpu(); |
---|
406 | 426 | pool = svc_pool_for_cpu(xprt->xpt_server, cpu); |
---|
407 | 427 | |
---|
408 | 428 | atomic_long_inc(&pool->sp_stats.packets); |
---|
.. | .. |
---|
426 | 446 | rqstp = NULL; |
---|
427 | 447 | out_unlock: |
---|
428 | 448 | rcu_read_unlock(); |
---|
429 | | - put_cpu_light(); |
---|
| 449 | + put_cpu(); |
---|
430 | 450 | trace_svc_xprt_do_enqueue(xprt, rqstp); |
---|
431 | 451 | } |
---|
432 | 452 | EXPORT_SYMBOL_GPL(svc_xprt_do_enqueue); |
---|
.. | .. |
---|
485 | 505 | if (xprt && space < rqstp->rq_reserved) { |
---|
486 | 506 | atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved); |
---|
487 | 507 | rqstp->rq_reserved = space; |
---|
488 | | - |
---|
| 508 | + smp_wmb(); /* See smp_rmb() in svc_xprt_ready() */ |
---|
489 | 509 | svc_xprt_enqueue(xprt); |
---|
490 | 510 | } |
---|
491 | 511 | } |
---|
.. | .. |
---|
762 | 782 | int len = 0; |
---|
763 | 783 | |
---|
764 | 784 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { |
---|
765 | | - dprintk("svc_recv: found XPT_CLOSE\n"); |
---|
766 | 785 | if (test_and_clear_bit(XPT_KILL_TEMP, &xprt->xpt_flags)) |
---|
767 | 786 | xprt->xpt_ops->xpo_kill_temp_xprt(xprt); |
---|
768 | 787 | svc_delete_xprt(xprt); |
---|
.. | .. |
---|
778 | 797 | __module_get(xprt->xpt_class->xcl_owner); |
---|
779 | 798 | svc_check_conn_limits(xprt->xpt_server); |
---|
780 | 799 | newxpt = xprt->xpt_ops->xpo_accept(xprt); |
---|
781 | | - if (newxpt) |
---|
| 800 | + if (newxpt) { |
---|
| 801 | + newxpt->xpt_cred = get_cred(xprt->xpt_cred); |
---|
782 | 802 | svc_add_new_temp_xprt(serv, newxpt); |
---|
783 | | - else |
---|
| 803 | + trace_svc_xprt_accept(newxpt, serv->sv_name); |
---|
| 804 | + } else |
---|
784 | 805 | module_put(xprt->xpt_class->xcl_owner); |
---|
785 | 806 | } else if (svc_xprt_reserve_slot(rqstp, xprt)) { |
---|
786 | 807 | /* XPT_DATA|XPT_DEFERRED case: */ |
---|
.. | .. |
---|
792 | 813 | len = svc_deferred_recv(rqstp); |
---|
793 | 814 | else |
---|
794 | 815 | len = xprt->xpt_ops->xpo_recvfrom(rqstp); |
---|
| 816 | + if (len > 0) |
---|
| 817 | + trace_svc_xdr_recvfrom(rqstp, &rqstp->rq_arg); |
---|
795 | 818 | rqstp->rq_stime = ktime_get(); |
---|
796 | 819 | rqstp->rq_reserved = serv->sv_max_mesg; |
---|
797 | 820 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); |
---|
.. | .. |
---|
813 | 836 | struct svc_xprt *xprt = NULL; |
---|
814 | 837 | struct svc_serv *serv = rqstp->rq_server; |
---|
815 | 838 | int len, err; |
---|
816 | | - |
---|
817 | | - dprintk("svc: server %p waiting for data (to = %ld)\n", |
---|
818 | | - rqstp, timeout); |
---|
819 | | - |
---|
820 | | - if (rqstp->rq_xprt) |
---|
821 | | - printk(KERN_ERR |
---|
822 | | - "svc_recv: service %p, transport not NULL!\n", |
---|
823 | | - rqstp); |
---|
824 | 839 | |
---|
825 | 840 | err = svc_alloc_arg(rqstp); |
---|
826 | 841 | if (err) |
---|
.. | .. |
---|
869 | 884 | void svc_drop(struct svc_rqst *rqstp) |
---|
870 | 885 | { |
---|
871 | 886 | trace_svc_drop(rqstp); |
---|
872 | | - dprintk("svc: xprt %p dropped request\n", rqstp->rq_xprt); |
---|
873 | 887 | svc_xprt_release(rqstp); |
---|
874 | 888 | } |
---|
875 | 889 | EXPORT_SYMBOL_GPL(svc_drop); |
---|
.. | .. |
---|
892 | 906 | xb->len = xb->head[0].iov_len + |
---|
893 | 907 | xb->page_len + |
---|
894 | 908 | xb->tail[0].iov_len; |
---|
895 | | - |
---|
896 | | - /* Grab mutex to serialize outgoing data. */ |
---|
897 | | - mutex_lock(&xprt->xpt_mutex); |
---|
| 909 | + trace_svc_xdr_sendto(rqstp, xb); |
---|
898 | 910 | trace_svc_stats_latency(rqstp); |
---|
899 | | - if (test_bit(XPT_DEAD, &xprt->xpt_flags) |
---|
900 | | - || test_bit(XPT_CLOSE, &xprt->xpt_flags)) |
---|
901 | | - len = -ENOTCONN; |
---|
902 | | - else |
---|
903 | | - len = xprt->xpt_ops->xpo_sendto(rqstp); |
---|
904 | | - mutex_unlock(&xprt->xpt_mutex); |
---|
905 | | - rpc_wake_up(&xprt->xpt_bc_pending); |
---|
| 911 | + |
---|
| 912 | + len = xprt->xpt_ops->xpo_sendto(rqstp); |
---|
| 913 | + |
---|
906 | 914 | trace_svc_send(rqstp, len); |
---|
907 | 915 | svc_xprt_release(rqstp); |
---|
908 | 916 | |
---|
.. | .. |
---|
1010 | 1018 | struct svc_serv *serv = xprt->xpt_server; |
---|
1011 | 1019 | struct svc_deferred_req *dr; |
---|
1012 | 1020 | |
---|
1013 | | - /* Only do this once */ |
---|
1014 | 1021 | if (test_and_set_bit(XPT_DEAD, &xprt->xpt_flags)) |
---|
1015 | | - BUG(); |
---|
| 1022 | + return; |
---|
1016 | 1023 | |
---|
1017 | | - dprintk("svc: svc_delete_xprt(%p)\n", xprt); |
---|
| 1024 | + trace_svc_xprt_detach(xprt); |
---|
1018 | 1025 | xprt->xpt_ops->xpo_detach(xprt); |
---|
| 1026 | + if (xprt->xpt_bc_xprt) |
---|
| 1027 | + xprt->xpt_bc_xprt->ops->close(xprt->xpt_bc_xprt); |
---|
1019 | 1028 | |
---|
1020 | 1029 | spin_lock_bh(&serv->sv_lock); |
---|
1021 | 1030 | list_del_init(&xprt->xpt_list); |
---|
.. | .. |
---|
1033 | 1042 | |
---|
1034 | 1043 | void svc_close_xprt(struct svc_xprt *xprt) |
---|
1035 | 1044 | { |
---|
| 1045 | + trace_svc_xprt_close(xprt); |
---|
1036 | 1046 | set_bit(XPT_CLOSE, &xprt->xpt_flags); |
---|
1037 | 1047 | if (test_and_set_bit(XPT_BUSY, &xprt->xpt_flags)) |
---|
1038 | 1048 | /* someone else will have to effect the close */ |
---|
.. | .. |
---|
1135 | 1145 | set_bit(XPT_DEFERRED, &xprt->xpt_flags); |
---|
1136 | 1146 | if (too_many || test_bit(XPT_DEAD, &xprt->xpt_flags)) { |
---|
1137 | 1147 | spin_unlock(&xprt->xpt_lock); |
---|
1138 | | - dprintk("revisit canceled\n"); |
---|
| 1148 | + trace_svc_defer_drop(dr); |
---|
1139 | 1149 | svc_xprt_put(xprt); |
---|
1140 | | - trace_svc_drop_deferred(dr); |
---|
1141 | 1150 | kfree(dr); |
---|
1142 | 1151 | return; |
---|
1143 | 1152 | } |
---|
1144 | | - dprintk("revisit queued\n"); |
---|
1145 | 1153 | dr->xprt = NULL; |
---|
1146 | 1154 | list_add(&dr->handle.recent, &xprt->xpt_deferred); |
---|
1147 | 1155 | spin_unlock(&xprt->xpt_lock); |
---|
| 1156 | + trace_svc_defer_queue(dr); |
---|
1148 | 1157 | svc_xprt_enqueue(xprt); |
---|
1149 | 1158 | svc_xprt_put(xprt); |
---|
1150 | 1159 | } |
---|
.. | .. |
---|
1190 | 1199 | memcpy(dr->args, rqstp->rq_arg.head[0].iov_base - skip, |
---|
1191 | 1200 | dr->argslen << 2); |
---|
1192 | 1201 | } |
---|
| 1202 | + trace_svc_defer(rqstp); |
---|
1193 | 1203 | svc_xprt_get(rqstp->rq_xprt); |
---|
1194 | 1204 | dr->xprt = rqstp->rq_xprt; |
---|
1195 | 1205 | set_bit(RQ_DROPME, &rqstp->rq_flags); |
---|
1196 | 1206 | |
---|
1197 | 1207 | dr->handle.revisit = svc_revisit; |
---|
1198 | | - trace_svc_defer(rqstp); |
---|
1199 | 1208 | return &dr->handle; |
---|
1200 | 1209 | } |
---|
1201 | 1210 | |
---|
1202 | 1211 | /* |
---|
1203 | 1212 | * recv data from a deferred request into an active one |
---|
1204 | 1213 | */ |
---|
1205 | | -static int svc_deferred_recv(struct svc_rqst *rqstp) |
---|
| 1214 | +static noinline int svc_deferred_recv(struct svc_rqst *rqstp) |
---|
1206 | 1215 | { |
---|
1207 | 1216 | struct svc_deferred_req *dr = rqstp->rq_deferred; |
---|
| 1217 | + |
---|
| 1218 | + trace_svc_defer_recv(dr); |
---|
1208 | 1219 | |
---|
1209 | 1220 | /* setup iov_base past transport header */ |
---|
1210 | 1221 | rqstp->rq_arg.head[0].iov_base = dr->args + (dr->xprt_hlen>>2); |
---|
.. | .. |
---|
1236 | 1247 | struct svc_deferred_req, |
---|
1237 | 1248 | handle.recent); |
---|
1238 | 1249 | list_del_init(&dr->handle.recent); |
---|
1239 | | - trace_svc_revisit_deferred(dr); |
---|
1240 | 1250 | } else |
---|
1241 | 1251 | clear_bit(XPT_DEFERRED, &xprt->xpt_flags); |
---|
1242 | 1252 | spin_unlock(&xprt->xpt_lock); |
---|