xref: /openbmc/linux/net/sunrpc/sysfs.c (revision 587bc725)
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>
7*587bc725SOlga Kornievskaia #include <linux/sunrpc/addr.h>
8*587bc725SOlga Kornievskaia 
9c5a382ebSOlga Kornievskaia #include "sysfs.h"
1074678748SOlga Kornievskaia 
11*587bc725SOlga Kornievskaia struct xprt_addr {
12*587bc725SOlga Kornievskaia 	const char *addr;
13*587bc725SOlga Kornievskaia 	struct rcu_head rcu;
14*587bc725SOlga Kornievskaia };
15*587bc725SOlga Kornievskaia 
16*587bc725SOlga Kornievskaia static void free_xprt_addr(struct rcu_head *head)
17*587bc725SOlga Kornievskaia {
18*587bc725SOlga Kornievskaia 	struct xprt_addr *addr = container_of(head, struct xprt_addr, rcu);
19*587bc725SOlga Kornievskaia 
20*587bc725SOlga Kornievskaia 	kfree(addr->addr);
21*587bc725SOlga Kornievskaia 	kfree(addr);
22*587bc725SOlga Kornievskaia }
23*587bc725SOlga 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 
61*587bc725SOlga Kornievskaia static inline struct rpc_xprt *
62*587bc725SOlga Kornievskaia rpc_sysfs_xprt_kobj_get_xprt(struct kobject *kobj)
63*587bc725SOlga Kornievskaia {
64*587bc725SOlga Kornievskaia 	struct rpc_sysfs_xprt *x = container_of(kobj,
65*587bc725SOlga Kornievskaia 		struct rpc_sysfs_xprt, kobject);
66*587bc725SOlga Kornievskaia 
67*587bc725SOlga Kornievskaia 	return xprt_get(x->xprt);
68*587bc725SOlga Kornievskaia }
69*587bc725SOlga Kornievskaia 
70*587bc725SOlga Kornievskaia static ssize_t rpc_sysfs_xprt_dstaddr_show(struct kobject *kobj,
71*587bc725SOlga Kornievskaia 					   struct kobj_attribute *attr,
72*587bc725SOlga Kornievskaia 					   char *buf)
73*587bc725SOlga Kornievskaia {
74*587bc725SOlga Kornievskaia 	struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
75*587bc725SOlga Kornievskaia 	ssize_t ret;
76*587bc725SOlga Kornievskaia 
77*587bc725SOlga Kornievskaia 	if (!xprt)
78*587bc725SOlga Kornievskaia 		return 0;
79*587bc725SOlga Kornievskaia 	ret = sprintf(buf, "%s\n", xprt->address_strings[RPC_DISPLAY_ADDR]);
80*587bc725SOlga Kornievskaia 	xprt_put(xprt);
81*587bc725SOlga Kornievskaia 	return ret + 1;
82*587bc725SOlga Kornievskaia }
83*587bc725SOlga Kornievskaia 
84*587bc725SOlga Kornievskaia static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj,
85*587bc725SOlga Kornievskaia 					    struct kobj_attribute *attr,
86*587bc725SOlga Kornievskaia 					    const char *buf, size_t count)
87*587bc725SOlga Kornievskaia {
88*587bc725SOlga Kornievskaia 	struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
89*587bc725SOlga Kornievskaia 	struct sockaddr *saddr;
90*587bc725SOlga Kornievskaia 	char *dst_addr;
91*587bc725SOlga Kornievskaia 	int port;
92*587bc725SOlga Kornievskaia 	struct xprt_addr *saved_addr;
93*587bc725SOlga Kornievskaia 	size_t buf_len;
94*587bc725SOlga Kornievskaia 
95*587bc725SOlga Kornievskaia 	if (!xprt)
96*587bc725SOlga Kornievskaia 		return 0;
97*587bc725SOlga Kornievskaia 	if (!(xprt->xprt_class->ident == XPRT_TRANSPORT_TCP ||
98*587bc725SOlga Kornievskaia 	      xprt->xprt_class->ident == XPRT_TRANSPORT_RDMA)) {
99*587bc725SOlga Kornievskaia 		xprt_put(xprt);
100*587bc725SOlga Kornievskaia 		return -EOPNOTSUPP;
101*587bc725SOlga Kornievskaia 	}
102*587bc725SOlga Kornievskaia 
103*587bc725SOlga Kornievskaia 	if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
104*587bc725SOlga Kornievskaia 		count = -EINTR;
105*587bc725SOlga Kornievskaia 		goto out_put;
106*587bc725SOlga Kornievskaia 	}
107*587bc725SOlga Kornievskaia 	saddr = (struct sockaddr *)&xprt->addr;
108*587bc725SOlga Kornievskaia 	port = rpc_get_port(saddr);
109*587bc725SOlga Kornievskaia 
110*587bc725SOlga Kornievskaia 	/* buf_len is the len until the first occurence of either
111*587bc725SOlga Kornievskaia 	 * '\n' or '\0'
112*587bc725SOlga Kornievskaia 	 */
113*587bc725SOlga Kornievskaia 	buf_len = strcspn(buf, "\n");
114*587bc725SOlga Kornievskaia 
115*587bc725SOlga Kornievskaia 	dst_addr = kstrndup(buf, buf_len, GFP_KERNEL);
116*587bc725SOlga Kornievskaia 	if (!dst_addr)
117*587bc725SOlga Kornievskaia 		goto out_err;
118*587bc725SOlga Kornievskaia 	saved_addr = kzalloc(sizeof(*saved_addr), GFP_KERNEL);
119*587bc725SOlga Kornievskaia 	if (!saved_addr)
120*587bc725SOlga Kornievskaia 		goto out_err_free;
121*587bc725SOlga Kornievskaia 	saved_addr->addr =
122*587bc725SOlga Kornievskaia 		rcu_dereference_raw(xprt->address_strings[RPC_DISPLAY_ADDR]);
123*587bc725SOlga Kornievskaia 	rcu_assign_pointer(xprt->address_strings[RPC_DISPLAY_ADDR], dst_addr);
124*587bc725SOlga Kornievskaia 	call_rcu(&saved_addr->rcu, free_xprt_addr);
125*587bc725SOlga Kornievskaia 	xprt->addrlen = rpc_pton(xprt->xprt_net, buf, buf_len, saddr,
126*587bc725SOlga Kornievskaia 				 sizeof(*saddr));
127*587bc725SOlga Kornievskaia 	rpc_set_port(saddr, port);
128*587bc725SOlga Kornievskaia 
129*587bc725SOlga Kornievskaia 	xprt_force_disconnect(xprt);
130*587bc725SOlga Kornievskaia out:
131*587bc725SOlga Kornievskaia 	xprt_release_write(xprt, NULL);
132*587bc725SOlga Kornievskaia out_put:
133*587bc725SOlga Kornievskaia 	xprt_put(xprt);
134*587bc725SOlga Kornievskaia 	return count;
135*587bc725SOlga Kornievskaia out_err_free:
136*587bc725SOlga Kornievskaia 	kfree(dst_addr);
137*587bc725SOlga Kornievskaia out_err:
138*587bc725SOlga Kornievskaia 	count = -ENOMEM;
139*587bc725SOlga Kornievskaia 	goto out;
140*587bc725SOlga Kornievskaia }
141*587bc725SOlga Kornievskaia 
14274678748SOlga Kornievskaia int rpc_sysfs_init(void)
14374678748SOlga Kornievskaia {
14474678748SOlga Kornievskaia 	rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, kernel_kobj);
14574678748SOlga Kornievskaia 	if (!rpc_sunrpc_kset)
14674678748SOlga Kornievskaia 		return -ENOMEM;
147baea9944SOlga Kornievskaia 	rpc_sunrpc_client_kobj =
148baea9944SOlga Kornievskaia 		rpc_sysfs_object_alloc("rpc-clients", rpc_sunrpc_kset, NULL);
149baea9944SOlga Kornievskaia 	if (!rpc_sunrpc_client_kobj)
150baea9944SOlga Kornievskaia 		goto err_client;
151baea9944SOlga Kornievskaia 	rpc_sunrpc_xprt_switch_kobj =
152baea9944SOlga Kornievskaia 		rpc_sysfs_object_alloc("xprt-switches", rpc_sunrpc_kset, NULL);
153baea9944SOlga Kornievskaia 	if (!rpc_sunrpc_xprt_switch_kobj)
154baea9944SOlga Kornievskaia 		goto err_switch;
15574678748SOlga Kornievskaia 	return 0;
156baea9944SOlga Kornievskaia err_switch:
157baea9944SOlga Kornievskaia 	kobject_put(rpc_sunrpc_client_kobj);
158baea9944SOlga Kornievskaia 	rpc_sunrpc_client_kobj = NULL;
159baea9944SOlga Kornievskaia err_client:
160baea9944SOlga Kornievskaia 	kset_unregister(rpc_sunrpc_kset);
161baea9944SOlga Kornievskaia 	rpc_sunrpc_kset = NULL;
162baea9944SOlga Kornievskaia 	return -ENOMEM;
16374678748SOlga Kornievskaia }
16474678748SOlga Kornievskaia 
165c5a382ebSOlga Kornievskaia static void rpc_sysfs_client_release(struct kobject *kobj)
166c5a382ebSOlga Kornievskaia {
167c5a382ebSOlga Kornievskaia 	struct rpc_sysfs_client *c;
168c5a382ebSOlga Kornievskaia 
169c5a382ebSOlga Kornievskaia 	c = container_of(kobj, struct rpc_sysfs_client, kobject);
170c5a382ebSOlga Kornievskaia 	kfree(c);
171c5a382ebSOlga Kornievskaia }
172c5a382ebSOlga Kornievskaia 
173baea9944SOlga Kornievskaia static void rpc_sysfs_xprt_switch_release(struct kobject *kobj)
174baea9944SOlga Kornievskaia {
175baea9944SOlga Kornievskaia 	struct rpc_sysfs_xprt_switch *xprt_switch;
176baea9944SOlga Kornievskaia 
177baea9944SOlga Kornievskaia 	xprt_switch = container_of(kobj, struct rpc_sysfs_xprt_switch, kobject);
178baea9944SOlga Kornievskaia 	kfree(xprt_switch);
179baea9944SOlga Kornievskaia }
180baea9944SOlga Kornievskaia 
181d408ebe0SOlga Kornievskaia static void rpc_sysfs_xprt_release(struct kobject *kobj)
182d408ebe0SOlga Kornievskaia {
183d408ebe0SOlga Kornievskaia 	struct rpc_sysfs_xprt *xprt;
184d408ebe0SOlga Kornievskaia 
185d408ebe0SOlga Kornievskaia 	xprt = container_of(kobj, struct rpc_sysfs_xprt, kobject);
186d408ebe0SOlga Kornievskaia 	kfree(xprt);
187d408ebe0SOlga Kornievskaia }
188d408ebe0SOlga Kornievskaia 
189c5a382ebSOlga Kornievskaia static const void *rpc_sysfs_client_namespace(struct kobject *kobj)
190c5a382ebSOlga Kornievskaia {
191c5a382ebSOlga Kornievskaia 	return container_of(kobj, struct rpc_sysfs_client, kobject)->net;
192c5a382ebSOlga Kornievskaia }
193c5a382ebSOlga Kornievskaia 
194baea9944SOlga Kornievskaia static const void *rpc_sysfs_xprt_switch_namespace(struct kobject *kobj)
195baea9944SOlga Kornievskaia {
196baea9944SOlga Kornievskaia 	return container_of(kobj, struct rpc_sysfs_xprt_switch, kobject)->net;
197baea9944SOlga Kornievskaia }
198baea9944SOlga Kornievskaia 
199d408ebe0SOlga Kornievskaia static const void *rpc_sysfs_xprt_namespace(struct kobject *kobj)
200d408ebe0SOlga Kornievskaia {
201d408ebe0SOlga Kornievskaia 	return container_of(kobj, struct rpc_sysfs_xprt,
202d408ebe0SOlga Kornievskaia 			    kobject)->xprt->xprt_net;
203d408ebe0SOlga Kornievskaia }
204d408ebe0SOlga Kornievskaia 
205*587bc725SOlga Kornievskaia static struct kobj_attribute rpc_sysfs_xprt_dstaddr = __ATTR(dstaddr,
206*587bc725SOlga Kornievskaia 	0644, rpc_sysfs_xprt_dstaddr_show, rpc_sysfs_xprt_dstaddr_store);
207*587bc725SOlga Kornievskaia 
208*587bc725SOlga Kornievskaia static struct attribute *rpc_sysfs_xprt_attrs[] = {
209*587bc725SOlga Kornievskaia 	&rpc_sysfs_xprt_dstaddr.attr,
210*587bc725SOlga Kornievskaia 	NULL,
211*587bc725SOlga Kornievskaia };
212*587bc725SOlga Kornievskaia 
213c5a382ebSOlga Kornievskaia static struct kobj_type rpc_sysfs_client_type = {
214c5a382ebSOlga Kornievskaia 	.release = rpc_sysfs_client_release,
215c5a382ebSOlga Kornievskaia 	.sysfs_ops = &kobj_sysfs_ops,
216c5a382ebSOlga Kornievskaia 	.namespace = rpc_sysfs_client_namespace,
217c5a382ebSOlga Kornievskaia };
218c5a382ebSOlga Kornievskaia 
219baea9944SOlga Kornievskaia static struct kobj_type rpc_sysfs_xprt_switch_type = {
220baea9944SOlga Kornievskaia 	.release = rpc_sysfs_xprt_switch_release,
221baea9944SOlga Kornievskaia 	.sysfs_ops = &kobj_sysfs_ops,
222baea9944SOlga Kornievskaia 	.namespace = rpc_sysfs_xprt_switch_namespace,
223baea9944SOlga Kornievskaia };
224baea9944SOlga Kornievskaia 
225d408ebe0SOlga Kornievskaia static struct kobj_type rpc_sysfs_xprt_type = {
226d408ebe0SOlga Kornievskaia 	.release = rpc_sysfs_xprt_release,
227*587bc725SOlga Kornievskaia 	.default_attrs = rpc_sysfs_xprt_attrs,
228d408ebe0SOlga Kornievskaia 	.sysfs_ops = &kobj_sysfs_ops,
229d408ebe0SOlga Kornievskaia 	.namespace = rpc_sysfs_xprt_namespace,
230d408ebe0SOlga Kornievskaia };
231d408ebe0SOlga Kornievskaia 
23274678748SOlga Kornievskaia void rpc_sysfs_exit(void)
23374678748SOlga Kornievskaia {
234c441f125SOlga Kornievskaia 	kobject_put(rpc_sunrpc_client_kobj);
235baea9944SOlga Kornievskaia 	kobject_put(rpc_sunrpc_xprt_switch_kobj);
23674678748SOlga Kornievskaia 	kset_unregister(rpc_sunrpc_kset);
23774678748SOlga Kornievskaia }
238c5a382ebSOlga Kornievskaia 
239c5a382ebSOlga Kornievskaia static struct rpc_sysfs_client *rpc_sysfs_client_alloc(struct kobject *parent,
240c5a382ebSOlga Kornievskaia 						       struct net *net,
241c5a382ebSOlga Kornievskaia 						       int clid)
242c5a382ebSOlga Kornievskaia {
243c5a382ebSOlga Kornievskaia 	struct rpc_sysfs_client *p;
244c5a382ebSOlga Kornievskaia 
245c5a382ebSOlga Kornievskaia 	p = kzalloc(sizeof(*p), GFP_KERNEL);
246c5a382ebSOlga Kornievskaia 	if (p) {
247c5a382ebSOlga Kornievskaia 		p->net = net;
248c5a382ebSOlga Kornievskaia 		p->kobject.kset = rpc_sunrpc_kset;
249c5a382ebSOlga Kornievskaia 		if (kobject_init_and_add(&p->kobject, &rpc_sysfs_client_type,
250c5a382ebSOlga Kornievskaia 					 parent, "clnt-%d", clid) == 0)
251c5a382ebSOlga Kornievskaia 			return p;
252c5a382ebSOlga Kornievskaia 		kobject_put(&p->kobject);
253c5a382ebSOlga Kornievskaia 	}
254c5a382ebSOlga Kornievskaia 	return NULL;
255c5a382ebSOlga Kornievskaia }
256c5a382ebSOlga Kornievskaia 
257baea9944SOlga Kornievskaia static struct rpc_sysfs_xprt_switch *
258baea9944SOlga Kornievskaia rpc_sysfs_xprt_switch_alloc(struct kobject *parent,
259baea9944SOlga Kornievskaia 			    struct rpc_xprt_switch *xprt_switch,
260baea9944SOlga Kornievskaia 			    struct net *net,
261baea9944SOlga Kornievskaia 			    gfp_t gfp_flags)
262baea9944SOlga Kornievskaia {
263baea9944SOlga Kornievskaia 	struct rpc_sysfs_xprt_switch *p;
264baea9944SOlga Kornievskaia 
265baea9944SOlga Kornievskaia 	p = kzalloc(sizeof(*p), gfp_flags);
266baea9944SOlga Kornievskaia 	if (p) {
267baea9944SOlga Kornievskaia 		p->net = net;
268baea9944SOlga Kornievskaia 		p->kobject.kset = rpc_sunrpc_kset;
269baea9944SOlga Kornievskaia 		if (kobject_init_and_add(&p->kobject,
270baea9944SOlga Kornievskaia 					 &rpc_sysfs_xprt_switch_type,
271baea9944SOlga Kornievskaia 					 parent, "switch-%d",
272baea9944SOlga Kornievskaia 					 xprt_switch->xps_id) == 0)
273baea9944SOlga Kornievskaia 			return p;
274baea9944SOlga Kornievskaia 		kobject_put(&p->kobject);
275baea9944SOlga Kornievskaia 	}
276baea9944SOlga Kornievskaia 	return NULL;
277baea9944SOlga Kornievskaia }
278baea9944SOlga Kornievskaia 
279d408ebe0SOlga Kornievskaia static struct rpc_sysfs_xprt *rpc_sysfs_xprt_alloc(struct kobject *parent,
280d408ebe0SOlga Kornievskaia 						   struct rpc_xprt *xprt,
281d408ebe0SOlga Kornievskaia 						   gfp_t gfp_flags)
282d408ebe0SOlga Kornievskaia {
283d408ebe0SOlga Kornievskaia 	struct rpc_sysfs_xprt *p;
284d408ebe0SOlga Kornievskaia 
285d408ebe0SOlga Kornievskaia 	p = kzalloc(sizeof(*p), gfp_flags);
286d408ebe0SOlga Kornievskaia 	if (!p)
287d408ebe0SOlga Kornievskaia 		goto out;
288d408ebe0SOlga Kornievskaia 	p->kobject.kset = rpc_sunrpc_kset;
289d408ebe0SOlga Kornievskaia 	if (kobject_init_and_add(&p->kobject, &rpc_sysfs_xprt_type,
290d408ebe0SOlga Kornievskaia 				 parent, "xprt-%d-%s", xprt->id,
291d408ebe0SOlga Kornievskaia 				 xprt->address_strings[RPC_DISPLAY_PROTO]) == 0)
292d408ebe0SOlga Kornievskaia 		return p;
293d408ebe0SOlga Kornievskaia 	kobject_put(&p->kobject);
294d408ebe0SOlga Kornievskaia out:
295d408ebe0SOlga Kornievskaia 	return NULL;
296d408ebe0SOlga Kornievskaia }
297d408ebe0SOlga Kornievskaia 
2982a338a54SOlga Kornievskaia void rpc_sysfs_client_setup(struct rpc_clnt *clnt,
2992a338a54SOlga Kornievskaia 			    struct rpc_xprt_switch *xprt_switch,
3002a338a54SOlga Kornievskaia 			    struct net *net)
301c5a382ebSOlga Kornievskaia {
302c5a382ebSOlga Kornievskaia 	struct rpc_sysfs_client *rpc_client;
303c5a382ebSOlga Kornievskaia 
3042a338a54SOlga Kornievskaia 	rpc_client = rpc_sysfs_client_alloc(rpc_sunrpc_client_kobj,
3052a338a54SOlga Kornievskaia 					    net, clnt->cl_clid);
306c5a382ebSOlga Kornievskaia 	if (rpc_client) {
3072a338a54SOlga Kornievskaia 		char name[] = "switch";
3082a338a54SOlga Kornievskaia 		struct rpc_sysfs_xprt_switch *xswitch =
3092a338a54SOlga Kornievskaia 			(struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
3102a338a54SOlga Kornievskaia 		int ret;
3112a338a54SOlga Kornievskaia 
312c5a382ebSOlga Kornievskaia 		clnt->cl_sysfs = rpc_client;
3132a338a54SOlga Kornievskaia 		rpc_client->clnt = clnt;
3142a338a54SOlga Kornievskaia 		rpc_client->xprt_switch = xprt_switch;
315c5a382ebSOlga Kornievskaia 		kobject_uevent(&rpc_client->kobject, KOBJ_ADD);
3162a338a54SOlga Kornievskaia 		ret = sysfs_create_link_nowarn(&rpc_client->kobject,
3172a338a54SOlga Kornievskaia 					       &xswitch->kobject, name);
3182a338a54SOlga Kornievskaia 		if (ret)
3192a338a54SOlga Kornievskaia 			pr_warn("can't create link to %s in sysfs (%d)\n",
3202a338a54SOlga Kornievskaia 				name, ret);
321c5a382ebSOlga Kornievskaia 	}
322c5a382ebSOlga Kornievskaia }
323c5a382ebSOlga Kornievskaia 
324baea9944SOlga Kornievskaia void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch,
325baea9944SOlga Kornievskaia 				 struct rpc_xprt *xprt,
326baea9944SOlga Kornievskaia 				 gfp_t gfp_flags)
327baea9944SOlga Kornievskaia {
328baea9944SOlga Kornievskaia 	struct rpc_sysfs_xprt_switch *rpc_xprt_switch;
329baea9944SOlga Kornievskaia 	struct net *net;
330baea9944SOlga Kornievskaia 
331baea9944SOlga Kornievskaia 	if (xprt_switch->xps_net)
332baea9944SOlga Kornievskaia 		net = xprt_switch->xps_net;
333baea9944SOlga Kornievskaia 	else
334baea9944SOlga Kornievskaia 		net = xprt->xprt_net;
335baea9944SOlga Kornievskaia 	rpc_xprt_switch =
336baea9944SOlga Kornievskaia 		rpc_sysfs_xprt_switch_alloc(rpc_sunrpc_xprt_switch_kobj,
337baea9944SOlga Kornievskaia 					    xprt_switch, net, gfp_flags);
338baea9944SOlga Kornievskaia 	if (rpc_xprt_switch) {
339baea9944SOlga Kornievskaia 		xprt_switch->xps_sysfs = rpc_xprt_switch;
340baea9944SOlga Kornievskaia 		rpc_xprt_switch->xprt_switch = xprt_switch;
341baea9944SOlga Kornievskaia 		rpc_xprt_switch->xprt = xprt;
342baea9944SOlga Kornievskaia 		kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD);
343baea9944SOlga Kornievskaia 	}
344baea9944SOlga Kornievskaia }
345baea9944SOlga Kornievskaia 
346d408ebe0SOlga Kornievskaia void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch,
347d408ebe0SOlga Kornievskaia 			  struct rpc_xprt *xprt,
348d408ebe0SOlga Kornievskaia 			  gfp_t gfp_flags)
349d408ebe0SOlga Kornievskaia {
350d408ebe0SOlga Kornievskaia 	struct rpc_sysfs_xprt *rpc_xprt;
351d408ebe0SOlga Kornievskaia 	struct rpc_sysfs_xprt_switch *switch_obj =
352d408ebe0SOlga Kornievskaia 		(struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
353d408ebe0SOlga Kornievskaia 
354d408ebe0SOlga Kornievskaia 	rpc_xprt = rpc_sysfs_xprt_alloc(&switch_obj->kobject, xprt, gfp_flags);
355d408ebe0SOlga Kornievskaia 	if (rpc_xprt) {
356d408ebe0SOlga Kornievskaia 		xprt->xprt_sysfs = rpc_xprt;
357d408ebe0SOlga Kornievskaia 		rpc_xprt->xprt = xprt;
358d408ebe0SOlga Kornievskaia 		kobject_uevent(&rpc_xprt->kobject, KOBJ_ADD);
359d408ebe0SOlga Kornievskaia 	}
360d408ebe0SOlga Kornievskaia }
361d408ebe0SOlga Kornievskaia 
362c5a382ebSOlga Kornievskaia void rpc_sysfs_client_destroy(struct rpc_clnt *clnt)
363c5a382ebSOlga Kornievskaia {
364c5a382ebSOlga Kornievskaia 	struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs;
365c5a382ebSOlga Kornievskaia 
366c5a382ebSOlga Kornievskaia 	if (rpc_client) {
3672a338a54SOlga Kornievskaia 		char name[] = "switch";
3682a338a54SOlga Kornievskaia 
3692a338a54SOlga Kornievskaia 		sysfs_remove_link(&rpc_client->kobject, name);
370c5a382ebSOlga Kornievskaia 		kobject_uevent(&rpc_client->kobject, KOBJ_REMOVE);
371c5a382ebSOlga Kornievskaia 		kobject_del(&rpc_client->kobject);
372c5a382ebSOlga Kornievskaia 		kobject_put(&rpc_client->kobject);
373c5a382ebSOlga Kornievskaia 		clnt->cl_sysfs = NULL;
374c5a382ebSOlga Kornievskaia 	}
375c5a382ebSOlga Kornievskaia }
376baea9944SOlga Kornievskaia 
377baea9944SOlga Kornievskaia void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt_switch)
378baea9944SOlga Kornievskaia {
379baea9944SOlga Kornievskaia 	struct rpc_sysfs_xprt_switch *rpc_xprt_switch = xprt_switch->xps_sysfs;
380baea9944SOlga Kornievskaia 
381baea9944SOlga Kornievskaia 	if (rpc_xprt_switch) {
382baea9944SOlga Kornievskaia 		kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_REMOVE);
383baea9944SOlga Kornievskaia 		kobject_del(&rpc_xprt_switch->kobject);
384baea9944SOlga Kornievskaia 		kobject_put(&rpc_xprt_switch->kobject);
385baea9944SOlga Kornievskaia 		xprt_switch->xps_sysfs = NULL;
386baea9944SOlga Kornievskaia 	}
387baea9944SOlga Kornievskaia }
388d408ebe0SOlga Kornievskaia 
389d408ebe0SOlga Kornievskaia void rpc_sysfs_xprt_destroy(struct rpc_xprt *xprt)
390d408ebe0SOlga Kornievskaia {
391d408ebe0SOlga Kornievskaia 	struct rpc_sysfs_xprt *rpc_xprt = xprt->xprt_sysfs;
392d408ebe0SOlga Kornievskaia 
393d408ebe0SOlga Kornievskaia 	if (rpc_xprt) {
394d408ebe0SOlga Kornievskaia 		kobject_uevent(&rpc_xprt->kobject, KOBJ_REMOVE);
395d408ebe0SOlga Kornievskaia 		kobject_del(&rpc_xprt->kobject);
396d408ebe0SOlga Kornievskaia 		kobject_put(&rpc_xprt->kobject);
397d408ebe0SOlga Kornievskaia 		xprt->xprt_sysfs = NULL;
398d408ebe0SOlga Kornievskaia 	}
399d408ebe0SOlga Kornievskaia }
400