Message ID | 20210426171947.99233-11-olga.kornievskaia@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | create sysfs files for changing IP address | expand |
On Mon, 2021-04-26 at 13:19 -0400, Olga Kornievskaia wrote: > From: Olga Kornievskaia <kolga@netapp.com> > > Add individual transport directories under each transport switch > group. For instance, for each nconnect=X connections there will be > a transport directory. Naming conventions also identifies transport > type -- xprt-<id>-<type> where type is udp, tcp, rdma, local, bc. > > Signed-off-by: Olga Kornievskaia <kolga@netapp.com> > --- > include/linux/sunrpc/xprt.h | 1 + > net/sunrpc/sysfs.c | 86 > +++++++++++++++++++++++++++++++++++++ > net/sunrpc/sysfs.h | 9 ++++ > net/sunrpc/xprtmultipath.c | 10 +++++ > 4 files changed, 106 insertions(+) > > diff --git a/include/linux/sunrpc/xprt.h > b/include/linux/sunrpc/xprt.h > index a2edcc42e6c4..1e4906759a6a 100644 > --- a/include/linux/sunrpc/xprt.h > +++ b/include/linux/sunrpc/xprt.h > @@ -291,6 +291,7 @@ struct rpc_xprt { > #endif > struct rcu_head rcu; > const struct xprt_class *xprt_class; > + void *xprt_sysfs; Again, this should be a typed pointer. > }; > > #if defined(CONFIG_SUNRPC_BACKCHANNEL) > diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c > index 871f7c696a93..682def4293f2 100644 > --- a/net/sunrpc/sysfs.c > +++ b/net/sunrpc/sysfs.c > @@ -81,6 +81,14 @@ static void rpc_sysfs_xprt_switch_release(struct > kobject *kobj) > kfree(xprt_switch); > } > > +static void rpc_sysfs_xprt_switch_xprt_release(struct kobject *kobj) > +{ > + struct rpc_sysfs_xprt_switch_xprt *xprt; > + > + xprt = container_of(kobj, struct rpc_sysfs_xprt_switch_xprt, > kobject); > + kfree(xprt); > +} > + > static const void *rpc_sysfs_client_namespace(struct kobject *kobj) > { > return container_of(kobj, struct rpc_sysfs_client, kobject)- > >net; > @@ -91,6 +99,12 @@ static const void > *rpc_sysfs_xprt_switch_namespace(struct kobject *kobj) > return container_of(kobj, struct rpc_sysfs_xprt_switch, > kobject)->net; > } > > +static const void *rpc_sysfs_xprt_switch_xprt_namespace(struct > kobject *kobj) > +{ > + return container_of(kobj, struct rpc_sysfs_xprt_switch_xprt, > + kobject)->net; > +} > + > static struct kobj_type rpc_sysfs_client_type = { > .release = rpc_sysfs_client_release, > .sysfs_ops = &kobj_sysfs_ops, > @@ -103,6 +117,12 @@ static struct kobj_type > rpc_sysfs_xprt_switch_type = { > .namespace = rpc_sysfs_xprt_switch_namespace, > }; > > +static struct kobj_type rpc_sysfs_xprt_switch_xprt_type = { > + .release = rpc_sysfs_xprt_switch_xprt_release, > + .sysfs_ops = &kobj_sysfs_ops, > + .namespace = rpc_sysfs_xprt_switch_xprt_namespace, > +}; > + > void rpc_sysfs_exit(void) > { > kobject_put(rpc_sunrpc_client_kobj); > @@ -150,6 +170,40 @@ rpc_sysfs_xprt_switch_alloc(struct kobject > *parent, > return NULL; > } > > +static struct rpc_sysfs_xprt_switch_xprt * > +rpc_sysfs_xprt_switch_xprt_alloc(struct kobject *parent, > + struct rpc_xprt *xprt, > + struct net *net, > + gfp_t gfp_flags) > +{ > + struct rpc_sysfs_xprt_switch_xprt *p; > + > + p = kzalloc(sizeof(*p), gfp_flags); > + if (p) { > + char type[6]; > + > + p->net = net; > + p->kobject.kset = rpc_sunrpc_kset; > + if (xprt->xprt_class->ident == XPRT_TRANSPORT_RDMA) > + snprintf(type, sizeof(type), "rdma"); > + else if (xprt->xprt_class->ident == > XPRT_TRANSPORT_TCP) > + snprintf(type, sizeof(type), "tcp"); > + else if (xprt->xprt_class->ident == > XPRT_TRANSPORT_UDP) > + snprintf(type, sizeof(type), "udp"); > + else if (xprt->xprt_class->ident == > XPRT_TRANSPORT_LOCAL) > + snprintf(type, sizeof(type), "local"); > + else if (xprt->xprt_class->ident == > XPRT_TRANSPORT_BC_TCP) > + snprintf(type, sizeof(type), "bc"); > + if (kobject_init_and_add(&p->kobject, > + > &rpc_sysfs_xprt_switch_xprt_type, > + parent, "xprt-%d-%s", xprt- > >id, > + type) == 0) > + return p; > + kobject_put(&p->kobject); > + } > + return NULL; > +} > + > void rpc_sysfs_client_setup(struct rpc_clnt *clnt, > struct rpc_xprt_switch *xprt_switch, > struct net *net) > @@ -199,6 +253,25 @@ void rpc_sysfs_xprt_switch_setup(struct > rpc_xprt_switch *xprt_switch, > } > } > > +void rpc_sysfs_xprt_switch_xprt_setup(struct rpc_xprt_switch > *xprt_switch, > + struct rpc_xprt *xprt, > + gfp_t gfp_flags) > +{ > + struct rpc_sysfs_xprt_switch_xprt *rpc_xprt_switch_xprt; > + struct rpc_sysfs_xprt_switch *switch_obj = > + (struct rpc_sysfs_xprt_switch *)xprt_switch- > >xps_sysfs; > + > + rpc_xprt_switch_xprt = > + rpc_sysfs_xprt_switch_xprt_alloc(&switch_obj- > >kobject, > + xprt, xprt- > >xprt_net, > + gfp_flags); > + if (rpc_xprt_switch_xprt) { > + xprt->xprt_sysfs = rpc_xprt_switch_xprt; > + rpc_xprt_switch_xprt->xprt = xprt; > + kobject_uevent(&rpc_xprt_switch_xprt->kobject, > KOBJ_ADD); > + } > +} > + > void rpc_sysfs_client_destroy(struct rpc_clnt *clnt) > { > struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs; > @@ -227,3 +300,16 @@ void rpc_sysfs_xprt_switch_destroy(struct > rpc_xprt_switch *xprt_switch) > xprt_switch->xps_sysfs = NULL; > } > } > + > +void rpc_sysfs_xprt_switch_xprt_destroy(struct rpc_xprt *xprt) > +{ > + struct rpc_sysfs_xprt_switch_xprt *rpc_xprt_switch_xprt = > + xprt->xprt_sysfs; > + > + if (rpc_xprt_switch_xprt) { > + kobject_uevent(&rpc_xprt_switch_xprt->kobject, > KOBJ_REMOVE); > + kobject_del(&rpc_xprt_switch_xprt->kobject); > + kobject_put(&rpc_xprt_switch_xprt->kobject); > + xprt->xprt_sysfs = NULL; > + } > +} > diff --git a/net/sunrpc/sysfs.h b/net/sunrpc/sysfs.h > index 760f0582aee5..b2ede4a2a82b 100644 > --- a/net/sunrpc/sysfs.h > +++ b/net/sunrpc/sysfs.h > @@ -19,6 +19,12 @@ struct rpc_sysfs_xprt_switch { > struct rpc_xprt *xprt; > }; > > +struct rpc_sysfs_xprt_switch_xprt { > + struct kobject kobject; > + struct net *net; > + struct rpc_xprt *xprt; > +}; Can we please rename this to something that doesn't imply that it is part of the xprt_switch? It is tied to a struct rpc_xprt rather than the switch. Also, why do you need a pointer to struct net here? Why not just use xprt->xprt_net when a pointer is needed? > + > int rpc_sysfs_init(void); > void rpc_sysfs_exit(void); > > @@ -29,5 +35,8 @@ void rpc_sysfs_client_destroy(struct rpc_clnt > *clnt); > void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch > *xprt_switch, > struct rpc_xprt *xprt, gfp_t > gfp_flags); > void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt); > +void rpc_sysfs_xprt_switch_xprt_setup(struct rpc_xprt_switch > *xprt_switch, > + struct rpc_xprt *xprt, gfp_t > gfp_flags); > +void rpc_sysfs_xprt_switch_xprt_destroy(struct rpc_xprt *xprt); > > #endif > diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c > index 2d73a35df9ee..839b20e72ffd 100644 > --- a/net/sunrpc/xprtmultipath.c > +++ b/net/sunrpc/xprtmultipath.c > @@ -57,6 +57,11 @@ void rpc_xprt_switch_add_xprt(struct > rpc_xprt_switch *xps, > if (xps->xps_net == xprt->xprt_net || xps->xps_net == NULL) > xprt_switch_add_xprt_locked(xps, xprt); > spin_unlock(&xps->xps_lock); > + xprt_switch_get(xps); > + xprt_get(xprt); Do we need the get/put here? Won't the caller always hold appropriate references? > + rpc_sysfs_xprt_switch_xprt_setup(xps, xprt, GFP_KERNEL); > + xprt_switch_put(xps); > + xprt_put(xprt); > } > > static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch > *xps, > @@ -85,6 +90,7 @@ void rpc_xprt_switch_remove_xprt(struct > rpc_xprt_switch *xps, > spin_lock(&xps->xps_lock); > xprt_switch_remove_xprt_locked(xps, xprt); > spin_unlock(&xps->xps_lock); > + rpc_sysfs_xprt_switch_xprt_destroy(xprt); > xprt_put(xprt); > } > > @@ -137,6 +143,9 @@ struct rpc_xprt_switch *xprt_switch_alloc(struct > rpc_xprt *xprt, > xps->xps_iter_ops = &rpc_xprt_iter_singular; > rpc_sysfs_xprt_switch_setup(xps, xprt, gfp_flags); > xprt_switch_add_xprt_locked(xps, xprt); > + xprt_get(xprt); > + rpc_sysfs_xprt_switch_xprt_setup(xps, xprt, > gfp_flags); > + xprt_put(xprt); > } > > return xps; > @@ -152,6 +161,7 @@ static void xprt_switch_free_entries(struct > rpc_xprt_switch *xps) > struct rpc_xprt, xprt_switch); > xprt_switch_remove_xprt_locked(xps, xprt); > spin_unlock(&xps->xps_lock); > + rpc_sysfs_xprt_switch_xprt_destroy(xprt); > xprt_put(xprt); > spin_lock(&xps->xps_lock); > }
On Mon, 2021-04-26 at 13:19 -0400, Olga Kornievskaia wrote: > From: Olga Kornievskaia <kolga@netapp.com> > > Add individual transport directories under each transport switch > group. For instance, for each nconnect=X connections there will be > a transport directory. Naming conventions also identifies transport > type -- xprt-<id>-<type> where type is udp, tcp, rdma, local, bc. > > Signed-off-by: Olga Kornievskaia <kolga@netapp.com> > --- > include/linux/sunrpc/xprt.h | 1 + > net/sunrpc/sysfs.c | 86 > +++++++++++++++++++++++++++++++++++++ > net/sunrpc/sysfs.h | 9 ++++ > net/sunrpc/xprtmultipath.c | 10 +++++ > 4 files changed, 106 insertions(+) > > diff --git a/include/linux/sunrpc/xprt.h > b/include/linux/sunrpc/xprt.h > index a2edcc42e6c4..1e4906759a6a 100644 > --- a/include/linux/sunrpc/xprt.h > +++ b/include/linux/sunrpc/xprt.h > @@ -291,6 +291,7 @@ struct rpc_xprt { > #endif > struct rcu_head rcu; > const struct xprt_class *xprt_class; > + void *xprt_sysfs; > }; > > #if defined(CONFIG_SUNRPC_BACKCHANNEL) > diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c > index 871f7c696a93..682def4293f2 100644 > --- a/net/sunrpc/sysfs.c > +++ b/net/sunrpc/sysfs.c > @@ -81,6 +81,14 @@ static void rpc_sysfs_xprt_switch_release(struct > kobject *kobj) > kfree(xprt_switch); > } > > +static void rpc_sysfs_xprt_switch_xprt_release(struct kobject *kobj) > +{ > + struct rpc_sysfs_xprt_switch_xprt *xprt; > + > + xprt = container_of(kobj, struct rpc_sysfs_xprt_switch_xprt, > kobject); > + kfree(xprt); > +} > + > static const void *rpc_sysfs_client_namespace(struct kobject *kobj) > { > return container_of(kobj, struct rpc_sysfs_client, kobject)- > >net; > @@ -91,6 +99,12 @@ static const void > *rpc_sysfs_xprt_switch_namespace(struct kobject *kobj) > return container_of(kobj, struct rpc_sysfs_xprt_switch, > kobject)->net; > } > > +static const void *rpc_sysfs_xprt_switch_xprt_namespace(struct > kobject *kobj) > +{ > + return container_of(kobj, struct rpc_sysfs_xprt_switch_xprt, > + kobject)->net; > +} > + > static struct kobj_type rpc_sysfs_client_type = { > .release = rpc_sysfs_client_release, > .sysfs_ops = &kobj_sysfs_ops, > @@ -103,6 +117,12 @@ static struct kobj_type > rpc_sysfs_xprt_switch_type = { > .namespace = rpc_sysfs_xprt_switch_namespace, > }; > > +static struct kobj_type rpc_sysfs_xprt_switch_xprt_type = { > + .release = rpc_sysfs_xprt_switch_xprt_release, > + .sysfs_ops = &kobj_sysfs_ops, > + .namespace = rpc_sysfs_xprt_switch_xprt_namespace, > +}; > + > void rpc_sysfs_exit(void) > { > kobject_put(rpc_sunrpc_client_kobj); > @@ -150,6 +170,40 @@ rpc_sysfs_xprt_switch_alloc(struct kobject > *parent, > return NULL; > } > > +static struct rpc_sysfs_xprt_switch_xprt * > +rpc_sysfs_xprt_switch_xprt_alloc(struct kobject *parent, > + struct rpc_xprt *xprt, > + struct net *net, > + gfp_t gfp_flags) > +{ > + struct rpc_sysfs_xprt_switch_xprt *p; > + > + p = kzalloc(sizeof(*p), gfp_flags); > + if (p) { > + char type[6]; > + > + p->net = net; > + p->kobject.kset = rpc_sunrpc_kset; > + if (xprt->xprt_class->ident == XPRT_TRANSPORT_RDMA) > + snprintf(type, sizeof(type), "rdma"); > + else if (xprt->xprt_class->ident == > XPRT_TRANSPORT_TCP) > + snprintf(type, sizeof(type), "tcp"); > + else if (xprt->xprt_class->ident == > XPRT_TRANSPORT_UDP) > + snprintf(type, sizeof(type), "udp"); > + else if (xprt->xprt_class->ident == > XPRT_TRANSPORT_LOCAL) > + snprintf(type, sizeof(type), "local"); > + else if (xprt->xprt_class->ident == > XPRT_TRANSPORT_BC_TCP) > + snprintf(type, sizeof(type), "bc"); Urgh. Can we perhaps use xprt->address_strings[RPC_DISPLAY_NETID] or RPC_DISPLAY_PROTO? I'd really prefer that we don't make assumptions that the current set of values for xprt->xprt_class is complete. > + if (kobject_init_and_add(&p->kobject, > + > &rpc_sysfs_xprt_switch_xprt_type, > + parent, "xprt-%d-%s", xprt- > >id, > + type) == 0) > + return p; > + kobject_put(&p->kobject); > + } > + return NULL; > +} > + > void rpc_sysfs_client_setup(struct rpc_clnt *clnt, > struct rpc_xprt_switch *xprt_switch, > struct net *net) > @@ -199,6 +253,25 @@ void rpc_sysfs_xprt_switch_setup(struct > rpc_xprt_switch *xprt_switch, > } > } > > +void rpc_sysfs_xprt_switch_xprt_setup(struct rpc_xprt_switch > *xprt_switch, > + struct rpc_xprt *xprt, > + gfp_t gfp_flags) > +{ > + struct rpc_sysfs_xprt_switch_xprt *rpc_xprt_switch_xprt; > + struct rpc_sysfs_xprt_switch *switch_obj = > + (struct rpc_sysfs_xprt_switch *)xprt_switch- > >xps_sysfs; > + > + rpc_xprt_switch_xprt = > + rpc_sysfs_xprt_switch_xprt_alloc(&switch_obj- > >kobject, > + xprt, xprt- > >xprt_net, > + gfp_flags); > + if (rpc_xprt_switch_xprt) { > + xprt->xprt_sysfs = rpc_xprt_switch_xprt; > + rpc_xprt_switch_xprt->xprt = xprt; > + kobject_uevent(&rpc_xprt_switch_xprt->kobject, > KOBJ_ADD); > + } > +} > + > void rpc_sysfs_client_destroy(struct rpc_clnt *clnt) > { > struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs; > @@ -227,3 +300,16 @@ void rpc_sysfs_xprt_switch_destroy(struct > rpc_xprt_switch *xprt_switch) > xprt_switch->xps_sysfs = NULL; > } > } > + > +void rpc_sysfs_xprt_switch_xprt_destroy(struct rpc_xprt *xprt) > +{ > + struct rpc_sysfs_xprt_switch_xprt *rpc_xprt_switch_xprt = > + xprt->xprt_sysfs; > + > + if (rpc_xprt_switch_xprt) { > + kobject_uevent(&rpc_xprt_switch_xprt->kobject, > KOBJ_REMOVE); > + kobject_del(&rpc_xprt_switch_xprt->kobject); > + kobject_put(&rpc_xprt_switch_xprt->kobject); > + xprt->xprt_sysfs = NULL; > + } > +} > diff --git a/net/sunrpc/sysfs.h b/net/sunrpc/sysfs.h > index 760f0582aee5..b2ede4a2a82b 100644 > --- a/net/sunrpc/sysfs.h > +++ b/net/sunrpc/sysfs.h > @@ -19,6 +19,12 @@ struct rpc_sysfs_xprt_switch { > struct rpc_xprt *xprt; > }; > > +struct rpc_sysfs_xprt_switch_xprt { > + struct kobject kobject; > + struct net *net; > + struct rpc_xprt *xprt; > +}; > + > int rpc_sysfs_init(void); > void rpc_sysfs_exit(void); > > @@ -29,5 +35,8 @@ void rpc_sysfs_client_destroy(struct rpc_clnt > *clnt); > void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch > *xprt_switch, > struct rpc_xprt *xprt, gfp_t > gfp_flags); > void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt); > +void rpc_sysfs_xprt_switch_xprt_setup(struct rpc_xprt_switch > *xprt_switch, > + struct rpc_xprt *xprt, gfp_t > gfp_flags); > +void rpc_sysfs_xprt_switch_xprt_destroy(struct rpc_xprt *xprt); > > #endif > diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c > index 2d73a35df9ee..839b20e72ffd 100644 > --- a/net/sunrpc/xprtmultipath.c > +++ b/net/sunrpc/xprtmultipath.c > @@ -57,6 +57,11 @@ void rpc_xprt_switch_add_xprt(struct > rpc_xprt_switch *xps, > if (xps->xps_net == xprt->xprt_net || xps->xps_net == NULL) > xprt_switch_add_xprt_locked(xps, xprt); > spin_unlock(&xps->xps_lock); > + xprt_switch_get(xps); > + xprt_get(xprt); Are the above references necessary? > + rpc_sysfs_xprt_switch_xprt_setup(xps, xprt, GFP_KERNEL); > + xprt_switch_put(xps); > + xprt_put(xprt); > } > > static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch > *xps, > @@ -85,6 +90,7 @@ void rpc_xprt_switch_remove_xprt(struct > rpc_xprt_switch *xps, > spin_lock(&xps->xps_lock); > xprt_switch_remove_xprt_locked(xps, xprt); > spin_unlock(&xps->xps_lock); > + rpc_sysfs_xprt_switch_xprt_destroy(xprt); > xprt_put(xprt); > } > > @@ -137,6 +143,9 @@ struct rpc_xprt_switch *xprt_switch_alloc(struct > rpc_xprt *xprt, > xps->xps_iter_ops = &rpc_xprt_iter_singular; > rpc_sysfs_xprt_switch_setup(xps, xprt, gfp_flags); > xprt_switch_add_xprt_locked(xps, xprt); > + xprt_get(xprt); > + rpc_sysfs_xprt_switch_xprt_setup(xps, xprt, > gfp_flags); > + xprt_put(xprt); > } > > return xps; > @@ -152,6 +161,7 @@ static void xprt_switch_free_entries(struct > rpc_xprt_switch *xps) > struct rpc_xprt, xprt_switch); > xprt_switch_remove_xprt_locked(xps, xprt); > spin_unlock(&xps->xps_lock); > + rpc_sysfs_xprt_switch_xprt_destroy(xprt); > xprt_put(xprt); > spin_lock(&xps->xps_lock); > }
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index a2edcc42e6c4..1e4906759a6a 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -291,6 +291,7 @@ struct rpc_xprt { #endif struct rcu_head rcu; const struct xprt_class *xprt_class; + void *xprt_sysfs; }; #if defined(CONFIG_SUNRPC_BACKCHANNEL) diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c index 871f7c696a93..682def4293f2 100644 --- a/net/sunrpc/sysfs.c +++ b/net/sunrpc/sysfs.c @@ -81,6 +81,14 @@ static void rpc_sysfs_xprt_switch_release(struct kobject *kobj) kfree(xprt_switch); } +static void rpc_sysfs_xprt_switch_xprt_release(struct kobject *kobj) +{ + struct rpc_sysfs_xprt_switch_xprt *xprt; + + xprt = container_of(kobj, struct rpc_sysfs_xprt_switch_xprt, kobject); + kfree(xprt); +} + static const void *rpc_sysfs_client_namespace(struct kobject *kobj) { return container_of(kobj, struct rpc_sysfs_client, kobject)->net; @@ -91,6 +99,12 @@ static const void *rpc_sysfs_xprt_switch_namespace(struct kobject *kobj) return container_of(kobj, struct rpc_sysfs_xprt_switch, kobject)->net; } +static const void *rpc_sysfs_xprt_switch_xprt_namespace(struct kobject *kobj) +{ + return container_of(kobj, struct rpc_sysfs_xprt_switch_xprt, + kobject)->net; +} + static struct kobj_type rpc_sysfs_client_type = { .release = rpc_sysfs_client_release, .sysfs_ops = &kobj_sysfs_ops, @@ -103,6 +117,12 @@ static struct kobj_type rpc_sysfs_xprt_switch_type = { .namespace = rpc_sysfs_xprt_switch_namespace, }; +static struct kobj_type rpc_sysfs_xprt_switch_xprt_type = { + .release = rpc_sysfs_xprt_switch_xprt_release, + .sysfs_ops = &kobj_sysfs_ops, + .namespace = rpc_sysfs_xprt_switch_xprt_namespace, +}; + void rpc_sysfs_exit(void) { kobject_put(rpc_sunrpc_client_kobj); @@ -150,6 +170,40 @@ rpc_sysfs_xprt_switch_alloc(struct kobject *parent, return NULL; } +static struct rpc_sysfs_xprt_switch_xprt * +rpc_sysfs_xprt_switch_xprt_alloc(struct kobject *parent, + struct rpc_xprt *xprt, + struct net *net, + gfp_t gfp_flags) +{ + struct rpc_sysfs_xprt_switch_xprt *p; + + p = kzalloc(sizeof(*p), gfp_flags); + if (p) { + char type[6]; + + p->net = net; + p->kobject.kset = rpc_sunrpc_kset; + if (xprt->xprt_class->ident == XPRT_TRANSPORT_RDMA) + snprintf(type, sizeof(type), "rdma"); + else if (xprt->xprt_class->ident == XPRT_TRANSPORT_TCP) + snprintf(type, sizeof(type), "tcp"); + else if (xprt->xprt_class->ident == XPRT_TRANSPORT_UDP) + snprintf(type, sizeof(type), "udp"); + else if (xprt->xprt_class->ident == XPRT_TRANSPORT_LOCAL) + snprintf(type, sizeof(type), "local"); + else if (xprt->xprt_class->ident == XPRT_TRANSPORT_BC_TCP) + snprintf(type, sizeof(type), "bc"); + if (kobject_init_and_add(&p->kobject, + &rpc_sysfs_xprt_switch_xprt_type, + parent, "xprt-%d-%s", xprt->id, + type) == 0) + return p; + kobject_put(&p->kobject); + } + return NULL; +} + void rpc_sysfs_client_setup(struct rpc_clnt *clnt, struct rpc_xprt_switch *xprt_switch, struct net *net) @@ -199,6 +253,25 @@ void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch, } } +void rpc_sysfs_xprt_switch_xprt_setup(struct rpc_xprt_switch *xprt_switch, + struct rpc_xprt *xprt, + gfp_t gfp_flags) +{ + struct rpc_sysfs_xprt_switch_xprt *rpc_xprt_switch_xprt; + struct rpc_sysfs_xprt_switch *switch_obj = + (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs; + + rpc_xprt_switch_xprt = + rpc_sysfs_xprt_switch_xprt_alloc(&switch_obj->kobject, + xprt, xprt->xprt_net, + gfp_flags); + if (rpc_xprt_switch_xprt) { + xprt->xprt_sysfs = rpc_xprt_switch_xprt; + rpc_xprt_switch_xprt->xprt = xprt; + kobject_uevent(&rpc_xprt_switch_xprt->kobject, KOBJ_ADD); + } +} + void rpc_sysfs_client_destroy(struct rpc_clnt *clnt) { struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs; @@ -227,3 +300,16 @@ void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt_switch) xprt_switch->xps_sysfs = NULL; } } + +void rpc_sysfs_xprt_switch_xprt_destroy(struct rpc_xprt *xprt) +{ + struct rpc_sysfs_xprt_switch_xprt *rpc_xprt_switch_xprt = + xprt->xprt_sysfs; + + if (rpc_xprt_switch_xprt) { + kobject_uevent(&rpc_xprt_switch_xprt->kobject, KOBJ_REMOVE); + kobject_del(&rpc_xprt_switch_xprt->kobject); + kobject_put(&rpc_xprt_switch_xprt->kobject); + xprt->xprt_sysfs = NULL; + } +} diff --git a/net/sunrpc/sysfs.h b/net/sunrpc/sysfs.h index 760f0582aee5..b2ede4a2a82b 100644 --- a/net/sunrpc/sysfs.h +++ b/net/sunrpc/sysfs.h @@ -19,6 +19,12 @@ struct rpc_sysfs_xprt_switch { struct rpc_xprt *xprt; }; +struct rpc_sysfs_xprt_switch_xprt { + struct kobject kobject; + struct net *net; + struct rpc_xprt *xprt; +}; + int rpc_sysfs_init(void); void rpc_sysfs_exit(void); @@ -29,5 +35,8 @@ void rpc_sysfs_client_destroy(struct rpc_clnt *clnt); void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch, struct rpc_xprt *xprt, gfp_t gfp_flags); void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt); +void rpc_sysfs_xprt_switch_xprt_setup(struct rpc_xprt_switch *xprt_switch, + struct rpc_xprt *xprt, gfp_t gfp_flags); +void rpc_sysfs_xprt_switch_xprt_destroy(struct rpc_xprt *xprt); #endif diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c index 2d73a35df9ee..839b20e72ffd 100644 --- a/net/sunrpc/xprtmultipath.c +++ b/net/sunrpc/xprtmultipath.c @@ -57,6 +57,11 @@ void rpc_xprt_switch_add_xprt(struct rpc_xprt_switch *xps, if (xps->xps_net == xprt->xprt_net || xps->xps_net == NULL) xprt_switch_add_xprt_locked(xps, xprt); spin_unlock(&xps->xps_lock); + xprt_switch_get(xps); + xprt_get(xprt); + rpc_sysfs_xprt_switch_xprt_setup(xps, xprt, GFP_KERNEL); + xprt_switch_put(xps); + xprt_put(xprt); } static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps, @@ -85,6 +90,7 @@ void rpc_xprt_switch_remove_xprt(struct rpc_xprt_switch *xps, spin_lock(&xps->xps_lock); xprt_switch_remove_xprt_locked(xps, xprt); spin_unlock(&xps->xps_lock); + rpc_sysfs_xprt_switch_xprt_destroy(xprt); xprt_put(xprt); } @@ -137,6 +143,9 @@ struct rpc_xprt_switch *xprt_switch_alloc(struct rpc_xprt *xprt, xps->xps_iter_ops = &rpc_xprt_iter_singular; rpc_sysfs_xprt_switch_setup(xps, xprt, gfp_flags); xprt_switch_add_xprt_locked(xps, xprt); + xprt_get(xprt); + rpc_sysfs_xprt_switch_xprt_setup(xps, xprt, gfp_flags); + xprt_put(xprt); } return xps; @@ -152,6 +161,7 @@ static void xprt_switch_free_entries(struct rpc_xprt_switch *xps) struct rpc_xprt, xprt_switch); xprt_switch_remove_xprt_locked(xps, xprt); spin_unlock(&xps->xps_lock); + rpc_sysfs_xprt_switch_xprt_destroy(xprt); xprt_put(xprt); spin_lock(&xps->xps_lock); }