1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2020 Anna Schumaker <Anna.Schumaker@Netapp.com>
4 */
5 #include <linux/sunrpc/clnt.h>
6 #include <linux/kobject.h>
7 #include <linux/sunrpc/addr.h>
8 #include <linux/sunrpc/xprtsock.h>
9
10 #include "sysfs.h"
11
12 struct xprt_addr {
13 const char *addr;
14 struct rcu_head rcu;
15 };
16
free_xprt_addr(struct rcu_head * head)17 static void free_xprt_addr(struct rcu_head *head)
18 {
19 struct xprt_addr *addr = container_of(head, struct xprt_addr, rcu);
20
21 kfree(addr->addr);
22 kfree(addr);
23 }
24
25 static struct kset *rpc_sunrpc_kset;
26 static struct kobject *rpc_sunrpc_client_kobj, *rpc_sunrpc_xprt_switch_kobj;
27
rpc_sysfs_object_release(struct kobject * kobj)28 static void rpc_sysfs_object_release(struct kobject *kobj)
29 {
30 kfree(kobj);
31 }
32
33 static const struct kobj_ns_type_operations *
rpc_sysfs_object_child_ns_type(const struct kobject * kobj)34 rpc_sysfs_object_child_ns_type(const struct kobject *kobj)
35 {
36 return &net_ns_type_operations;
37 }
38
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,
43 };
44
rpc_sysfs_object_alloc(const char * name,struct kset * kset,struct kobject * parent)45 static struct kobject *rpc_sysfs_object_alloc(const char *name,
46 struct kset *kset,
47 struct kobject *parent)
48 {
49 struct kobject *kobj;
50
51 kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
52 if (kobj) {
53 kobj->kset = kset;
54 if (kobject_init_and_add(kobj, &rpc_sysfs_object_type,
55 parent, "%s", name) == 0)
56 return kobj;
57 kobject_put(kobj);
58 }
59 return NULL;
60 }
61
62 static inline struct rpc_clnt *
rpc_sysfs_client_kobj_get_clnt(struct kobject * kobj)63 rpc_sysfs_client_kobj_get_clnt(struct kobject *kobj)
64 {
65 struct rpc_sysfs_client *c = container_of(kobj,
66 struct rpc_sysfs_client, kobject);
67 struct rpc_clnt *ret = c->clnt;
68
69 return refcount_inc_not_zero(&ret->cl_count) ? ret : NULL;
70 }
71
72 static inline struct rpc_xprt *
rpc_sysfs_xprt_kobj_get_xprt(struct kobject * kobj)73 rpc_sysfs_xprt_kobj_get_xprt(struct kobject *kobj)
74 {
75 struct rpc_sysfs_xprt *x = container_of(kobj,
76 struct rpc_sysfs_xprt, kobject);
77
78 return xprt_get(x->xprt);
79 }
80
81 static inline struct rpc_xprt_switch *
rpc_sysfs_xprt_kobj_get_xprt_switch(struct kobject * kobj)82 rpc_sysfs_xprt_kobj_get_xprt_switch(struct kobject *kobj)
83 {
84 struct rpc_sysfs_xprt *x = container_of(kobj,
85 struct rpc_sysfs_xprt, kobject);
86
87 return xprt_switch_get(x->xprt_switch);
88 }
89
90 static inline struct rpc_xprt_switch *
rpc_sysfs_xprt_switch_kobj_get_xprt(struct kobject * kobj)91 rpc_sysfs_xprt_switch_kobj_get_xprt(struct kobject *kobj)
92 {
93 struct rpc_sysfs_xprt_switch *x = container_of(kobj,
94 struct rpc_sysfs_xprt_switch, kobject);
95
96 return xprt_switch_get(x->xprt_switch);
97 }
98
rpc_sysfs_clnt_version_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)99 static ssize_t rpc_sysfs_clnt_version_show(struct kobject *kobj,
100 struct kobj_attribute *attr,
101 char *buf)
102 {
103 struct rpc_clnt *clnt = rpc_sysfs_client_kobj_get_clnt(kobj);
104 ssize_t ret;
105
106 if (!clnt)
107 return sprintf(buf, "<closed>\n");
108
109 ret = sprintf(buf, "%u", clnt->cl_vers);
110 refcount_dec(&clnt->cl_count);
111 return ret;
112 }
113
rpc_sysfs_clnt_program_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)114 static ssize_t rpc_sysfs_clnt_program_show(struct kobject *kobj,
115 struct kobj_attribute *attr,
116 char *buf)
117 {
118 struct rpc_clnt *clnt = rpc_sysfs_client_kobj_get_clnt(kobj);
119 ssize_t ret;
120
121 if (!clnt)
122 return sprintf(buf, "<closed>\n");
123
124 ret = sprintf(buf, "%s", clnt->cl_program->name);
125 refcount_dec(&clnt->cl_count);
126 return ret;
127 }
128
rpc_sysfs_clnt_max_connect_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)129 static ssize_t rpc_sysfs_clnt_max_connect_show(struct kobject *kobj,
130 struct kobj_attribute *attr,
131 char *buf)
132 {
133 struct rpc_clnt *clnt = rpc_sysfs_client_kobj_get_clnt(kobj);
134 ssize_t ret;
135
136 if (!clnt)
137 return sprintf(buf, "<closed>\n");
138
139 ret = sprintf(buf, "%u\n", clnt->cl_max_connect);
140 refcount_dec(&clnt->cl_count);
141 return ret;
142 }
143
rpc_sysfs_xprt_dstaddr_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)144 static ssize_t rpc_sysfs_xprt_dstaddr_show(struct kobject *kobj,
145 struct kobj_attribute *attr,
146 char *buf)
147 {
148 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
149 ssize_t ret;
150
151 if (!xprt) {
152 ret = sprintf(buf, "<closed>\n");
153 goto out;
154 }
155 ret = sprintf(buf, "%s\n", xprt->address_strings[RPC_DISPLAY_ADDR]);
156 xprt_put(xprt);
157 out:
158 return ret;
159 }
160
rpc_sysfs_xprt_srcaddr_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)161 static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj,
162 struct kobj_attribute *attr,
163 char *buf)
164 {
165 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
166 size_t buflen = PAGE_SIZE;
167 ssize_t ret;
168
169 if (!xprt || !xprt_connected(xprt)) {
170 ret = sprintf(buf, "<closed>\n");
171 } else if (xprt->ops->get_srcaddr) {
172 ret = xprt->ops->get_srcaddr(xprt, buf, buflen);
173 if (ret > 0) {
174 if (ret < buflen - 1) {
175 buf[ret] = '\n';
176 ret++;
177 buf[ret] = '\0';
178 }
179 } else
180 ret = sprintf(buf, "<closed>\n");
181 } else
182 ret = sprintf(buf, "<not a socket>\n");
183 xprt_put(xprt);
184 return ret;
185 }
186
187 static const char *xprtsec_strings[] = {
188 [RPC_XPRTSEC_NONE] = "none",
189 [RPC_XPRTSEC_TLS_ANON] = "tls-anon",
190 [RPC_XPRTSEC_TLS_X509] = "tls-x509",
191 };
192
rpc_sysfs_xprt_xprtsec_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)193 static ssize_t rpc_sysfs_xprt_xprtsec_show(struct kobject *kobj,
194 struct kobj_attribute *attr,
195 char *buf)
196 {
197 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
198 ssize_t ret;
199
200 if (!xprt) {
201 ret = sprintf(buf, "<closed>\n");
202 goto out;
203 }
204
205 ret = sprintf(buf, "%s\n", xprtsec_strings[xprt->xprtsec.policy]);
206 xprt_put(xprt);
207 out:
208 return ret;
209
210 }
211
rpc_sysfs_xprt_info_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)212 static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj,
213 struct kobj_attribute *attr, char *buf)
214 {
215 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
216 unsigned short srcport = 0;
217 size_t buflen = PAGE_SIZE;
218 ssize_t ret;
219
220 if (!xprt || !xprt_connected(xprt)) {
221 ret = sprintf(buf, "<closed>\n");
222 goto out;
223 }
224
225 if (xprt->ops->get_srcport)
226 srcport = xprt->ops->get_srcport(xprt);
227
228 ret = snprintf(buf, buflen,
229 "last_used=%lu\ncur_cong=%lu\ncong_win=%lu\n"
230 "max_num_slots=%u\nmin_num_slots=%u\nnum_reqs=%u\n"
231 "binding_q_len=%u\nsending_q_len=%u\npending_q_len=%u\n"
232 "backlog_q_len=%u\nmain_xprt=%d\nsrc_port=%u\n"
233 "tasks_queuelen=%ld\ndst_port=%s\n",
234 xprt->last_used, xprt->cong, xprt->cwnd, xprt->max_reqs,
235 xprt->min_reqs, xprt->num_reqs, xprt->binding.qlen,
236 xprt->sending.qlen, xprt->pending.qlen,
237 xprt->backlog.qlen, xprt->main, srcport,
238 atomic_long_read(&xprt->queuelen),
239 xprt->address_strings[RPC_DISPLAY_PORT]);
240 out:
241 xprt_put(xprt);
242 return ret;
243 }
244
rpc_sysfs_xprt_state_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)245 static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
246 struct kobj_attribute *attr,
247 char *buf)
248 {
249 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
250 ssize_t ret;
251 int locked, connected, connecting, close_wait, bound, binding,
252 closing, congested, cwnd_wait, write_space, offline, remove;
253
254 if (!(xprt && xprt->state)) {
255 ret = sprintf(buf, "state=CLOSED\n");
256 } else {
257 locked = test_bit(XPRT_LOCKED, &xprt->state);
258 connected = test_bit(XPRT_CONNECTED, &xprt->state);
259 connecting = test_bit(XPRT_CONNECTING, &xprt->state);
260 close_wait = test_bit(XPRT_CLOSE_WAIT, &xprt->state);
261 bound = test_bit(XPRT_BOUND, &xprt->state);
262 binding = test_bit(XPRT_BINDING, &xprt->state);
263 closing = test_bit(XPRT_CLOSING, &xprt->state);
264 congested = test_bit(XPRT_CONGESTED, &xprt->state);
265 cwnd_wait = test_bit(XPRT_CWND_WAIT, &xprt->state);
266 write_space = test_bit(XPRT_WRITE_SPACE, &xprt->state);
267 offline = test_bit(XPRT_OFFLINE, &xprt->state);
268 remove = test_bit(XPRT_REMOVE, &xprt->state);
269
270 ret = sprintf(buf, "state=%s %s %s %s %s %s %s %s %s %s %s %s\n",
271 locked ? "LOCKED" : "",
272 connected ? "CONNECTED" : "",
273 connecting ? "CONNECTING" : "",
274 close_wait ? "CLOSE_WAIT" : "",
275 bound ? "BOUND" : "",
276 binding ? "BOUNDING" : "",
277 closing ? "CLOSING" : "",
278 congested ? "CONGESTED" : "",
279 cwnd_wait ? "CWND_WAIT" : "",
280 write_space ? "WRITE_SPACE" : "",
281 offline ? "OFFLINE" : "",
282 remove ? "REMOVE" : "");
283 }
284
285 xprt_put(xprt);
286 return ret;
287 }
288
rpc_sysfs_xprt_del_xprt_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)289 static ssize_t rpc_sysfs_xprt_del_xprt_show(struct kobject *kobj,
290 struct kobj_attribute *attr,
291 char *buf)
292 {
293 return sprintf(buf, "# delete this xprt\n");
294 }
295
296
rpc_sysfs_xprt_switch_info_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)297 static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj,
298 struct kobj_attribute *attr,
299 char *buf)
300 {
301 struct rpc_xprt_switch *xprt_switch =
302 rpc_sysfs_xprt_switch_kobj_get_xprt(kobj);
303 ssize_t ret;
304
305 if (!xprt_switch)
306 return 0;
307 ret = sprintf(buf, "num_xprts=%u\nnum_active=%u\n"
308 "num_unique_destaddr=%u\nqueue_len=%ld\n",
309 xprt_switch->xps_nxprts, xprt_switch->xps_nactive,
310 xprt_switch->xps_nunique_destaddr_xprts,
311 atomic_long_read(&xprt_switch->xps_queuelen));
312 xprt_switch_put(xprt_switch);
313 return ret;
314 }
315
rpc_sysfs_xprt_switch_add_xprt_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)316 static ssize_t rpc_sysfs_xprt_switch_add_xprt_show(struct kobject *kobj,
317 struct kobj_attribute *attr,
318 char *buf)
319 {
320 return sprintf(buf, "# add one xprt to this xprt_switch\n");
321 }
322
rpc_sysfs_xprt_switch_add_xprt_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)323 static ssize_t rpc_sysfs_xprt_switch_add_xprt_store(struct kobject *kobj,
324 struct kobj_attribute *attr,
325 const char *buf, size_t count)
326 {
327 struct rpc_xprt_switch *xprt_switch =
328 rpc_sysfs_xprt_switch_kobj_get_xprt(kobj);
329 struct xprt_create xprt_create_args;
330 struct rpc_xprt *xprt, *new;
331
332 if (!xprt_switch)
333 return 0;
334
335 xprt = rpc_xprt_switch_get_main_xprt(xprt_switch);
336 if (!xprt)
337 goto out;
338
339 xprt_create_args.ident = xprt->xprt_class->ident;
340 xprt_create_args.net = xprt->xprt_net;
341 xprt_create_args.dstaddr = (struct sockaddr *)&xprt->addr;
342 xprt_create_args.addrlen = xprt->addrlen;
343 xprt_create_args.servername = xprt->servername;
344 xprt_create_args.bc_xprt = xprt->bc_xprt;
345 xprt_create_args.xprtsec = xprt->xprtsec;
346 xprt_create_args.connect_timeout = xprt->connect_timeout;
347 xprt_create_args.reconnect_timeout = xprt->max_reconnect_timeout;
348
349 new = xprt_create_transport(&xprt_create_args);
350 if (IS_ERR_OR_NULL(new)) {
351 count = PTR_ERR(new);
352 goto out_put_xprt;
353 }
354
355 rpc_xprt_switch_add_xprt(xprt_switch, new);
356 xprt_put(new);
357
358 out_put_xprt:
359 xprt_put(xprt);
360 out:
361 xprt_switch_put(xprt_switch);
362 return count;
363 }
364
rpc_sysfs_xprt_dstaddr_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)365 static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj,
366 struct kobj_attribute *attr,
367 const char *buf, size_t count)
368 {
369 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
370 struct sockaddr *saddr;
371 char *dst_addr;
372 int port;
373 struct xprt_addr *saved_addr;
374 size_t buf_len;
375
376 if (!xprt)
377 return 0;
378 if (!(xprt->xprt_class->ident == XPRT_TRANSPORT_TCP ||
379 xprt->xprt_class->ident == XPRT_TRANSPORT_TCP_TLS ||
380 xprt->xprt_class->ident == XPRT_TRANSPORT_RDMA)) {
381 xprt_put(xprt);
382 return -EOPNOTSUPP;
383 }
384
385 if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
386 count = -EINTR;
387 goto out_put;
388 }
389 saddr = (struct sockaddr *)&xprt->addr;
390 port = rpc_get_port(saddr);
391
392 /* buf_len is the len until the first occurence of either
393 * '\n' or '\0'
394 */
395 buf_len = strcspn(buf, "\n");
396
397 dst_addr = kstrndup(buf, buf_len, GFP_KERNEL);
398 if (!dst_addr)
399 goto out_err;
400 saved_addr = kzalloc(sizeof(*saved_addr), GFP_KERNEL);
401 if (!saved_addr)
402 goto out_err_free;
403 saved_addr->addr =
404 rcu_dereference_raw(xprt->address_strings[RPC_DISPLAY_ADDR]);
405 rcu_assign_pointer(xprt->address_strings[RPC_DISPLAY_ADDR], dst_addr);
406 call_rcu(&saved_addr->rcu, free_xprt_addr);
407 xprt->addrlen = rpc_pton(xprt->xprt_net, buf, buf_len, saddr,
408 sizeof(*saddr));
409 rpc_set_port(saddr, port);
410
411 xprt_force_disconnect(xprt);
412 out:
413 xprt_release_write(xprt, NULL);
414 out_put:
415 xprt_put(xprt);
416 return count;
417 out_err_free:
418 kfree(dst_addr);
419 out_err:
420 count = -ENOMEM;
421 goto out;
422 }
423
rpc_sysfs_xprt_state_change(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)424 static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj,
425 struct kobj_attribute *attr,
426 const char *buf, size_t count)
427 {
428 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
429 int offline = 0, online = 0, remove = 0;
430 struct rpc_xprt_switch *xps = rpc_sysfs_xprt_kobj_get_xprt_switch(kobj);
431
432 if (!xprt || !xps) {
433 count = 0;
434 goto out_put;
435 }
436
437 if (!strncmp(buf, "offline", 7))
438 offline = 1;
439 else if (!strncmp(buf, "online", 6))
440 online = 1;
441 else if (!strncmp(buf, "remove", 6))
442 remove = 1;
443 else {
444 count = -EINVAL;
445 goto out_put;
446 }
447
448 if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
449 count = -EINTR;
450 goto out_put;
451 }
452 if (xprt->main) {
453 count = -EINVAL;
454 goto release_tasks;
455 }
456 if (offline) {
457 xprt_set_offline_locked(xprt, xps);
458 } else if (online) {
459 xprt_set_online_locked(xprt, xps);
460 } else if (remove) {
461 if (test_bit(XPRT_OFFLINE, &xprt->state))
462 xprt_delete_locked(xprt, xps);
463 else
464 count = -EINVAL;
465 }
466
467 release_tasks:
468 xprt_release_write(xprt, NULL);
469 out_put:
470 xprt_put(xprt);
471 xprt_switch_put(xps);
472 return count;
473 }
474
rpc_sysfs_xprt_del_xprt(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)475 static ssize_t rpc_sysfs_xprt_del_xprt(struct kobject *kobj,
476 struct kobj_attribute *attr,
477 const char *buf, size_t count)
478 {
479 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
480 struct rpc_xprt_switch *xps = rpc_sysfs_xprt_kobj_get_xprt_switch(kobj);
481
482 if (!xprt || !xps) {
483 count = 0;
484 goto out;
485 }
486
487 if (xprt->main) {
488 count = -EINVAL;
489 goto release_tasks;
490 }
491
492 if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
493 count = -EINTR;
494 goto out_put;
495 }
496
497 xprt_set_offline_locked(xprt, xps);
498 xprt_delete_locked(xprt, xps);
499
500 release_tasks:
501 xprt_release_write(xprt, NULL);
502 out_put:
503 xprt_put(xprt);
504 xprt_switch_put(xps);
505 out:
506 return count;
507 }
508
rpc_sysfs_init(void)509 int rpc_sysfs_init(void)
510 {
511 rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, kernel_kobj);
512 if (!rpc_sunrpc_kset)
513 return -ENOMEM;
514 rpc_sunrpc_client_kobj =
515 rpc_sysfs_object_alloc("rpc-clients", rpc_sunrpc_kset, NULL);
516 if (!rpc_sunrpc_client_kobj)
517 goto err_client;
518 rpc_sunrpc_xprt_switch_kobj =
519 rpc_sysfs_object_alloc("xprt-switches", rpc_sunrpc_kset, NULL);
520 if (!rpc_sunrpc_xprt_switch_kobj)
521 goto err_switch;
522 return 0;
523 err_switch:
524 kobject_put(rpc_sunrpc_client_kobj);
525 rpc_sunrpc_client_kobj = NULL;
526 err_client:
527 kset_unregister(rpc_sunrpc_kset);
528 rpc_sunrpc_kset = NULL;
529 return -ENOMEM;
530 }
531
rpc_sysfs_client_release(struct kobject * kobj)532 static void rpc_sysfs_client_release(struct kobject *kobj)
533 {
534 struct rpc_sysfs_client *c;
535
536 c = container_of(kobj, struct rpc_sysfs_client, kobject);
537 kfree(c);
538 }
539
rpc_sysfs_xprt_switch_release(struct kobject * kobj)540 static void rpc_sysfs_xprt_switch_release(struct kobject *kobj)
541 {
542 struct rpc_sysfs_xprt_switch *xprt_switch;
543
544 xprt_switch = container_of(kobj, struct rpc_sysfs_xprt_switch, kobject);
545 kfree(xprt_switch);
546 }
547
rpc_sysfs_xprt_release(struct kobject * kobj)548 static void rpc_sysfs_xprt_release(struct kobject *kobj)
549 {
550 struct rpc_sysfs_xprt *xprt;
551
552 xprt = container_of(kobj, struct rpc_sysfs_xprt, kobject);
553 kfree(xprt);
554 }
555
rpc_sysfs_client_namespace(const struct kobject * kobj)556 static const void *rpc_sysfs_client_namespace(const struct kobject *kobj)
557 {
558 return container_of(kobj, struct rpc_sysfs_client, kobject)->net;
559 }
560
rpc_sysfs_xprt_switch_namespace(const struct kobject * kobj)561 static const void *rpc_sysfs_xprt_switch_namespace(const struct kobject *kobj)
562 {
563 return container_of(kobj, struct rpc_sysfs_xprt_switch, kobject)->net;
564 }
565
rpc_sysfs_xprt_namespace(const struct kobject * kobj)566 static const void *rpc_sysfs_xprt_namespace(const struct kobject *kobj)
567 {
568 return container_of(kobj, struct rpc_sysfs_xprt,
569 kobject)->xprt->xprt_net;
570 }
571
572 static struct kobj_attribute rpc_sysfs_clnt_version = __ATTR(rpc_version,
573 0444, rpc_sysfs_clnt_version_show, NULL);
574
575 static struct kobj_attribute rpc_sysfs_clnt_program = __ATTR(program,
576 0444, rpc_sysfs_clnt_program_show, NULL);
577
578 static struct kobj_attribute rpc_sysfs_clnt_max_connect = __ATTR(max_connect,
579 0444, rpc_sysfs_clnt_max_connect_show, NULL);
580
581 static struct attribute *rpc_sysfs_rpc_clnt_attrs[] = {
582 &rpc_sysfs_clnt_version.attr,
583 &rpc_sysfs_clnt_program.attr,
584 &rpc_sysfs_clnt_max_connect.attr,
585 NULL,
586 };
587 ATTRIBUTE_GROUPS(rpc_sysfs_rpc_clnt);
588
589 static struct kobj_attribute rpc_sysfs_xprt_dstaddr = __ATTR(dstaddr,
590 0644, rpc_sysfs_xprt_dstaddr_show, rpc_sysfs_xprt_dstaddr_store);
591
592 static struct kobj_attribute rpc_sysfs_xprt_srcaddr = __ATTR(srcaddr,
593 0644, rpc_sysfs_xprt_srcaddr_show, NULL);
594
595 static struct kobj_attribute rpc_sysfs_xprt_xprtsec = __ATTR(xprtsec,
596 0644, rpc_sysfs_xprt_xprtsec_show, NULL);
597
598 static struct kobj_attribute rpc_sysfs_xprt_info = __ATTR(xprt_info,
599 0444, rpc_sysfs_xprt_info_show, NULL);
600
601 static struct kobj_attribute rpc_sysfs_xprt_change_state = __ATTR(xprt_state,
602 0644, rpc_sysfs_xprt_state_show, rpc_sysfs_xprt_state_change);
603
604 static struct kobj_attribute rpc_sysfs_xprt_del = __ATTR(del_xprt,
605 0644, rpc_sysfs_xprt_del_xprt_show, rpc_sysfs_xprt_del_xprt);
606
607 static struct attribute *rpc_sysfs_xprt_attrs[] = {
608 &rpc_sysfs_xprt_dstaddr.attr,
609 &rpc_sysfs_xprt_srcaddr.attr,
610 &rpc_sysfs_xprt_xprtsec.attr,
611 &rpc_sysfs_xprt_info.attr,
612 &rpc_sysfs_xprt_change_state.attr,
613 &rpc_sysfs_xprt_del.attr,
614 NULL,
615 };
616 ATTRIBUTE_GROUPS(rpc_sysfs_xprt);
617
618 static struct kobj_attribute rpc_sysfs_xprt_switch_info =
619 __ATTR(xprt_switch_info, 0444, rpc_sysfs_xprt_switch_info_show, NULL);
620
621 static struct kobj_attribute rpc_sysfs_xprt_switch_add_xprt =
622 __ATTR(add_xprt, 0644, rpc_sysfs_xprt_switch_add_xprt_show,
623 rpc_sysfs_xprt_switch_add_xprt_store);
624
625 static struct attribute *rpc_sysfs_xprt_switch_attrs[] = {
626 &rpc_sysfs_xprt_switch_info.attr,
627 &rpc_sysfs_xprt_switch_add_xprt.attr,
628 NULL,
629 };
630 ATTRIBUTE_GROUPS(rpc_sysfs_xprt_switch);
631
632 static const struct kobj_type rpc_sysfs_client_type = {
633 .release = rpc_sysfs_client_release,
634 .default_groups = rpc_sysfs_rpc_clnt_groups,
635 .sysfs_ops = &kobj_sysfs_ops,
636 .namespace = rpc_sysfs_client_namespace,
637 };
638
639 static const struct kobj_type rpc_sysfs_xprt_switch_type = {
640 .release = rpc_sysfs_xprt_switch_release,
641 .default_groups = rpc_sysfs_xprt_switch_groups,
642 .sysfs_ops = &kobj_sysfs_ops,
643 .namespace = rpc_sysfs_xprt_switch_namespace,
644 };
645
646 static const struct kobj_type rpc_sysfs_xprt_type = {
647 .release = rpc_sysfs_xprt_release,
648 .default_groups = rpc_sysfs_xprt_groups,
649 .sysfs_ops = &kobj_sysfs_ops,
650 .namespace = rpc_sysfs_xprt_namespace,
651 };
652
rpc_sysfs_exit(void)653 void rpc_sysfs_exit(void)
654 {
655 kobject_put(rpc_sunrpc_client_kobj);
656 kobject_put(rpc_sunrpc_xprt_switch_kobj);
657 kset_unregister(rpc_sunrpc_kset);
658 }
659
rpc_sysfs_client_alloc(struct kobject * parent,struct net * net,int clid)660 static struct rpc_sysfs_client *rpc_sysfs_client_alloc(struct kobject *parent,
661 struct net *net,
662 int clid)
663 {
664 struct rpc_sysfs_client *p;
665
666 p = kzalloc(sizeof(*p), GFP_KERNEL);
667 if (p) {
668 p->net = net;
669 p->kobject.kset = rpc_sunrpc_kset;
670 if (kobject_init_and_add(&p->kobject, &rpc_sysfs_client_type,
671 parent, "clnt-%d", clid) == 0)
672 return p;
673 kobject_put(&p->kobject);
674 }
675 return NULL;
676 }
677
678 static struct rpc_sysfs_xprt_switch *
rpc_sysfs_xprt_switch_alloc(struct kobject * parent,struct rpc_xprt_switch * xprt_switch,struct net * net,gfp_t gfp_flags)679 rpc_sysfs_xprt_switch_alloc(struct kobject *parent,
680 struct rpc_xprt_switch *xprt_switch,
681 struct net *net,
682 gfp_t gfp_flags)
683 {
684 struct rpc_sysfs_xprt_switch *p;
685
686 p = kzalloc(sizeof(*p), gfp_flags);
687 if (p) {
688 p->net = net;
689 p->kobject.kset = rpc_sunrpc_kset;
690 if (kobject_init_and_add(&p->kobject,
691 &rpc_sysfs_xprt_switch_type,
692 parent, "switch-%d",
693 xprt_switch->xps_id) == 0)
694 return p;
695 kobject_put(&p->kobject);
696 }
697 return NULL;
698 }
699
rpc_sysfs_xprt_alloc(struct kobject * parent,struct rpc_xprt * xprt,gfp_t gfp_flags)700 static struct rpc_sysfs_xprt *rpc_sysfs_xprt_alloc(struct kobject *parent,
701 struct rpc_xprt *xprt,
702 gfp_t gfp_flags)
703 {
704 struct rpc_sysfs_xprt *p;
705
706 p = kzalloc(sizeof(*p), gfp_flags);
707 if (!p)
708 goto out;
709 p->kobject.kset = rpc_sunrpc_kset;
710 if (kobject_init_and_add(&p->kobject, &rpc_sysfs_xprt_type,
711 parent, "xprt-%d-%s", xprt->id,
712 xprt->address_strings[RPC_DISPLAY_PROTO]) == 0)
713 return p;
714 kobject_put(&p->kobject);
715 out:
716 return NULL;
717 }
718
rpc_sysfs_client_setup(struct rpc_clnt * clnt,struct rpc_xprt_switch * xprt_switch,struct net * net)719 void rpc_sysfs_client_setup(struct rpc_clnt *clnt,
720 struct rpc_xprt_switch *xprt_switch,
721 struct net *net)
722 {
723 struct rpc_sysfs_client *rpc_client;
724 struct rpc_sysfs_xprt_switch *xswitch =
725 (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
726
727 if (!xswitch)
728 return;
729
730 rpc_client = rpc_sysfs_client_alloc(rpc_sunrpc_client_kobj,
731 net, clnt->cl_clid);
732 if (rpc_client) {
733 char name[] = "switch";
734 int ret;
735
736 clnt->cl_sysfs = rpc_client;
737 rpc_client->clnt = clnt;
738 rpc_client->xprt_switch = xprt_switch;
739 kobject_uevent(&rpc_client->kobject, KOBJ_ADD);
740 ret = sysfs_create_link_nowarn(&rpc_client->kobject,
741 &xswitch->kobject, name);
742 if (ret)
743 pr_warn("can't create link to %s in sysfs (%d)\n",
744 name, ret);
745 }
746 }
747
rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch * xprt_switch,struct rpc_xprt * xprt,gfp_t gfp_flags)748 void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch,
749 struct rpc_xprt *xprt,
750 gfp_t gfp_flags)
751 {
752 struct rpc_sysfs_xprt_switch *rpc_xprt_switch;
753 struct net *net;
754
755 if (xprt_switch->xps_net)
756 net = xprt_switch->xps_net;
757 else
758 net = xprt->xprt_net;
759 rpc_xprt_switch =
760 rpc_sysfs_xprt_switch_alloc(rpc_sunrpc_xprt_switch_kobj,
761 xprt_switch, net, gfp_flags);
762 if (rpc_xprt_switch) {
763 xprt_switch->xps_sysfs = rpc_xprt_switch;
764 rpc_xprt_switch->xprt_switch = xprt_switch;
765 rpc_xprt_switch->xprt = xprt;
766 kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD);
767 } else {
768 xprt_switch->xps_sysfs = NULL;
769 }
770 }
771
rpc_sysfs_xprt_setup(struct rpc_xprt_switch * xprt_switch,struct rpc_xprt * xprt,gfp_t gfp_flags)772 void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch,
773 struct rpc_xprt *xprt,
774 gfp_t gfp_flags)
775 {
776 struct rpc_sysfs_xprt *rpc_xprt;
777 struct rpc_sysfs_xprt_switch *switch_obj =
778 (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
779
780 if (!switch_obj)
781 return;
782
783 rpc_xprt = rpc_sysfs_xprt_alloc(&switch_obj->kobject, xprt, gfp_flags);
784 if (rpc_xprt) {
785 xprt->xprt_sysfs = rpc_xprt;
786 rpc_xprt->xprt = xprt;
787 rpc_xprt->xprt_switch = xprt_switch;
788 kobject_uevent(&rpc_xprt->kobject, KOBJ_ADD);
789 }
790 }
791
rpc_sysfs_client_destroy(struct rpc_clnt * clnt)792 void rpc_sysfs_client_destroy(struct rpc_clnt *clnt)
793 {
794 struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs;
795
796 if (rpc_client) {
797 char name[] = "switch";
798
799 sysfs_remove_link(&rpc_client->kobject, name);
800 kobject_uevent(&rpc_client->kobject, KOBJ_REMOVE);
801 kobject_del(&rpc_client->kobject);
802 kobject_put(&rpc_client->kobject);
803 clnt->cl_sysfs = NULL;
804 }
805 }
806
rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch * xprt_switch)807 void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt_switch)
808 {
809 struct rpc_sysfs_xprt_switch *rpc_xprt_switch = xprt_switch->xps_sysfs;
810
811 if (rpc_xprt_switch) {
812 kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_REMOVE);
813 kobject_del(&rpc_xprt_switch->kobject);
814 kobject_put(&rpc_xprt_switch->kobject);
815 xprt_switch->xps_sysfs = NULL;
816 }
817 }
818
rpc_sysfs_xprt_destroy(struct rpc_xprt * xprt)819 void rpc_sysfs_xprt_destroy(struct rpc_xprt *xprt)
820 {
821 struct rpc_sysfs_xprt *rpc_xprt = xprt->xprt_sysfs;
822
823 if (rpc_xprt) {
824 kobject_uevent(&rpc_xprt->kobject, KOBJ_REMOVE);
825 kobject_del(&rpc_xprt->kobject);
826 kobject_put(&rpc_xprt->kobject);
827 xprt->xprt_sysfs = NULL;
828 }
829 }
830