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