1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020 Anna Schumaker <Anna.Schumaker@Netapp.com>
5 #include <linux/sunrpc/clnt.h>
6 #include <linux/kobject.h>
7 #include <linux/sunrpc/addr.h>
8 #include <linux/sunrpc/xprtsock.h>
17 static void free_xprt_addr(struct rcu_head
*head
)
19 struct xprt_addr
*addr
= container_of(head
, struct xprt_addr
, rcu
);
25 static struct kset
*rpc_sunrpc_kset
;
26 static struct kobject
*rpc_sunrpc_client_kobj
, *rpc_sunrpc_xprt_switch_kobj
;
28 static void rpc_sysfs_object_release(struct kobject
*kobj
)
33 static const struct kobj_ns_type_operations
*
34 rpc_sysfs_object_child_ns_type(const struct kobject
*kobj
)
36 return &net_ns_type_operations
;
39 static const struct kobj_type rpc_sysfs_object_type
= {
40 .release
= rpc_sysfs_object_release
,
41 .sysfs_ops
= &kobj_sysfs_ops
,
42 .child_ns_type
= rpc_sysfs_object_child_ns_type
,
45 static struct kobject
*rpc_sysfs_object_alloc(const char *name
,
47 struct kobject
*parent
)
51 kobj
= kzalloc(sizeof(*kobj
), GFP_KERNEL
);
54 if (kobject_init_and_add(kobj
, &rpc_sysfs_object_type
,
55 parent
, "%s", name
) == 0)
62 static inline struct rpc_xprt
*
63 rpc_sysfs_xprt_kobj_get_xprt(struct kobject
*kobj
)
65 struct rpc_sysfs_xprt
*x
= container_of(kobj
,
66 struct rpc_sysfs_xprt
, kobject
);
68 return xprt_get(x
->xprt
);
71 static inline struct rpc_xprt_switch
*
72 rpc_sysfs_xprt_kobj_get_xprt_switch(struct kobject
*kobj
)
74 struct rpc_sysfs_xprt
*x
= container_of(kobj
,
75 struct rpc_sysfs_xprt
, kobject
);
77 return xprt_switch_get(x
->xprt_switch
);
80 static inline struct rpc_xprt_switch
*
81 rpc_sysfs_xprt_switch_kobj_get_xprt(struct kobject
*kobj
)
83 struct rpc_sysfs_xprt_switch
*x
= container_of(kobj
,
84 struct rpc_sysfs_xprt_switch
, kobject
);
86 return xprt_switch_get(x
->xprt_switch
);
89 static ssize_t
rpc_sysfs_xprt_dstaddr_show(struct kobject
*kobj
,
90 struct kobj_attribute
*attr
,
93 struct rpc_xprt
*xprt
= rpc_sysfs_xprt_kobj_get_xprt(kobj
);
97 ret
= sprintf(buf
, "<closed>\n");
100 ret
= sprintf(buf
, "%s\n", xprt
->address_strings
[RPC_DISPLAY_ADDR
]);
106 static ssize_t
rpc_sysfs_xprt_srcaddr_show(struct kobject
*kobj
,
107 struct kobj_attribute
*attr
,
110 struct rpc_xprt
*xprt
= rpc_sysfs_xprt_kobj_get_xprt(kobj
);
111 size_t buflen
= PAGE_SIZE
;
114 if (!xprt
|| !xprt_connected(xprt
)) {
115 ret
= sprintf(buf
, "<closed>\n");
116 } else if (xprt
->ops
->get_srcaddr
) {
117 ret
= xprt
->ops
->get_srcaddr(xprt
, buf
, buflen
);
119 if (ret
< buflen
- 1) {
125 ret
= sprintf(buf
, "<closed>\n");
127 ret
= sprintf(buf
, "<not a socket>\n");
132 static ssize_t
rpc_sysfs_xprt_info_show(struct kobject
*kobj
,
133 struct kobj_attribute
*attr
, char *buf
)
135 struct rpc_xprt
*xprt
= rpc_sysfs_xprt_kobj_get_xprt(kobj
);
136 unsigned short srcport
= 0;
137 size_t buflen
= PAGE_SIZE
;
140 if (!xprt
|| !xprt_connected(xprt
)) {
141 ret
= sprintf(buf
, "<closed>\n");
145 if (xprt
->ops
->get_srcport
)
146 srcport
= xprt
->ops
->get_srcport(xprt
);
148 ret
= snprintf(buf
, buflen
,
149 "last_used=%lu\ncur_cong=%lu\ncong_win=%lu\n"
150 "max_num_slots=%u\nmin_num_slots=%u\nnum_reqs=%u\n"
151 "binding_q_len=%u\nsending_q_len=%u\npending_q_len=%u\n"
152 "backlog_q_len=%u\nmain_xprt=%d\nsrc_port=%u\n"
153 "tasks_queuelen=%ld\ndst_port=%s\n",
154 xprt
->last_used
, xprt
->cong
, xprt
->cwnd
, xprt
->max_reqs
,
155 xprt
->min_reqs
, xprt
->num_reqs
, xprt
->binding
.qlen
,
156 xprt
->sending
.qlen
, xprt
->pending
.qlen
,
157 xprt
->backlog
.qlen
, xprt
->main
, srcport
,
158 atomic_long_read(&xprt
->queuelen
),
159 xprt
->address_strings
[RPC_DISPLAY_PORT
]);
165 static ssize_t
rpc_sysfs_xprt_state_show(struct kobject
*kobj
,
166 struct kobj_attribute
*attr
,
169 struct rpc_xprt
*xprt
= rpc_sysfs_xprt_kobj_get_xprt(kobj
);
171 int locked
, connected
, connecting
, close_wait
, bound
, binding
,
172 closing
, congested
, cwnd_wait
, write_space
, offline
, remove
;
174 if (!(xprt
&& xprt
->state
)) {
175 ret
= sprintf(buf
, "state=CLOSED\n");
177 locked
= test_bit(XPRT_LOCKED
, &xprt
->state
);
178 connected
= test_bit(XPRT_CONNECTED
, &xprt
->state
);
179 connecting
= test_bit(XPRT_CONNECTING
, &xprt
->state
);
180 close_wait
= test_bit(XPRT_CLOSE_WAIT
, &xprt
->state
);
181 bound
= test_bit(XPRT_BOUND
, &xprt
->state
);
182 binding
= test_bit(XPRT_BINDING
, &xprt
->state
);
183 closing
= test_bit(XPRT_CLOSING
, &xprt
->state
);
184 congested
= test_bit(XPRT_CONGESTED
, &xprt
->state
);
185 cwnd_wait
= test_bit(XPRT_CWND_WAIT
, &xprt
->state
);
186 write_space
= test_bit(XPRT_WRITE_SPACE
, &xprt
->state
);
187 offline
= test_bit(XPRT_OFFLINE
, &xprt
->state
);
188 remove
= test_bit(XPRT_REMOVE
, &xprt
->state
);
190 ret
= sprintf(buf
, "state=%s %s %s %s %s %s %s %s %s %s %s %s\n",
191 locked
? "LOCKED" : "",
192 connected
? "CONNECTED" : "",
193 connecting
? "CONNECTING" : "",
194 close_wait
? "CLOSE_WAIT" : "",
195 bound
? "BOUND" : "",
196 binding
? "BOUNDING" : "",
197 closing
? "CLOSING" : "",
198 congested
? "CONGESTED" : "",
199 cwnd_wait
? "CWND_WAIT" : "",
200 write_space
? "WRITE_SPACE" : "",
201 offline
? "OFFLINE" : "",
202 remove
? "REMOVE" : "");
209 static ssize_t
rpc_sysfs_xprt_switch_info_show(struct kobject
*kobj
,
210 struct kobj_attribute
*attr
,
213 struct rpc_xprt_switch
*xprt_switch
=
214 rpc_sysfs_xprt_switch_kobj_get_xprt(kobj
);
219 ret
= sprintf(buf
, "num_xprts=%u\nnum_active=%u\n"
220 "num_unique_destaddr=%u\nqueue_len=%ld\n",
221 xprt_switch
->xps_nxprts
, xprt_switch
->xps_nactive
,
222 xprt_switch
->xps_nunique_destaddr_xprts
,
223 atomic_long_read(&xprt_switch
->xps_queuelen
));
224 xprt_switch_put(xprt_switch
);
228 static ssize_t
rpc_sysfs_xprt_dstaddr_store(struct kobject
*kobj
,
229 struct kobj_attribute
*attr
,
230 const char *buf
, size_t count
)
232 struct rpc_xprt
*xprt
= rpc_sysfs_xprt_kobj_get_xprt(kobj
);
233 struct sockaddr
*saddr
;
236 struct xprt_addr
*saved_addr
;
241 if (!(xprt
->xprt_class
->ident
== XPRT_TRANSPORT_TCP
||
242 xprt
->xprt_class
->ident
== XPRT_TRANSPORT_TCP_TLS
||
243 xprt
->xprt_class
->ident
== XPRT_TRANSPORT_RDMA
)) {
248 if (wait_on_bit_lock(&xprt
->state
, XPRT_LOCKED
, TASK_KILLABLE
)) {
252 saddr
= (struct sockaddr
*)&xprt
->addr
;
253 port
= rpc_get_port(saddr
);
255 /* buf_len is the len until the first occurence of either
258 buf_len
= strcspn(buf
, "\n");
260 dst_addr
= kstrndup(buf
, buf_len
, GFP_KERNEL
);
263 saved_addr
= kzalloc(sizeof(*saved_addr
), GFP_KERNEL
);
267 rcu_dereference_raw(xprt
->address_strings
[RPC_DISPLAY_ADDR
]);
268 rcu_assign_pointer(xprt
->address_strings
[RPC_DISPLAY_ADDR
], dst_addr
);
269 call_rcu(&saved_addr
->rcu
, free_xprt_addr
);
270 xprt
->addrlen
= rpc_pton(xprt
->xprt_net
, buf
, buf_len
, saddr
,
272 rpc_set_port(saddr
, port
);
274 xprt_force_disconnect(xprt
);
276 xprt_release_write(xprt
, NULL
);
287 static ssize_t
rpc_sysfs_xprt_state_change(struct kobject
*kobj
,
288 struct kobj_attribute
*attr
,
289 const char *buf
, size_t count
)
291 struct rpc_xprt
*xprt
= rpc_sysfs_xprt_kobj_get_xprt(kobj
);
292 int offline
= 0, online
= 0, remove
= 0;
293 struct rpc_xprt_switch
*xps
= rpc_sysfs_xprt_kobj_get_xprt_switch(kobj
);
300 if (!strncmp(buf
, "offline", 7))
302 else if (!strncmp(buf
, "online", 6))
304 else if (!strncmp(buf
, "remove", 6))
311 if (wait_on_bit_lock(&xprt
->state
, XPRT_LOCKED
, TASK_KILLABLE
)) {
320 xprt_set_offline_locked(xprt
, xps
);
322 xprt_set_online_locked(xprt
, xps
);
324 if (test_bit(XPRT_OFFLINE
, &xprt
->state
))
325 xprt_delete_locked(xprt
, xps
);
331 xprt_release_write(xprt
, NULL
);
334 xprt_switch_put(xps
);
338 int rpc_sysfs_init(void)
340 rpc_sunrpc_kset
= kset_create_and_add("sunrpc", NULL
, kernel_kobj
);
341 if (!rpc_sunrpc_kset
)
343 rpc_sunrpc_client_kobj
=
344 rpc_sysfs_object_alloc("rpc-clients", rpc_sunrpc_kset
, NULL
);
345 if (!rpc_sunrpc_client_kobj
)
347 rpc_sunrpc_xprt_switch_kobj
=
348 rpc_sysfs_object_alloc("xprt-switches", rpc_sunrpc_kset
, NULL
);
349 if (!rpc_sunrpc_xprt_switch_kobj
)
353 kobject_put(rpc_sunrpc_client_kobj
);
354 rpc_sunrpc_client_kobj
= NULL
;
356 kset_unregister(rpc_sunrpc_kset
);
357 rpc_sunrpc_kset
= NULL
;
361 static void rpc_sysfs_client_release(struct kobject
*kobj
)
363 struct rpc_sysfs_client
*c
;
365 c
= container_of(kobj
, struct rpc_sysfs_client
, kobject
);
369 static void rpc_sysfs_xprt_switch_release(struct kobject
*kobj
)
371 struct rpc_sysfs_xprt_switch
*xprt_switch
;
373 xprt_switch
= container_of(kobj
, struct rpc_sysfs_xprt_switch
, kobject
);
377 static void rpc_sysfs_xprt_release(struct kobject
*kobj
)
379 struct rpc_sysfs_xprt
*xprt
;
381 xprt
= container_of(kobj
, struct rpc_sysfs_xprt
, kobject
);
385 static const void *rpc_sysfs_client_namespace(const struct kobject
*kobj
)
387 return container_of(kobj
, struct rpc_sysfs_client
, kobject
)->net
;
390 static const void *rpc_sysfs_xprt_switch_namespace(const struct kobject
*kobj
)
392 return container_of(kobj
, struct rpc_sysfs_xprt_switch
, kobject
)->net
;
395 static const void *rpc_sysfs_xprt_namespace(const struct kobject
*kobj
)
397 return container_of(kobj
, struct rpc_sysfs_xprt
,
398 kobject
)->xprt
->xprt_net
;
401 static struct kobj_attribute rpc_sysfs_xprt_dstaddr
= __ATTR(dstaddr
,
402 0644, rpc_sysfs_xprt_dstaddr_show
, rpc_sysfs_xprt_dstaddr_store
);
404 static struct kobj_attribute rpc_sysfs_xprt_srcaddr
= __ATTR(srcaddr
,
405 0644, rpc_sysfs_xprt_srcaddr_show
, NULL
);
407 static struct kobj_attribute rpc_sysfs_xprt_info
= __ATTR(xprt_info
,
408 0444, rpc_sysfs_xprt_info_show
, NULL
);
410 static struct kobj_attribute rpc_sysfs_xprt_change_state
= __ATTR(xprt_state
,
411 0644, rpc_sysfs_xprt_state_show
, rpc_sysfs_xprt_state_change
);
413 static struct attribute
*rpc_sysfs_xprt_attrs
[] = {
414 &rpc_sysfs_xprt_dstaddr
.attr
,
415 &rpc_sysfs_xprt_srcaddr
.attr
,
416 &rpc_sysfs_xprt_info
.attr
,
417 &rpc_sysfs_xprt_change_state
.attr
,
420 ATTRIBUTE_GROUPS(rpc_sysfs_xprt
);
422 static struct kobj_attribute rpc_sysfs_xprt_switch_info
=
423 __ATTR(xprt_switch_info
, 0444, rpc_sysfs_xprt_switch_info_show
, NULL
);
425 static struct attribute
*rpc_sysfs_xprt_switch_attrs
[] = {
426 &rpc_sysfs_xprt_switch_info
.attr
,
429 ATTRIBUTE_GROUPS(rpc_sysfs_xprt_switch
);
431 static const struct kobj_type rpc_sysfs_client_type
= {
432 .release
= rpc_sysfs_client_release
,
433 .sysfs_ops
= &kobj_sysfs_ops
,
434 .namespace = rpc_sysfs_client_namespace
,
437 static const struct kobj_type rpc_sysfs_xprt_switch_type
= {
438 .release
= rpc_sysfs_xprt_switch_release
,
439 .default_groups
= rpc_sysfs_xprt_switch_groups
,
440 .sysfs_ops
= &kobj_sysfs_ops
,
441 .namespace = rpc_sysfs_xprt_switch_namespace
,
444 static const struct kobj_type rpc_sysfs_xprt_type
= {
445 .release
= rpc_sysfs_xprt_release
,
446 .default_groups
= rpc_sysfs_xprt_groups
,
447 .sysfs_ops
= &kobj_sysfs_ops
,
448 .namespace = rpc_sysfs_xprt_namespace
,
451 void rpc_sysfs_exit(void)
453 kobject_put(rpc_sunrpc_client_kobj
);
454 kobject_put(rpc_sunrpc_xprt_switch_kobj
);
455 kset_unregister(rpc_sunrpc_kset
);
458 static struct rpc_sysfs_client
*rpc_sysfs_client_alloc(struct kobject
*parent
,
462 struct rpc_sysfs_client
*p
;
464 p
= kzalloc(sizeof(*p
), GFP_KERNEL
);
467 p
->kobject
.kset
= rpc_sunrpc_kset
;
468 if (kobject_init_and_add(&p
->kobject
, &rpc_sysfs_client_type
,
469 parent
, "clnt-%d", clid
) == 0)
471 kobject_put(&p
->kobject
);
476 static struct rpc_sysfs_xprt_switch
*
477 rpc_sysfs_xprt_switch_alloc(struct kobject
*parent
,
478 struct rpc_xprt_switch
*xprt_switch
,
482 struct rpc_sysfs_xprt_switch
*p
;
484 p
= kzalloc(sizeof(*p
), gfp_flags
);
487 p
->kobject
.kset
= rpc_sunrpc_kset
;
488 if (kobject_init_and_add(&p
->kobject
,
489 &rpc_sysfs_xprt_switch_type
,
491 xprt_switch
->xps_id
) == 0)
493 kobject_put(&p
->kobject
);
498 static struct rpc_sysfs_xprt
*rpc_sysfs_xprt_alloc(struct kobject
*parent
,
499 struct rpc_xprt
*xprt
,
502 struct rpc_sysfs_xprt
*p
;
504 p
= kzalloc(sizeof(*p
), gfp_flags
);
507 p
->kobject
.kset
= rpc_sunrpc_kset
;
508 if (kobject_init_and_add(&p
->kobject
, &rpc_sysfs_xprt_type
,
509 parent
, "xprt-%d-%s", xprt
->id
,
510 xprt
->address_strings
[RPC_DISPLAY_PROTO
]) == 0)
512 kobject_put(&p
->kobject
);
517 void rpc_sysfs_client_setup(struct rpc_clnt
*clnt
,
518 struct rpc_xprt_switch
*xprt_switch
,
521 struct rpc_sysfs_client
*rpc_client
;
522 struct rpc_sysfs_xprt_switch
*xswitch
=
523 (struct rpc_sysfs_xprt_switch
*)xprt_switch
->xps_sysfs
;
528 rpc_client
= rpc_sysfs_client_alloc(rpc_sunrpc_client_kobj
,
531 char name
[] = "switch";
534 clnt
->cl_sysfs
= rpc_client
;
535 rpc_client
->clnt
= clnt
;
536 rpc_client
->xprt_switch
= xprt_switch
;
537 kobject_uevent(&rpc_client
->kobject
, KOBJ_ADD
);
538 ret
= sysfs_create_link_nowarn(&rpc_client
->kobject
,
539 &xswitch
->kobject
, name
);
541 pr_warn("can't create link to %s in sysfs (%d)\n",
546 void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch
*xprt_switch
,
547 struct rpc_xprt
*xprt
,
550 struct rpc_sysfs_xprt_switch
*rpc_xprt_switch
;
553 if (xprt_switch
->xps_net
)
554 net
= xprt_switch
->xps_net
;
556 net
= xprt
->xprt_net
;
558 rpc_sysfs_xprt_switch_alloc(rpc_sunrpc_xprt_switch_kobj
,
559 xprt_switch
, net
, gfp_flags
);
560 if (rpc_xprt_switch
) {
561 xprt_switch
->xps_sysfs
= rpc_xprt_switch
;
562 rpc_xprt_switch
->xprt_switch
= xprt_switch
;
563 rpc_xprt_switch
->xprt
= xprt
;
564 kobject_uevent(&rpc_xprt_switch
->kobject
, KOBJ_ADD
);
566 xprt_switch
->xps_sysfs
= NULL
;
570 void rpc_sysfs_xprt_setup(struct rpc_xprt_switch
*xprt_switch
,
571 struct rpc_xprt
*xprt
,
574 struct rpc_sysfs_xprt
*rpc_xprt
;
575 struct rpc_sysfs_xprt_switch
*switch_obj
=
576 (struct rpc_sysfs_xprt_switch
*)xprt_switch
->xps_sysfs
;
581 rpc_xprt
= rpc_sysfs_xprt_alloc(&switch_obj
->kobject
, xprt
, gfp_flags
);
583 xprt
->xprt_sysfs
= rpc_xprt
;
584 rpc_xprt
->xprt
= xprt
;
585 rpc_xprt
->xprt_switch
= xprt_switch
;
586 kobject_uevent(&rpc_xprt
->kobject
, KOBJ_ADD
);
590 void rpc_sysfs_client_destroy(struct rpc_clnt
*clnt
)
592 struct rpc_sysfs_client
*rpc_client
= clnt
->cl_sysfs
;
595 char name
[] = "switch";
597 sysfs_remove_link(&rpc_client
->kobject
, name
);
598 kobject_uevent(&rpc_client
->kobject
, KOBJ_REMOVE
);
599 kobject_del(&rpc_client
->kobject
);
600 kobject_put(&rpc_client
->kobject
);
601 clnt
->cl_sysfs
= NULL
;
605 void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch
*xprt_switch
)
607 struct rpc_sysfs_xprt_switch
*rpc_xprt_switch
= xprt_switch
->xps_sysfs
;
609 if (rpc_xprt_switch
) {
610 kobject_uevent(&rpc_xprt_switch
->kobject
, KOBJ_REMOVE
);
611 kobject_del(&rpc_xprt_switch
->kobject
);
612 kobject_put(&rpc_xprt_switch
->kobject
);
613 xprt_switch
->xps_sysfs
= NULL
;
617 void rpc_sysfs_xprt_destroy(struct rpc_xprt
*xprt
)
619 struct rpc_sysfs_xprt
*rpc_xprt
= xprt
->xprt_sysfs
;
622 kobject_uevent(&rpc_xprt
->kobject
, KOBJ_REMOVE
);
623 kobject_del(&rpc_xprt
->kobject
);
624 kobject_put(&rpc_xprt
->kobject
);
625 xprt
->xprt_sysfs
= NULL
;