Message ID | 20210426171947.99233-9-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 xprt_switch directory to the sysfs and create individual > xprt_swith subdirectories for multipath transport group. > > Signed-off-by: Olga Kornievskaia <kolga@netapp.com> > --- > include/linux/sunrpc/xprtmultipath.h | 1 + > net/sunrpc/sysfs.c | 99 > ++++++++++++++++++++++++++-- > net/sunrpc/sysfs.h | 10 +++ > net/sunrpc/xprtmultipath.c | 4 ++ > 4 files changed, 107 insertions(+), 7 deletions(-) > > diff --git a/include/linux/sunrpc/xprtmultipath.h > b/include/linux/sunrpc/xprtmultipath.h > index ef95a6f18ccf..47b0a85cdcfa 100644 > --- a/include/linux/sunrpc/xprtmultipath.h > +++ b/include/linux/sunrpc/xprtmultipath.h > @@ -24,6 +24,7 @@ struct rpc_xprt_switch { > > const struct rpc_xprt_iter_ops *xps_iter_ops; > > + void *xps_sysfs; Why is this a void pointer instead of being a pointer to a struct rpc_sysfs_xprt_switch? > struct rcu_head xps_rcu; > }; > > diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c > index d14d54f33c65..03ea6d3ace95 100644 > --- a/net/sunrpc/sysfs.c > +++ b/net/sunrpc/sysfs.c > @@ -7,7 +7,7 @@ > #include "sysfs.h" > > static struct kset *rpc_sunrpc_kset; > -static struct kobject *rpc_sunrpc_client_kobj; > +static struct kobject *rpc_sunrpc_client_kobj, > *rpc_sunrpc_xprt_switch_kobj; > > static void rpc_sysfs_object_release(struct kobject *kobj) > { > @@ -47,13 +47,22 @@ int rpc_sysfs_init(void) > rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, > kernel_kobj); > if (!rpc_sunrpc_kset) > return -ENOMEM; > - rpc_sunrpc_client_kobj = rpc_sysfs_object_alloc("client", > rpc_sunrpc_kset, NULL); > - if (!rpc_sunrpc_client_kobj) { > - kset_unregister(rpc_sunrpc_kset); > - rpc_sunrpc_client_kobj = NULL; > - return -ENOMEM; > - } > + rpc_sunrpc_client_kobj = > + rpc_sysfs_object_alloc("rpc-clients", > rpc_sunrpc_kset, NULL); > + if (!rpc_sunrpc_client_kobj) > + goto err_client; > + rpc_sunrpc_xprt_switch_kobj = > + rpc_sysfs_object_alloc("xprt-switches", > rpc_sunrpc_kset, NULL); > + if (!rpc_sunrpc_xprt_switch_kobj) > + goto err_switch; > return 0; > +err_switch: > + kobject_put(rpc_sunrpc_client_kobj); > + rpc_sunrpc_client_kobj = NULL; > +err_client: > + kset_unregister(rpc_sunrpc_kset); > + rpc_sunrpc_kset = NULL; > + return -ENOMEM; > } > > static void rpc_sysfs_client_release(struct kobject *kobj) > @@ -64,20 +73,40 @@ static void rpc_sysfs_client_release(struct > kobject *kobj) > kfree(c); > } > > +static void rpc_sysfs_xprt_switch_release(struct kobject *kobj) > +{ > + struct rpc_sysfs_xprt_switch *xprt_switch; > + > + xprt_switch = container_of(kobj, struct > rpc_sysfs_xprt_switch, kobject); > + kfree(xprt_switch); > +} > + > static const void *rpc_sysfs_client_namespace(struct kobject *kobj) > { > return container_of(kobj, struct rpc_sysfs_client, kobject)- > >net; > } > > +static const void *rpc_sysfs_xprt_switch_namespace(struct kobject > *kobj) > +{ > + return container_of(kobj, struct rpc_sysfs_xprt_switch, > kobject)->net; > +} > + > static struct kobj_type rpc_sysfs_client_type = { > .release = rpc_sysfs_client_release, > .sysfs_ops = &kobj_sysfs_ops, > .namespace = rpc_sysfs_client_namespace, > }; > > +static struct kobj_type rpc_sysfs_xprt_switch_type = { > + .release = rpc_sysfs_xprt_switch_release, > + .sysfs_ops = &kobj_sysfs_ops, > + .namespace = rpc_sysfs_xprt_switch_namespace, > +}; > + > void rpc_sysfs_exit(void) > { > kobject_put(rpc_sunrpc_client_kobj); > + kobject_put(rpc_sunrpc_xprt_switch_kobj); > kset_unregister(rpc_sunrpc_kset); > } > > @@ -99,6 +128,28 @@ static struct rpc_sysfs_client > *rpc_sysfs_client_alloc(struct kobject *parent, > return NULL; > } > > +static struct rpc_sysfs_xprt_switch * > +rpc_sysfs_xprt_switch_alloc(struct kobject *parent, > + struct rpc_xprt_switch *xprt_switch, > + struct net *net, > + gfp_t gfp_flags) > +{ > + struct rpc_sysfs_xprt_switch *p; > + > + p = kzalloc(sizeof(*p), gfp_flags); > + if (p) { > + p->net = net; > + p->kobject.kset = rpc_sunrpc_kset; > + if (kobject_init_and_add(&p->kobject, > + &rpc_sysfs_xprt_switch_type, > + parent, "switch-%d", > + xprt_switch->xps_id) == 0) > + return p; > + kobject_put(&p->kobject); > + } > + return NULL; > +} > + > void rpc_sysfs_client_setup(struct rpc_clnt *clnt, struct net *net) > { > struct rpc_sysfs_client *rpc_client; > @@ -110,6 +161,28 @@ void rpc_sysfs_client_setup(struct rpc_clnt > *clnt, struct net *net) > } > } > > +void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch > *xprt_switch, > + struct rpc_xprt *xprt, > + gfp_t gfp_flags) > +{ > + struct rpc_sysfs_xprt_switch *rpc_xprt_switch; > + struct net *net; > + > + if (xprt_switch->xps_net) > + net = xprt_switch->xps_net; > + else > + net = xprt->xprt_net; > + rpc_xprt_switch = > + rpc_sysfs_xprt_switch_alloc(rpc_sunrpc_xprt_switch_ko > bj, > + xprt_switch, net, > gfp_flags); > + if (rpc_xprt_switch) { > + xprt_switch->xps_sysfs = rpc_xprt_switch; > + rpc_xprt_switch->xprt_switch = xprt_switch; > + rpc_xprt_switch->xprt = xprt; > + kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD); > + } > +} > + > void rpc_sysfs_client_destroy(struct rpc_clnt *clnt) > { > struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs; > @@ -121,3 +194,15 @@ void rpc_sysfs_client_destroy(struct rpc_clnt > *clnt) > clnt->cl_sysfs = NULL; > } > } > + > +void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch > *xprt_switch) > +{ > + struct rpc_sysfs_xprt_switch *rpc_xprt_switch = xprt_switch- > >xps_sysfs; > + > + if (rpc_xprt_switch) { > + kobject_uevent(&rpc_xprt_switch->kobject, > KOBJ_REMOVE); > + kobject_del(&rpc_xprt_switch->kobject); > + kobject_put(&rpc_xprt_switch->kobject); > + xprt_switch->xps_sysfs = NULL; > + } > +} > diff --git a/net/sunrpc/sysfs.h b/net/sunrpc/sysfs.h > index c46afc848993..52ec472bd4a9 100644 > --- a/net/sunrpc/sysfs.h > +++ b/net/sunrpc/sysfs.h > @@ -10,10 +10,20 @@ struct rpc_sysfs_client { > struct net *net; > }; > > +struct rpc_sysfs_xprt_switch { > + struct kobject kobject; > + struct net *net; > + struct rpc_xprt_switch *xprt_switch; > + struct rpc_xprt *xprt; > +}; > + > int rpc_sysfs_init(void); > void rpc_sysfs_exit(void); > > void rpc_sysfs_client_setup(struct rpc_clnt *clnt, struct net *net); > 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); > > #endif > diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c > index 4969a4c216f7..2d73a35df9ee 100644 > --- a/net/sunrpc/xprtmultipath.c > +++ b/net/sunrpc/xprtmultipath.c > @@ -19,6 +19,8 @@ > #include <linux/sunrpc/addr.h> > #include <linux/sunrpc/xprtmultipath.h> > > +#include "sysfs.h" > + > typedef struct rpc_xprt *(*xprt_switch_find_xprt_t)(struct > rpc_xprt_switch *xps, > const struct rpc_xprt *cur); > > @@ -133,6 +135,7 @@ struct rpc_xprt_switch *xprt_switch_alloc(struct > rpc_xprt *xprt, > xps->xps_net = NULL; > INIT_LIST_HEAD(&xps->xps_xprt_list); > xps->xps_iter_ops = &rpc_xprt_iter_singular; > + rpc_sysfs_xprt_switch_setup(xps, xprt, gfp_flags); > xprt_switch_add_xprt_locked(xps, xprt); > } > > @@ -161,6 +164,7 @@ static void xprt_switch_free(struct kref *kref) > struct rpc_xprt_switch, xps_kref); > > xprt_switch_free_entries(xps); > + rpc_sysfs_xprt_switch_destroy(xps); > xprt_switch_free_id(xps); > kfree_rcu(xps, xps_rcu); > }
diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h index ef95a6f18ccf..47b0a85cdcfa 100644 --- a/include/linux/sunrpc/xprtmultipath.h +++ b/include/linux/sunrpc/xprtmultipath.h @@ -24,6 +24,7 @@ struct rpc_xprt_switch { const struct rpc_xprt_iter_ops *xps_iter_ops; + void *xps_sysfs; struct rcu_head xps_rcu; }; diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c index d14d54f33c65..03ea6d3ace95 100644 --- a/net/sunrpc/sysfs.c +++ b/net/sunrpc/sysfs.c @@ -7,7 +7,7 @@ #include "sysfs.h" static struct kset *rpc_sunrpc_kset; -static struct kobject *rpc_sunrpc_client_kobj; +static struct kobject *rpc_sunrpc_client_kobj, *rpc_sunrpc_xprt_switch_kobj; static void rpc_sysfs_object_release(struct kobject *kobj) { @@ -47,13 +47,22 @@ int rpc_sysfs_init(void) rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, kernel_kobj); if (!rpc_sunrpc_kset) return -ENOMEM; - rpc_sunrpc_client_kobj = rpc_sysfs_object_alloc("client", rpc_sunrpc_kset, NULL); - if (!rpc_sunrpc_client_kobj) { - kset_unregister(rpc_sunrpc_kset); - rpc_sunrpc_client_kobj = NULL; - return -ENOMEM; - } + rpc_sunrpc_client_kobj = + rpc_sysfs_object_alloc("rpc-clients", rpc_sunrpc_kset, NULL); + if (!rpc_sunrpc_client_kobj) + goto err_client; + rpc_sunrpc_xprt_switch_kobj = + rpc_sysfs_object_alloc("xprt-switches", rpc_sunrpc_kset, NULL); + if (!rpc_sunrpc_xprt_switch_kobj) + goto err_switch; return 0; +err_switch: + kobject_put(rpc_sunrpc_client_kobj); + rpc_sunrpc_client_kobj = NULL; +err_client: + kset_unregister(rpc_sunrpc_kset); + rpc_sunrpc_kset = NULL; + return -ENOMEM; } static void rpc_sysfs_client_release(struct kobject *kobj) @@ -64,20 +73,40 @@ static void rpc_sysfs_client_release(struct kobject *kobj) kfree(c); } +static void rpc_sysfs_xprt_switch_release(struct kobject *kobj) +{ + struct rpc_sysfs_xprt_switch *xprt_switch; + + xprt_switch = container_of(kobj, struct rpc_sysfs_xprt_switch, kobject); + kfree(xprt_switch); +} + static const void *rpc_sysfs_client_namespace(struct kobject *kobj) { return container_of(kobj, struct rpc_sysfs_client, kobject)->net; } +static const void *rpc_sysfs_xprt_switch_namespace(struct kobject *kobj) +{ + return container_of(kobj, struct rpc_sysfs_xprt_switch, kobject)->net; +} + static struct kobj_type rpc_sysfs_client_type = { .release = rpc_sysfs_client_release, .sysfs_ops = &kobj_sysfs_ops, .namespace = rpc_sysfs_client_namespace, }; +static struct kobj_type rpc_sysfs_xprt_switch_type = { + .release = rpc_sysfs_xprt_switch_release, + .sysfs_ops = &kobj_sysfs_ops, + .namespace = rpc_sysfs_xprt_switch_namespace, +}; + void rpc_sysfs_exit(void) { kobject_put(rpc_sunrpc_client_kobj); + kobject_put(rpc_sunrpc_xprt_switch_kobj); kset_unregister(rpc_sunrpc_kset); } @@ -99,6 +128,28 @@ static struct rpc_sysfs_client *rpc_sysfs_client_alloc(struct kobject *parent, return NULL; } +static struct rpc_sysfs_xprt_switch * +rpc_sysfs_xprt_switch_alloc(struct kobject *parent, + struct rpc_xprt_switch *xprt_switch, + struct net *net, + gfp_t gfp_flags) +{ + struct rpc_sysfs_xprt_switch *p; + + p = kzalloc(sizeof(*p), gfp_flags); + if (p) { + p->net = net; + p->kobject.kset = rpc_sunrpc_kset; + if (kobject_init_and_add(&p->kobject, + &rpc_sysfs_xprt_switch_type, + parent, "switch-%d", + xprt_switch->xps_id) == 0) + return p; + kobject_put(&p->kobject); + } + return NULL; +} + void rpc_sysfs_client_setup(struct rpc_clnt *clnt, struct net *net) { struct rpc_sysfs_client *rpc_client; @@ -110,6 +161,28 @@ void rpc_sysfs_client_setup(struct rpc_clnt *clnt, struct net *net) } } +void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch, + struct rpc_xprt *xprt, + gfp_t gfp_flags) +{ + struct rpc_sysfs_xprt_switch *rpc_xprt_switch; + struct net *net; + + if (xprt_switch->xps_net) + net = xprt_switch->xps_net; + else + net = xprt->xprt_net; + rpc_xprt_switch = + rpc_sysfs_xprt_switch_alloc(rpc_sunrpc_xprt_switch_kobj, + xprt_switch, net, gfp_flags); + if (rpc_xprt_switch) { + xprt_switch->xps_sysfs = rpc_xprt_switch; + rpc_xprt_switch->xprt_switch = xprt_switch; + rpc_xprt_switch->xprt = xprt; + kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD); + } +} + void rpc_sysfs_client_destroy(struct rpc_clnt *clnt) { struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs; @@ -121,3 +194,15 @@ void rpc_sysfs_client_destroy(struct rpc_clnt *clnt) clnt->cl_sysfs = NULL; } } + +void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt_switch) +{ + struct rpc_sysfs_xprt_switch *rpc_xprt_switch = xprt_switch->xps_sysfs; + + if (rpc_xprt_switch) { + kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_REMOVE); + kobject_del(&rpc_xprt_switch->kobject); + kobject_put(&rpc_xprt_switch->kobject); + xprt_switch->xps_sysfs = NULL; + } +} diff --git a/net/sunrpc/sysfs.h b/net/sunrpc/sysfs.h index c46afc848993..52ec472bd4a9 100644 --- a/net/sunrpc/sysfs.h +++ b/net/sunrpc/sysfs.h @@ -10,10 +10,20 @@ struct rpc_sysfs_client { struct net *net; }; +struct rpc_sysfs_xprt_switch { + struct kobject kobject; + struct net *net; + struct rpc_xprt_switch *xprt_switch; + struct rpc_xprt *xprt; +}; + int rpc_sysfs_init(void); void rpc_sysfs_exit(void); void rpc_sysfs_client_setup(struct rpc_clnt *clnt, struct net *net); 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); #endif diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c index 4969a4c216f7..2d73a35df9ee 100644 --- a/net/sunrpc/xprtmultipath.c +++ b/net/sunrpc/xprtmultipath.c @@ -19,6 +19,8 @@ #include <linux/sunrpc/addr.h> #include <linux/sunrpc/xprtmultipath.h> +#include "sysfs.h" + typedef struct rpc_xprt *(*xprt_switch_find_xprt_t)(struct rpc_xprt_switch *xps, const struct rpc_xprt *cur); @@ -133,6 +135,7 @@ struct rpc_xprt_switch *xprt_switch_alloc(struct rpc_xprt *xprt, xps->xps_net = NULL; INIT_LIST_HEAD(&xps->xps_xprt_list); xps->xps_iter_ops = &rpc_xprt_iter_singular; + rpc_sysfs_xprt_switch_setup(xps, xprt, gfp_flags); xprt_switch_add_xprt_locked(xps, xprt); } @@ -161,6 +164,7 @@ static void xprt_switch_free(struct kref *kref) struct rpc_xprt_switch, xps_kref); xprt_switch_free_entries(xps); + rpc_sysfs_xprt_switch_destroy(xps); xprt_switch_free_id(xps); kfree_rcu(xps, xps_rcu); }