xref: /linux/net/sunrpc/sysfs.c (revision 4c2226be8161a12f0a68e81d25cf8ed05fa622e0)
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(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 
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 *
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 *
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 *
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 *
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 *
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 
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 
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 
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 
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 
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 
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 
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