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