diff mbox series

[v3,08/13] sunrpc: add xprt_switch direcotry to sunrpc's sysfs

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

Commit Message

Olga Kornievskaia April 26, 2021, 5:19 p.m. UTC
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(-)

Comments

Trond Myklebust April 27, 2021, 12:55 p.m. UTC | #1
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 mbox series

Patch

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);
 }