xref: /openbmc/linux/net/sunrpc/sysfs.c (revision 4a09651a)
174678748SOlga Kornievskaia // SPDX-License-Identifier: GPL-2.0
274678748SOlga Kornievskaia /*
374678748SOlga Kornievskaia  * Copyright (c) 2020 Anna Schumaker <Anna.Schumaker@Netapp.com>
474678748SOlga Kornievskaia  */
5c441f125SOlga Kornievskaia #include <linux/sunrpc/clnt.h>
674678748SOlga Kornievskaia #include <linux/kobject.h>
7587bc725SOlga Kornievskaia #include <linux/sunrpc/addr.h>
8587bc725SOlga Kornievskaia 
9c5a382ebSOlga Kornievskaia #include "sysfs.h"
1074678748SOlga Kornievskaia 
11587bc725SOlga Kornievskaia struct xprt_addr {
12587bc725SOlga Kornievskaia 	const char *addr;
13587bc725SOlga Kornievskaia 	struct rcu_head rcu;
14587bc725SOlga Kornievskaia };
15587bc725SOlga Kornievskaia 
16587bc725SOlga Kornievskaia static void free_xprt_addr(struct rcu_head *head)
17587bc725SOlga Kornievskaia {
18587bc725SOlga Kornievskaia 	struct xprt_addr *addr = container_of(head, struct xprt_addr, rcu);
19587bc725SOlga Kornievskaia 
20587bc725SOlga Kornievskaia 	kfree(addr->addr);
21587bc725SOlga Kornievskaia 	kfree(addr);
22587bc725SOlga Kornievskaia }
23587bc725SOlga Kornievskaia 
2474678748SOlga Kornievskaia static struct kset *rpc_sunrpc_kset;
25baea9944SOlga Kornievskaia static struct kobject *rpc_sunrpc_client_kobj, *rpc_sunrpc_xprt_switch_kobj;
26c441f125SOlga Kornievskaia 
27c441f125SOlga Kornievskaia static void rpc_sysfs_object_release(struct kobject *kobj)
28c441f125SOlga Kornievskaia {
29c441f125SOlga Kornievskaia 	kfree(kobj);
30c441f125SOlga Kornievskaia }
31c441f125SOlga Kornievskaia 
32c441f125SOlga Kornievskaia static const struct kobj_ns_type_operations *
33c441f125SOlga Kornievskaia rpc_sysfs_object_child_ns_type(struct kobject *kobj)
34c441f125SOlga Kornievskaia {
35c441f125SOlga Kornievskaia 	return &net_ns_type_operations;
36c441f125SOlga Kornievskaia }
37c441f125SOlga Kornievskaia 
38c441f125SOlga Kornievskaia static struct kobj_type rpc_sysfs_object_type = {
39c441f125SOlga Kornievskaia 	.release = rpc_sysfs_object_release,
40c441f125SOlga Kornievskaia 	.sysfs_ops = &kobj_sysfs_ops,
41c441f125SOlga Kornievskaia 	.child_ns_type = rpc_sysfs_object_child_ns_type,
42c441f125SOlga Kornievskaia };
43c441f125SOlga Kornievskaia 
44c441f125SOlga Kornievskaia static struct kobject *rpc_sysfs_object_alloc(const char *name,
45c441f125SOlga Kornievskaia 					      struct kset *kset,
46c441f125SOlga Kornievskaia 					      struct kobject *parent)
47c441f125SOlga Kornievskaia {
48c441f125SOlga Kornievskaia 	struct kobject *kobj;
49c441f125SOlga Kornievskaia 
50c441f125SOlga Kornievskaia 	kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
51c441f125SOlga Kornievskaia 	if (kobj) {
52c441f125SOlga Kornievskaia 		kobj->kset = kset;
53c441f125SOlga Kornievskaia 		if (kobject_init_and_add(kobj, &rpc_sysfs_object_type,
54c441f125SOlga Kornievskaia 					 parent, "%s", name) == 0)
55c441f125SOlga Kornievskaia 			return kobj;
56c441f125SOlga Kornievskaia 		kobject_put(kobj);
57c441f125SOlga Kornievskaia 	}
58c441f125SOlga Kornievskaia 	return NULL;
59c441f125SOlga Kornievskaia }
6074678748SOlga Kornievskaia 
61587bc725SOlga Kornievskaia static inline struct rpc_xprt *
62587bc725SOlga Kornievskaia rpc_sysfs_xprt_kobj_get_xprt(struct kobject *kobj)
63587bc725SOlga Kornievskaia {
64587bc725SOlga Kornievskaia 	struct rpc_sysfs_xprt *x = container_of(kobj,
65587bc725SOlga Kornievskaia 		struct rpc_sysfs_xprt, kobject);
66587bc725SOlga Kornievskaia 
67587bc725SOlga Kornievskaia 	return xprt_get(x->xprt);
68587bc725SOlga Kornievskaia }
69587bc725SOlga Kornievskaia 
70587bc725SOlga Kornievskaia static ssize_t rpc_sysfs_xprt_dstaddr_show(struct kobject *kobj,
71587bc725SOlga Kornievskaia 					   struct kobj_attribute *attr,
72587bc725SOlga Kornievskaia 					   char *buf)
73587bc725SOlga Kornievskaia {
74587bc725SOlga Kornievskaia 	struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
75587bc725SOlga Kornievskaia 	ssize_t ret;
76587bc725SOlga Kornievskaia 
77587bc725SOlga Kornievskaia 	if (!xprt)
78587bc725SOlga Kornievskaia 		return 0;
79587bc725SOlga Kornievskaia 	ret = sprintf(buf, "%s\n", xprt->address_strings[RPC_DISPLAY_ADDR]);
80587bc725SOlga Kornievskaia 	xprt_put(xprt);
81587bc725SOlga Kornievskaia 	return ret + 1;
82587bc725SOlga Kornievskaia }
83587bc725SOlga Kornievskaia 
84*4a09651aSOlga Kornievskaia static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj,
85*4a09651aSOlga Kornievskaia 					struct kobj_attribute *attr,
86*4a09651aSOlga Kornievskaia 					char *buf)
87*4a09651aSOlga Kornievskaia {
88*4a09651aSOlga Kornievskaia 	struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
89*4a09651aSOlga Kornievskaia 	ssize_t ret;
90*4a09651aSOlga Kornievskaia 
91*4a09651aSOlga Kornievskaia 	if (!xprt)
92*4a09651aSOlga Kornievskaia 		return 0;
93*4a09651aSOlga Kornievskaia 
94*4a09651aSOlga Kornievskaia 	ret = sprintf(buf, "last_used=%lu\ncur_cong=%lu\ncong_win=%lu\n"
95*4a09651aSOlga Kornievskaia 		       "max_num_slots=%u\nmin_num_slots=%u\nnum_reqs=%u\n"
96*4a09651aSOlga Kornievskaia 		       "binding_q_len=%u\nsending_q_len=%u\npending_q_len=%u\n"
97*4a09651aSOlga Kornievskaia 		       "backlog_q_len=%u\n", xprt->last_used, xprt->cong,
98*4a09651aSOlga Kornievskaia 		       xprt->cwnd, xprt->max_reqs, xprt->min_reqs,
99*4a09651aSOlga Kornievskaia 		       xprt->num_reqs, xprt->binding.qlen, xprt->sending.qlen,
100*4a09651aSOlga Kornievskaia 		       xprt->pending.qlen, xprt->backlog.qlen);
101*4a09651aSOlga Kornievskaia 	xprt_put(xprt);
102*4a09651aSOlga Kornievskaia 	return ret + 1;
103*4a09651aSOlga Kornievskaia }
104*4a09651aSOlga Kornievskaia 
105587bc725SOlga Kornievskaia static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj,
106587bc725SOlga Kornievskaia 					    struct kobj_attribute *attr,
107587bc725SOlga Kornievskaia 					    const char *buf, size_t count)
108587bc725SOlga Kornievskaia {
109587bc725SOlga Kornievskaia 	struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
110587bc725SOlga Kornievskaia 	struct sockaddr *saddr;
111587bc725SOlga Kornievskaia 	char *dst_addr;
112587bc725SOlga Kornievskaia 	int port;
113587bc725SOlga Kornievskaia 	struct xprt_addr *saved_addr;
114587bc725SOlga Kornievskaia 	size_t buf_len;
115587bc725SOlga Kornievskaia 
116587bc725SOlga Kornievskaia 	if (!xprt)
117587bc725SOlga Kornievskaia 		return 0;
118587bc725SOlga Kornievskaia 	if (!(xprt->xprt_class->ident == XPRT_TRANSPORT_TCP ||
119587bc725SOlga Kornievskaia 	      xprt->xprt_class->ident == XPRT_TRANSPORT_RDMA)) {
120587bc725SOlga Kornievskaia 		xprt_put(xprt);
121587bc725SOlga Kornievskaia 		return -EOPNOTSUPP;
122587bc725SOlga Kornievskaia 	}
123587bc725SOlga Kornievskaia 
124587bc725SOlga Kornievskaia 	if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
125587bc725SOlga Kornievskaia 		count = -EINTR;
126587bc725SOlga Kornievskaia 		goto out_put;
127587bc725SOlga Kornievskaia 	}
128587bc725SOlga Kornievskaia 	saddr = (struct sockaddr *)&xprt->addr;
129587bc725SOlga Kornievskaia 	port = rpc_get_port(saddr);
130587bc725SOlga Kornievskaia 
131587bc725SOlga Kornievskaia 	/* buf_len is the len until the first occurence of either
132587bc725SOlga Kornievskaia 	 * '\n' or '\0'
133587bc725SOlga Kornievskaia 	 */
134587bc725SOlga Kornievskaia 	buf_len = strcspn(buf, "\n");
135587bc725SOlga Kornievskaia 
136587bc725SOlga Kornievskaia 	dst_addr = kstrndup(buf, buf_len, GFP_KERNEL);
137587bc725SOlga Kornievskaia 	if (!dst_addr)
138587bc725SOlga Kornievskaia 		goto out_err;
139587bc725SOlga Kornievskaia 	saved_addr = kzalloc(sizeof(*saved_addr), GFP_KERNEL);
140587bc725SOlga Kornievskaia 	if (!saved_addr)
141587bc725SOlga Kornievskaia 		goto out_err_free;
142587bc725SOlga Kornievskaia 	saved_addr->addr =
143587bc725SOlga Kornievskaia 		rcu_dereference_raw(xprt->address_strings[RPC_DISPLAY_ADDR]);
144587bc725SOlga Kornievskaia 	rcu_assign_pointer(xprt->address_strings[RPC_DISPLAY_ADDR], dst_addr);
145587bc725SOlga Kornievskaia 	call_rcu(&saved_addr->rcu, free_xprt_addr);
146587bc725SOlga Kornievskaia 	xprt->addrlen = rpc_pton(xprt->xprt_net, buf, buf_len, saddr,
147587bc725SOlga Kornievskaia 				 sizeof(*saddr));
148587bc725SOlga Kornievskaia 	rpc_set_port(saddr, port);
149587bc725SOlga Kornievskaia 
150587bc725SOlga Kornievskaia 	xprt_force_disconnect(xprt);
151587bc725SOlga Kornievskaia out:
152587bc725SOlga Kornievskaia 	xprt_release_write(xprt, NULL);
153587bc725SOlga Kornievskaia out_put:
154587bc725SOlga Kornievskaia 	xprt_put(xprt);
155587bc725SOlga Kornievskaia 	return count;
156587bc725SOlga Kornievskaia out_err_free:
157587bc725SOlga Kornievskaia 	kfree(dst_addr);
158587bc725SOlga Kornievskaia out_err:
159587bc725SOlga Kornievskaia 	count = -ENOMEM;
160587bc725SOlga Kornievskaia 	goto out;
161587bc725SOlga Kornievskaia }
162587bc725SOlga Kornievskaia 
16374678748SOlga Kornievskaia int rpc_sysfs_init(void)
16474678748SOlga Kornievskaia {
16574678748SOlga Kornievskaia 	rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, kernel_kobj);
16674678748SOlga Kornievskaia 	if (!rpc_sunrpc_kset)
16774678748SOlga Kornievskaia 		return -ENOMEM;
168baea9944SOlga Kornievskaia 	rpc_sunrpc_client_kobj =
169baea9944SOlga Kornievskaia 		rpc_sysfs_object_alloc("rpc-clients", rpc_sunrpc_kset, NULL);
170baea9944SOlga Kornievskaia 	if (!rpc_sunrpc_client_kobj)
171baea9944SOlga Kornievskaia 		goto err_client;
172baea9944SOlga Kornievskaia 	rpc_sunrpc_xprt_switch_kobj =
173baea9944SOlga Kornievskaia 		rpc_sysfs_object_alloc("xprt-switches", rpc_sunrpc_kset, NULL);
174baea9944SOlga Kornievskaia 	if (!rpc_sunrpc_xprt_switch_kobj)
175baea9944SOlga Kornievskaia 		goto err_switch;
17674678748SOlga Kornievskaia 	return 0;
177baea9944SOlga Kornievskaia err_switch:
178baea9944SOlga Kornievskaia 	kobject_put(rpc_sunrpc_client_kobj);
179baea9944SOlga Kornievskaia 	rpc_sunrpc_client_kobj = NULL;
180baea9944SOlga Kornievskaia err_client:
181baea9944SOlga Kornievskaia 	kset_unregister(rpc_sunrpc_kset);
182baea9944SOlga Kornievskaia 	rpc_sunrpc_kset = NULL;
183baea9944SOlga Kornievskaia 	return -ENOMEM;
18474678748SOlga Kornievskaia }
18574678748SOlga Kornievskaia 
186c5a382ebSOlga Kornievskaia static void rpc_sysfs_client_release(struct kobject *kobj)
187c5a382ebSOlga Kornievskaia {
188c5a382ebSOlga Kornievskaia 	struct rpc_sysfs_client *c;
189c5a382ebSOlga Kornievskaia 
190c5a382ebSOlga Kornievskaia 	c = container_of(kobj, struct rpc_sysfs_client, kobject);
191c5a382ebSOlga Kornievskaia 	kfree(c);
192c5a382ebSOlga Kornievskaia }
193c5a382ebSOlga Kornievskaia 
194baea9944SOlga Kornievskaia static void rpc_sysfs_xprt_switch_release(struct kobject *kobj)
195baea9944SOlga Kornievskaia {
196baea9944SOlga Kornievskaia 	struct rpc_sysfs_xprt_switch *xprt_switch;
197baea9944SOlga Kornievskaia 
198baea9944SOlga Kornievskaia 	xprt_switch = container_of(kobj, struct rpc_sysfs_xprt_switch, kobject);
199baea9944SOlga Kornievskaia 	kfree(xprt_switch);
200baea9944SOlga Kornievskaia }
201baea9944SOlga Kornievskaia 
202d408ebe0SOlga Kornievskaia static void rpc_sysfs_xprt_release(struct kobject *kobj)
203d408ebe0SOlga Kornievskaia {
204d408ebe0SOlga Kornievskaia 	struct rpc_sysfs_xprt *xprt;
205d408ebe0SOlga Kornievskaia 
206d408ebe0SOlga Kornievskaia 	xprt = container_of(kobj, struct rpc_sysfs_xprt, kobject);
207d408ebe0SOlga Kornievskaia 	kfree(xprt);
208d408ebe0SOlga Kornievskaia }
209d408ebe0SOlga Kornievskaia 
210c5a382ebSOlga Kornievskaia static const void *rpc_sysfs_client_namespace(struct kobject *kobj)
211c5a382ebSOlga Kornievskaia {
212c5a382ebSOlga Kornievskaia 	return container_of(kobj, struct rpc_sysfs_client, kobject)->net;
213c5a382ebSOlga Kornievskaia }
214c5a382ebSOlga Kornievskaia 
215baea9944SOlga Kornievskaia static const void *rpc_sysfs_xprt_switch_namespace(struct kobject *kobj)
216baea9944SOlga Kornievskaia {
217baea9944SOlga Kornievskaia 	return container_of(kobj, struct rpc_sysfs_xprt_switch, kobject)->net;
218baea9944SOlga Kornievskaia }
219baea9944SOlga Kornievskaia 
220d408ebe0SOlga Kornievskaia static const void *rpc_sysfs_xprt_namespace(struct kobject *kobj)
221d408ebe0SOlga Kornievskaia {
222d408ebe0SOlga Kornievskaia 	return container_of(kobj, struct rpc_sysfs_xprt,
223d408ebe0SOlga Kornievskaia 			    kobject)->xprt->xprt_net;
224d408ebe0SOlga Kornievskaia }
225d408ebe0SOlga Kornievskaia 
226587bc725SOlga Kornievskaia static struct kobj_attribute rpc_sysfs_xprt_dstaddr = __ATTR(dstaddr,
227587bc725SOlga Kornievskaia 	0644, rpc_sysfs_xprt_dstaddr_show, rpc_sysfs_xprt_dstaddr_store);
228587bc725SOlga Kornievskaia 
229*4a09651aSOlga Kornievskaia static struct kobj_attribute rpc_sysfs_xprt_info = __ATTR(xprt_info,
230*4a09651aSOlga Kornievskaia 	0444, rpc_sysfs_xprt_info_show, NULL);
231*4a09651aSOlga Kornievskaia 
232587bc725SOlga Kornievskaia static struct attribute *rpc_sysfs_xprt_attrs[] = {
233587bc725SOlga Kornievskaia 	&rpc_sysfs_xprt_dstaddr.attr,
234*4a09651aSOlga Kornievskaia 	&rpc_sysfs_xprt_info.attr,
235587bc725SOlga Kornievskaia 	NULL,
236587bc725SOlga Kornievskaia };
237587bc725SOlga Kornievskaia 
238c5a382ebSOlga Kornievskaia static struct kobj_type rpc_sysfs_client_type = {
239c5a382ebSOlga Kornievskaia 	.release = rpc_sysfs_client_release,
240c5a382ebSOlga Kornievskaia 	.sysfs_ops = &kobj_sysfs_ops,
241c5a382ebSOlga Kornievskaia 	.namespace = rpc_sysfs_client_namespace,
242c5a382ebSOlga Kornievskaia };
243c5a382ebSOlga Kornievskaia 
244baea9944SOlga Kornievskaia static struct kobj_type rpc_sysfs_xprt_switch_type = {
245baea9944SOlga Kornievskaia 	.release = rpc_sysfs_xprt_switch_release,
246baea9944SOlga Kornievskaia 	.sysfs_ops = &kobj_sysfs_ops,
247baea9944SOlga Kornievskaia 	.namespace = rpc_sysfs_xprt_switch_namespace,
248baea9944SOlga Kornievskaia };
249baea9944SOlga Kornievskaia 
250d408ebe0SOlga Kornievskaia static struct kobj_type rpc_sysfs_xprt_type = {
251d408ebe0SOlga Kornievskaia 	.release = rpc_sysfs_xprt_release,
252587bc725SOlga Kornievskaia 	.default_attrs = rpc_sysfs_xprt_attrs,
253d408ebe0SOlga Kornievskaia 	.sysfs_ops = &kobj_sysfs_ops,
254d408ebe0SOlga Kornievskaia 	.namespace = rpc_sysfs_xprt_namespace,
255d408ebe0SOlga Kornievskaia };
256d408ebe0SOlga Kornievskaia 
25774678748SOlga Kornievskaia void rpc_sysfs_exit(void)
25874678748SOlga Kornievskaia {
259c441f125SOlga Kornievskaia 	kobject_put(rpc_sunrpc_client_kobj);
260baea9944SOlga Kornievskaia 	kobject_put(rpc_sunrpc_xprt_switch_kobj);
26174678748SOlga Kornievskaia 	kset_unregister(rpc_sunrpc_kset);
26274678748SOlga Kornievskaia }
263c5a382ebSOlga Kornievskaia 
264c5a382ebSOlga Kornievskaia static struct rpc_sysfs_client *rpc_sysfs_client_alloc(struct kobject *parent,
265c5a382ebSOlga Kornievskaia 						       struct net *net,
266c5a382ebSOlga Kornievskaia 						       int clid)
267c5a382ebSOlga Kornievskaia {
268c5a382ebSOlga Kornievskaia 	struct rpc_sysfs_client *p;
269c5a382ebSOlga Kornievskaia 
270c5a382ebSOlga Kornievskaia 	p = kzalloc(sizeof(*p), GFP_KERNEL);
271c5a382ebSOlga Kornievskaia 	if (p) {
272c5a382ebSOlga Kornievskaia 		p->net = net;
273c5a382ebSOlga Kornievskaia 		p->kobject.kset = rpc_sunrpc_kset;
274c5a382ebSOlga Kornievskaia 		if (kobject_init_and_add(&p->kobject, &rpc_sysfs_client_type,
275c5a382ebSOlga Kornievskaia 					 parent, "clnt-%d", clid) == 0)
276c5a382ebSOlga Kornievskaia 			return p;
277c5a382ebSOlga Kornievskaia 		kobject_put(&p->kobject);
278c5a382ebSOlga Kornievskaia 	}
279c5a382ebSOlga Kornievskaia 	return NULL;
280c5a382ebSOlga Kornievskaia }
281c5a382ebSOlga Kornievskaia 
282baea9944SOlga Kornievskaia static struct rpc_sysfs_xprt_switch *
283baea9944SOlga Kornievskaia rpc_sysfs_xprt_switch_alloc(struct kobject *parent,
284baea9944SOlga Kornievskaia 			    struct rpc_xprt_switch *xprt_switch,
285baea9944SOlga Kornievskaia 			    struct net *net,
286baea9944SOlga Kornievskaia 			    gfp_t gfp_flags)
287baea9944SOlga Kornievskaia {
288baea9944SOlga Kornievskaia 	struct rpc_sysfs_xprt_switch *p;
289baea9944SOlga Kornievskaia 
290baea9944SOlga Kornievskaia 	p = kzalloc(sizeof(*p), gfp_flags);
291baea9944SOlga Kornievskaia 	if (p) {
292baea9944SOlga Kornievskaia 		p->net = net;
293baea9944SOlga Kornievskaia 		p->kobject.kset = rpc_sunrpc_kset;
294baea9944SOlga Kornievskaia 		if (kobject_init_and_add(&p->kobject,
295baea9944SOlga Kornievskaia 					 &rpc_sysfs_xprt_switch_type,
296baea9944SOlga Kornievskaia 					 parent, "switch-%d",
297baea9944SOlga Kornievskaia 					 xprt_switch->xps_id) == 0)
298baea9944SOlga Kornievskaia 			return p;
299baea9944SOlga Kornievskaia 		kobject_put(&p->kobject);
300baea9944SOlga Kornievskaia 	}
301baea9944SOlga Kornievskaia 	return NULL;
302baea9944SOlga Kornievskaia }
303baea9944SOlga Kornievskaia 
304d408ebe0SOlga Kornievskaia static struct rpc_sysfs_xprt *rpc_sysfs_xprt_alloc(struct kobject *parent,
305d408ebe0SOlga Kornievskaia 						   struct rpc_xprt *xprt,
306d408ebe0SOlga Kornievskaia 						   gfp_t gfp_flags)
307d408ebe0SOlga Kornievskaia {
308d408ebe0SOlga Kornievskaia 	struct rpc_sysfs_xprt *p;
309d408ebe0SOlga Kornievskaia 
310d408ebe0SOlga Kornievskaia 	p = kzalloc(sizeof(*p), gfp_flags);
311d408ebe0SOlga Kornievskaia 	if (!p)
312d408ebe0SOlga Kornievskaia 		goto out;
313d408ebe0SOlga Kornievskaia 	p->kobject.kset = rpc_sunrpc_kset;
314d408ebe0SOlga Kornievskaia 	if (kobject_init_and_add(&p->kobject, &rpc_sysfs_xprt_type,
315d408ebe0SOlga Kornievskaia 				 parent, "xprt-%d-%s", xprt->id,
316d408ebe0SOlga Kornievskaia 				 xprt->address_strings[RPC_DISPLAY_PROTO]) == 0)
317d408ebe0SOlga Kornievskaia 		return p;
318d408ebe0SOlga Kornievskaia 	kobject_put(&p->kobject);
319d408ebe0SOlga Kornievskaia out:
320d408ebe0SOlga Kornievskaia 	return NULL;
321d408ebe0SOlga Kornievskaia }
322d408ebe0SOlga Kornievskaia 
3232a338a54SOlga Kornievskaia void rpc_sysfs_client_setup(struct rpc_clnt *clnt,
3242a338a54SOlga Kornievskaia 			    struct rpc_xprt_switch *xprt_switch,
3252a338a54SOlga Kornievskaia 			    struct net *net)
326c5a382ebSOlga Kornievskaia {
327c5a382ebSOlga Kornievskaia 	struct rpc_sysfs_client *rpc_client;
328c5a382ebSOlga Kornievskaia 
3292a338a54SOlga Kornievskaia 	rpc_client = rpc_sysfs_client_alloc(rpc_sunrpc_client_kobj,
3302a338a54SOlga Kornievskaia 					    net, clnt->cl_clid);
331c5a382ebSOlga Kornievskaia 	if (rpc_client) {
3322a338a54SOlga Kornievskaia 		char name[] = "switch";
3332a338a54SOlga Kornievskaia 		struct rpc_sysfs_xprt_switch *xswitch =
3342a338a54SOlga Kornievskaia 			(struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
3352a338a54SOlga Kornievskaia 		int ret;
3362a338a54SOlga Kornievskaia 
337c5a382ebSOlga Kornievskaia 		clnt->cl_sysfs = rpc_client;
3382a338a54SOlga Kornievskaia 		rpc_client->clnt = clnt;
3392a338a54SOlga Kornievskaia 		rpc_client->xprt_switch = xprt_switch;
340c5a382ebSOlga Kornievskaia 		kobject_uevent(&rpc_client->kobject, KOBJ_ADD);
3412a338a54SOlga Kornievskaia 		ret = sysfs_create_link_nowarn(&rpc_client->kobject,
3422a338a54SOlga Kornievskaia 					       &xswitch->kobject, name);
3432a338a54SOlga Kornievskaia 		if (ret)
3442a338a54SOlga Kornievskaia 			pr_warn("can't create link to %s in sysfs (%d)\n",
3452a338a54SOlga Kornievskaia 				name, ret);
346c5a382ebSOlga Kornievskaia 	}
347c5a382ebSOlga Kornievskaia }
348c5a382ebSOlga Kornievskaia 
349baea9944SOlga Kornievskaia void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch,
350baea9944SOlga Kornievskaia 				 struct rpc_xprt *xprt,
351baea9944SOlga Kornievskaia 				 gfp_t gfp_flags)
352baea9944SOlga Kornievskaia {
353baea9944SOlga Kornievskaia 	struct rpc_sysfs_xprt_switch *rpc_xprt_switch;
354baea9944SOlga Kornievskaia 	struct net *net;
355baea9944SOlga Kornievskaia 
356baea9944SOlga Kornievskaia 	if (xprt_switch->xps_net)
357baea9944SOlga Kornievskaia 		net = xprt_switch->xps_net;
358baea9944SOlga Kornievskaia 	else
359baea9944SOlga Kornievskaia 		net = xprt->xprt_net;
360baea9944SOlga Kornievskaia 	rpc_xprt_switch =
361baea9944SOlga Kornievskaia 		rpc_sysfs_xprt_switch_alloc(rpc_sunrpc_xprt_switch_kobj,
362baea9944SOlga Kornievskaia 					    xprt_switch, net, gfp_flags);
363baea9944SOlga Kornievskaia 	if (rpc_xprt_switch) {
364baea9944SOlga Kornievskaia 		xprt_switch->xps_sysfs = rpc_xprt_switch;
365baea9944SOlga Kornievskaia 		rpc_xprt_switch->xprt_switch = xprt_switch;
366baea9944SOlga Kornievskaia 		rpc_xprt_switch->xprt = xprt;
367baea9944SOlga Kornievskaia 		kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD);
368baea9944SOlga Kornievskaia 	}
369baea9944SOlga Kornievskaia }
370baea9944SOlga Kornievskaia 
371d408ebe0SOlga Kornievskaia void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch,
372d408ebe0SOlga Kornievskaia 			  struct rpc_xprt *xprt,
373d408ebe0SOlga Kornievskaia 			  gfp_t gfp_flags)
374d408ebe0SOlga Kornievskaia {
375d408ebe0SOlga Kornievskaia 	struct rpc_sysfs_xprt *rpc_xprt;
376d408ebe0SOlga Kornievskaia 	struct rpc_sysfs_xprt_switch *switch_obj =
377d408ebe0SOlga Kornievskaia 		(struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
378d408ebe0SOlga Kornievskaia 
379d408ebe0SOlga Kornievskaia 	rpc_xprt = rpc_sysfs_xprt_alloc(&switch_obj->kobject, xprt, gfp_flags);
380d408ebe0SOlga Kornievskaia 	if (rpc_xprt) {
381d408ebe0SOlga Kornievskaia 		xprt->xprt_sysfs = rpc_xprt;
382d408ebe0SOlga Kornievskaia 		rpc_xprt->xprt = xprt;
383d408ebe0SOlga Kornievskaia 		kobject_uevent(&rpc_xprt->kobject, KOBJ_ADD);
384d408ebe0SOlga Kornievskaia 	}
385d408ebe0SOlga Kornievskaia }
386d408ebe0SOlga Kornievskaia 
387c5a382ebSOlga Kornievskaia void rpc_sysfs_client_destroy(struct rpc_clnt *clnt)
388c5a382ebSOlga Kornievskaia {
389c5a382ebSOlga Kornievskaia 	struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs;
390c5a382ebSOlga Kornievskaia 
391c5a382ebSOlga Kornievskaia 	if (rpc_client) {
3922a338a54SOlga Kornievskaia 		char name[] = "switch";
3932a338a54SOlga Kornievskaia 
3942a338a54SOlga Kornievskaia 		sysfs_remove_link(&rpc_client->kobject, name);
395c5a382ebSOlga Kornievskaia 		kobject_uevent(&rpc_client->kobject, KOBJ_REMOVE);
396c5a382ebSOlga Kornievskaia 		kobject_del(&rpc_client->kobject);
397c5a382ebSOlga Kornievskaia 		kobject_put(&rpc_client->kobject);
398c5a382ebSOlga Kornievskaia 		clnt->cl_sysfs = NULL;
399c5a382ebSOlga Kornievskaia 	}
400c5a382ebSOlga Kornievskaia }
401baea9944SOlga Kornievskaia 
402baea9944SOlga Kornievskaia void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt_switch)
403baea9944SOlga Kornievskaia {
404baea9944SOlga Kornievskaia 	struct rpc_sysfs_xprt_switch *rpc_xprt_switch = xprt_switch->xps_sysfs;
405baea9944SOlga Kornievskaia 
406baea9944SOlga Kornievskaia 	if (rpc_xprt_switch) {
407baea9944SOlga Kornievskaia 		kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_REMOVE);
408baea9944SOlga Kornievskaia 		kobject_del(&rpc_xprt_switch->kobject);
409baea9944SOlga Kornievskaia 		kobject_put(&rpc_xprt_switch->kobject);
410baea9944SOlga Kornievskaia 		xprt_switch->xps_sysfs = NULL;
411baea9944SOlga Kornievskaia 	}
412baea9944SOlga Kornievskaia }
413d408ebe0SOlga Kornievskaia 
414d408ebe0SOlga Kornievskaia void rpc_sysfs_xprt_destroy(struct rpc_xprt *xprt)
415d408ebe0SOlga Kornievskaia {
416d408ebe0SOlga Kornievskaia 	struct rpc_sysfs_xprt *rpc_xprt = xprt->xprt_sysfs;
417d408ebe0SOlga Kornievskaia 
418d408ebe0SOlga Kornievskaia 	if (rpc_xprt) {
419d408ebe0SOlga Kornievskaia 		kobject_uevent(&rpc_xprt->kobject, KOBJ_REMOVE);
420d408ebe0SOlga Kornievskaia 		kobject_del(&rpc_xprt->kobject);
421d408ebe0SOlga Kornievskaia 		kobject_put(&rpc_xprt->kobject);
422d408ebe0SOlga Kornievskaia 		xprt->xprt_sysfs = NULL;
423d408ebe0SOlga Kornievskaia 	}
424d408ebe0SOlga Kornievskaia }
425