Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
[linux-2.6-microblaze.git] / net / sunrpc / sysfs.c
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
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
28 static void rpc_sysfs_object_release(struct kobject *kobj)
29 {
30         kfree(kobj);
31 }
32
33 static const struct kobj_ns_type_operations *
34 rpc_sysfs_object_child_ns_type(struct kobject *kobj)
35 {
36         return &net_ns_type_operations;
37 }
38
39 static 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
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_xprt *
63 rpc_sysfs_xprt_kobj_get_xprt(struct kobject *kobj)
64 {
65         struct rpc_sysfs_xprt *x = container_of(kobj,
66                 struct rpc_sysfs_xprt, kobject);
67
68         return xprt_get(x->xprt);
69 }
70
71 static inline struct rpc_xprt_switch *
72 rpc_sysfs_xprt_kobj_get_xprt_switch(struct kobject *kobj)
73 {
74         struct rpc_sysfs_xprt *x = container_of(kobj,
75                 struct rpc_sysfs_xprt, kobject);
76
77         return xprt_switch_get(x->xprt_switch);
78 }
79
80 static inline struct rpc_xprt_switch *
81 rpc_sysfs_xprt_switch_kobj_get_xprt(struct kobject *kobj)
82 {
83         struct rpc_sysfs_xprt_switch *x = container_of(kobj,
84                 struct rpc_sysfs_xprt_switch, kobject);
85
86         return xprt_switch_get(x->xprt_switch);
87 }
88
89 static ssize_t rpc_sysfs_xprt_dstaddr_show(struct kobject *kobj,
90                                            struct kobj_attribute *attr,
91                                            char *buf)
92 {
93         struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
94         ssize_t ret;
95
96         if (!xprt)
97                 return 0;
98         ret = sprintf(buf, "%s\n", xprt->address_strings[RPC_DISPLAY_ADDR]);
99         xprt_put(xprt);
100         return ret + 1;
101 }
102
103 static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj,
104                                         struct kobj_attribute *attr,
105                                         char *buf)
106 {
107         struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
108         ssize_t ret;
109
110         if (!xprt)
111                 return 0;
112
113         ret = sprintf(buf, "last_used=%lu\ncur_cong=%lu\ncong_win=%lu\n"
114                        "max_num_slots=%u\nmin_num_slots=%u\nnum_reqs=%u\n"
115                        "binding_q_len=%u\nsending_q_len=%u\npending_q_len=%u\n"
116                        "backlog_q_len=%u\nmain_xprt=%d\nsrc_port=%u\n"
117                        "tasks_queuelen=%ld\n",
118                        xprt->last_used, xprt->cong, xprt->cwnd, xprt->max_reqs,
119                        xprt->min_reqs, xprt->num_reqs, xprt->binding.qlen,
120                        xprt->sending.qlen, xprt->pending.qlen,
121                        xprt->backlog.qlen, xprt->main,
122                        (xprt->xprt_class->ident == XPRT_TRANSPORT_TCP) ?
123                        get_srcport(xprt) : 0,
124                        atomic_long_read(&xprt->queuelen));
125         xprt_put(xprt);
126         return ret + 1;
127 }
128
129 static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
130                                          struct kobj_attribute *attr,
131                                          char *buf)
132 {
133         struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
134         ssize_t ret;
135         int locked, connected, connecting, close_wait, bound, binding,
136             closing, congested, cwnd_wait, write_space, offline, remove;
137
138         if (!xprt)
139                 return 0;
140
141         if (!xprt->state) {
142                 ret = sprintf(buf, "state=CLOSED\n");
143         } else {
144                 locked = test_bit(XPRT_LOCKED, &xprt->state);
145                 connected = test_bit(XPRT_CONNECTED, &xprt->state);
146                 connecting = test_bit(XPRT_CONNECTING, &xprt->state);
147                 close_wait = test_bit(XPRT_CLOSE_WAIT, &xprt->state);
148                 bound = test_bit(XPRT_BOUND, &xprt->state);
149                 binding = test_bit(XPRT_BINDING, &xprt->state);
150                 closing = test_bit(XPRT_CLOSING, &xprt->state);
151                 congested = test_bit(XPRT_CONGESTED, &xprt->state);
152                 cwnd_wait = test_bit(XPRT_CWND_WAIT, &xprt->state);
153                 write_space = test_bit(XPRT_WRITE_SPACE, &xprt->state);
154                 offline = test_bit(XPRT_OFFLINE, &xprt->state);
155                 remove = test_bit(XPRT_REMOVE, &xprt->state);
156
157                 ret = sprintf(buf, "state=%s %s %s %s %s %s %s %s %s %s %s %s\n",
158                               locked ? "LOCKED" : "",
159                               connected ? "CONNECTED" : "",
160                               connecting ? "CONNECTING" : "",
161                               close_wait ? "CLOSE_WAIT" : "",
162                               bound ? "BOUND" : "",
163                               binding ? "BOUNDING" : "",
164                               closing ? "CLOSING" : "",
165                               congested ? "CONGESTED" : "",
166                               cwnd_wait ? "CWND_WAIT" : "",
167                               write_space ? "WRITE_SPACE" : "",
168                               offline ? "OFFLINE" : "",
169                               remove ? "REMOVE" : "");
170         }
171
172         xprt_put(xprt);
173         return ret + 1;
174 }
175
176 static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj,
177                                                struct kobj_attribute *attr,
178                                                char *buf)
179 {
180         struct rpc_xprt_switch *xprt_switch =
181                 rpc_sysfs_xprt_switch_kobj_get_xprt(kobj);
182         ssize_t ret;
183
184         if (!xprt_switch)
185                 return 0;
186         ret = sprintf(buf, "num_xprts=%u\nnum_active=%u\nqueue_len=%ld\n",
187                       xprt_switch->xps_nxprts, xprt_switch->xps_nactive,
188                       atomic_long_read(&xprt_switch->xps_queuelen));
189         xprt_switch_put(xprt_switch);
190         return ret + 1;
191 }
192
193 static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj,
194                                             struct kobj_attribute *attr,
195                                             const char *buf, size_t count)
196 {
197         struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
198         struct sockaddr *saddr;
199         char *dst_addr;
200         int port;
201         struct xprt_addr *saved_addr;
202         size_t buf_len;
203
204         if (!xprt)
205                 return 0;
206         if (!(xprt->xprt_class->ident == XPRT_TRANSPORT_TCP ||
207               xprt->xprt_class->ident == XPRT_TRANSPORT_RDMA)) {
208                 xprt_put(xprt);
209                 return -EOPNOTSUPP;
210         }
211
212         if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
213                 count = -EINTR;
214                 goto out_put;
215         }
216         saddr = (struct sockaddr *)&xprt->addr;
217         port = rpc_get_port(saddr);
218
219         /* buf_len is the len until the first occurence of either
220          * '\n' or '\0'
221          */
222         buf_len = strcspn(buf, "\n");
223
224         dst_addr = kstrndup(buf, buf_len, GFP_KERNEL);
225         if (!dst_addr)
226                 goto out_err;
227         saved_addr = kzalloc(sizeof(*saved_addr), GFP_KERNEL);
228         if (!saved_addr)
229                 goto out_err_free;
230         saved_addr->addr =
231                 rcu_dereference_raw(xprt->address_strings[RPC_DISPLAY_ADDR]);
232         rcu_assign_pointer(xprt->address_strings[RPC_DISPLAY_ADDR], dst_addr);
233         call_rcu(&saved_addr->rcu, free_xprt_addr);
234         xprt->addrlen = rpc_pton(xprt->xprt_net, buf, buf_len, saddr,
235                                  sizeof(*saddr));
236         rpc_set_port(saddr, port);
237
238         xprt_force_disconnect(xprt);
239 out:
240         xprt_release_write(xprt, NULL);
241 out_put:
242         xprt_put(xprt);
243         return count;
244 out_err_free:
245         kfree(dst_addr);
246 out_err:
247         count = -ENOMEM;
248         goto out;
249 }
250
251 static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj,
252                                            struct kobj_attribute *attr,
253                                            const char *buf, size_t count)
254 {
255         struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
256         int offline = 0, online = 0, remove = 0;
257         struct rpc_xprt_switch *xps = rpc_sysfs_xprt_kobj_get_xprt_switch(kobj);
258
259         if (!xprt)
260                 return 0;
261
262         if (!strncmp(buf, "offline", 7))
263                 offline = 1;
264         else if (!strncmp(buf, "online", 6))
265                 online = 1;
266         else if (!strncmp(buf, "remove", 6))
267                 remove = 1;
268         else
269                 return -EINVAL;
270
271         if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
272                 count = -EINTR;
273                 goto out_put;
274         }
275         if (xprt->main) {
276                 count = -EINVAL;
277                 goto release_tasks;
278         }
279         if (offline) {
280                 set_bit(XPRT_OFFLINE, &xprt->state);
281                 spin_lock(&xps->xps_lock);
282                 xps->xps_nactive--;
283                 spin_unlock(&xps->xps_lock);
284         } else if (online) {
285                 clear_bit(XPRT_OFFLINE, &xprt->state);
286                 spin_lock(&xps->xps_lock);
287                 xps->xps_nactive++;
288                 spin_unlock(&xps->xps_lock);
289         } else if (remove) {
290                 if (test_bit(XPRT_OFFLINE, &xprt->state)) {
291                         set_bit(XPRT_REMOVE, &xprt->state);
292                         xprt_force_disconnect(xprt);
293                         if (test_bit(XPRT_CONNECTED, &xprt->state)) {
294                                 if (!xprt->sending.qlen &&
295                                     !xprt->pending.qlen &&
296                                     !xprt->backlog.qlen &&
297                                     !atomic_long_read(&xprt->queuelen))
298                                         rpc_xprt_switch_remove_xprt(xps, xprt);
299                         }
300                 } else {
301                         count = -EINVAL;
302                 }
303         }
304
305 release_tasks:
306         xprt_release_write(xprt, NULL);
307 out_put:
308         xprt_put(xprt);
309         xprt_switch_put(xps);
310         return count;
311 }
312
313 int rpc_sysfs_init(void)
314 {
315         rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, kernel_kobj);
316         if (!rpc_sunrpc_kset)
317                 return -ENOMEM;
318         rpc_sunrpc_client_kobj =
319                 rpc_sysfs_object_alloc("rpc-clients", rpc_sunrpc_kset, NULL);
320         if (!rpc_sunrpc_client_kobj)
321                 goto err_client;
322         rpc_sunrpc_xprt_switch_kobj =
323                 rpc_sysfs_object_alloc("xprt-switches", rpc_sunrpc_kset, NULL);
324         if (!rpc_sunrpc_xprt_switch_kobj)
325                 goto err_switch;
326         return 0;
327 err_switch:
328         kobject_put(rpc_sunrpc_client_kobj);
329         rpc_sunrpc_client_kobj = NULL;
330 err_client:
331         kset_unregister(rpc_sunrpc_kset);
332         rpc_sunrpc_kset = NULL;
333         return -ENOMEM;
334 }
335
336 static void rpc_sysfs_client_release(struct kobject *kobj)
337 {
338         struct rpc_sysfs_client *c;
339
340         c = container_of(kobj, struct rpc_sysfs_client, kobject);
341         kfree(c);
342 }
343
344 static void rpc_sysfs_xprt_switch_release(struct kobject *kobj)
345 {
346         struct rpc_sysfs_xprt_switch *xprt_switch;
347
348         xprt_switch = container_of(kobj, struct rpc_sysfs_xprt_switch, kobject);
349         kfree(xprt_switch);
350 }
351
352 static void rpc_sysfs_xprt_release(struct kobject *kobj)
353 {
354         struct rpc_sysfs_xprt *xprt;
355
356         xprt = container_of(kobj, struct rpc_sysfs_xprt, kobject);
357         kfree(xprt);
358 }
359
360 static const void *rpc_sysfs_client_namespace(struct kobject *kobj)
361 {
362         return container_of(kobj, struct rpc_sysfs_client, kobject)->net;
363 }
364
365 static const void *rpc_sysfs_xprt_switch_namespace(struct kobject *kobj)
366 {
367         return container_of(kobj, struct rpc_sysfs_xprt_switch, kobject)->net;
368 }
369
370 static const void *rpc_sysfs_xprt_namespace(struct kobject *kobj)
371 {
372         return container_of(kobj, struct rpc_sysfs_xprt,
373                             kobject)->xprt->xprt_net;
374 }
375
376 static struct kobj_attribute rpc_sysfs_xprt_dstaddr = __ATTR(dstaddr,
377         0644, rpc_sysfs_xprt_dstaddr_show, rpc_sysfs_xprt_dstaddr_store);
378
379 static struct kobj_attribute rpc_sysfs_xprt_info = __ATTR(xprt_info,
380         0444, rpc_sysfs_xprt_info_show, NULL);
381
382 static struct kobj_attribute rpc_sysfs_xprt_change_state = __ATTR(xprt_state,
383         0644, rpc_sysfs_xprt_state_show, rpc_sysfs_xprt_state_change);
384
385 static struct attribute *rpc_sysfs_xprt_attrs[] = {
386         &rpc_sysfs_xprt_dstaddr.attr,
387         &rpc_sysfs_xprt_info.attr,
388         &rpc_sysfs_xprt_change_state.attr,
389         NULL,
390 };
391
392 static struct kobj_attribute rpc_sysfs_xprt_switch_info =
393         __ATTR(xprt_switch_info, 0444, rpc_sysfs_xprt_switch_info_show, NULL);
394
395 static struct attribute *rpc_sysfs_xprt_switch_attrs[] = {
396         &rpc_sysfs_xprt_switch_info.attr,
397         NULL,
398 };
399
400 static struct kobj_type rpc_sysfs_client_type = {
401         .release = rpc_sysfs_client_release,
402         .sysfs_ops = &kobj_sysfs_ops,
403         .namespace = rpc_sysfs_client_namespace,
404 };
405
406 static struct kobj_type rpc_sysfs_xprt_switch_type = {
407         .release = rpc_sysfs_xprt_switch_release,
408         .default_attrs = rpc_sysfs_xprt_switch_attrs,
409         .sysfs_ops = &kobj_sysfs_ops,
410         .namespace = rpc_sysfs_xprt_switch_namespace,
411 };
412
413 static struct kobj_type rpc_sysfs_xprt_type = {
414         .release = rpc_sysfs_xprt_release,
415         .default_attrs = rpc_sysfs_xprt_attrs,
416         .sysfs_ops = &kobj_sysfs_ops,
417         .namespace = rpc_sysfs_xprt_namespace,
418 };
419
420 void rpc_sysfs_exit(void)
421 {
422         kobject_put(rpc_sunrpc_client_kobj);
423         kobject_put(rpc_sunrpc_xprt_switch_kobj);
424         kset_unregister(rpc_sunrpc_kset);
425 }
426
427 static struct rpc_sysfs_client *rpc_sysfs_client_alloc(struct kobject *parent,
428                                                        struct net *net,
429                                                        int clid)
430 {
431         struct rpc_sysfs_client *p;
432
433         p = kzalloc(sizeof(*p), GFP_KERNEL);
434         if (p) {
435                 p->net = net;
436                 p->kobject.kset = rpc_sunrpc_kset;
437                 if (kobject_init_and_add(&p->kobject, &rpc_sysfs_client_type,
438                                          parent, "clnt-%d", clid) == 0)
439                         return p;
440                 kobject_put(&p->kobject);
441         }
442         return NULL;
443 }
444
445 static struct rpc_sysfs_xprt_switch *
446 rpc_sysfs_xprt_switch_alloc(struct kobject *parent,
447                             struct rpc_xprt_switch *xprt_switch,
448                             struct net *net,
449                             gfp_t gfp_flags)
450 {
451         struct rpc_sysfs_xprt_switch *p;
452
453         p = kzalloc(sizeof(*p), gfp_flags);
454         if (p) {
455                 p->net = net;
456                 p->kobject.kset = rpc_sunrpc_kset;
457                 if (kobject_init_and_add(&p->kobject,
458                                          &rpc_sysfs_xprt_switch_type,
459                                          parent, "switch-%d",
460                                          xprt_switch->xps_id) == 0)
461                         return p;
462                 kobject_put(&p->kobject);
463         }
464         return NULL;
465 }
466
467 static struct rpc_sysfs_xprt *rpc_sysfs_xprt_alloc(struct kobject *parent,
468                                                    struct rpc_xprt *xprt,
469                                                    gfp_t gfp_flags)
470 {
471         struct rpc_sysfs_xprt *p;
472
473         p = kzalloc(sizeof(*p), gfp_flags);
474         if (!p)
475                 goto out;
476         p->kobject.kset = rpc_sunrpc_kset;
477         if (kobject_init_and_add(&p->kobject, &rpc_sysfs_xprt_type,
478                                  parent, "xprt-%d-%s", xprt->id,
479                                  xprt->address_strings[RPC_DISPLAY_PROTO]) == 0)
480                 return p;
481         kobject_put(&p->kobject);
482 out:
483         return NULL;
484 }
485
486 void rpc_sysfs_client_setup(struct rpc_clnt *clnt,
487                             struct rpc_xprt_switch *xprt_switch,
488                             struct net *net)
489 {
490         struct rpc_sysfs_client *rpc_client;
491
492         rpc_client = rpc_sysfs_client_alloc(rpc_sunrpc_client_kobj,
493                                             net, clnt->cl_clid);
494         if (rpc_client) {
495                 char name[] = "switch";
496                 struct rpc_sysfs_xprt_switch *xswitch =
497                         (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
498                 int ret;
499
500                 clnt->cl_sysfs = rpc_client;
501                 rpc_client->clnt = clnt;
502                 rpc_client->xprt_switch = xprt_switch;
503                 kobject_uevent(&rpc_client->kobject, KOBJ_ADD);
504                 ret = sysfs_create_link_nowarn(&rpc_client->kobject,
505                                                &xswitch->kobject, name);
506                 if (ret)
507                         pr_warn("can't create link to %s in sysfs (%d)\n",
508                                 name, ret);
509         }
510 }
511
512 void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch,
513                                  struct rpc_xprt *xprt,
514                                  gfp_t gfp_flags)
515 {
516         struct rpc_sysfs_xprt_switch *rpc_xprt_switch;
517         struct net *net;
518
519         if (xprt_switch->xps_net)
520                 net = xprt_switch->xps_net;
521         else
522                 net = xprt->xprt_net;
523         rpc_xprt_switch =
524                 rpc_sysfs_xprt_switch_alloc(rpc_sunrpc_xprt_switch_kobj,
525                                             xprt_switch, net, gfp_flags);
526         if (rpc_xprt_switch) {
527                 xprt_switch->xps_sysfs = rpc_xprt_switch;
528                 rpc_xprt_switch->xprt_switch = xprt_switch;
529                 rpc_xprt_switch->xprt = xprt;
530                 kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD);
531         }
532 }
533
534 void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch,
535                           struct rpc_xprt *xprt,
536                           gfp_t gfp_flags)
537 {
538         struct rpc_sysfs_xprt *rpc_xprt;
539         struct rpc_sysfs_xprt_switch *switch_obj =
540                 (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
541
542         rpc_xprt = rpc_sysfs_xprt_alloc(&switch_obj->kobject, xprt, gfp_flags);
543         if (rpc_xprt) {
544                 xprt->xprt_sysfs = rpc_xprt;
545                 rpc_xprt->xprt = xprt;
546                 rpc_xprt->xprt_switch = xprt_switch;
547                 kobject_uevent(&rpc_xprt->kobject, KOBJ_ADD);
548         }
549 }
550
551 void rpc_sysfs_client_destroy(struct rpc_clnt *clnt)
552 {
553         struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs;
554
555         if (rpc_client) {
556                 char name[] = "switch";
557
558                 sysfs_remove_link(&rpc_client->kobject, name);
559                 kobject_uevent(&rpc_client->kobject, KOBJ_REMOVE);
560                 kobject_del(&rpc_client->kobject);
561                 kobject_put(&rpc_client->kobject);
562                 clnt->cl_sysfs = NULL;
563         }
564 }
565
566 void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt_switch)
567 {
568         struct rpc_sysfs_xprt_switch *rpc_xprt_switch = xprt_switch->xps_sysfs;
569
570         if (rpc_xprt_switch) {
571                 kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_REMOVE);
572                 kobject_del(&rpc_xprt_switch->kobject);
573                 kobject_put(&rpc_xprt_switch->kobject);
574                 xprt_switch->xps_sysfs = NULL;
575         }
576 }
577
578 void rpc_sysfs_xprt_destroy(struct rpc_xprt *xprt)
579 {
580         struct rpc_sysfs_xprt *rpc_xprt = xprt->xprt_sysfs;
581
582         if (rpc_xprt) {
583                 kobject_uevent(&rpc_xprt->kobject, KOBJ_REMOVE);
584                 kobject_del(&rpc_xprt->kobject);
585                 kobject_put(&rpc_xprt->kobject);
586                 xprt->xprt_sysfs = NULL;
587         }
588 }