sunrpc: Add a sysfs file for adding a new xprt
authorAnna Schumaker <anna.schumaker@oracle.com>
Fri, 7 Feb 2025 20:42:24 +0000 (15:42 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Fri, 21 Mar 2025 13:34:53 +0000 (09:34 -0400)
Writing to this file will clone the 'main' xprt of an xprt_switch and
add it to be used as an additional connection.

--

Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
v3: Replace call to xprt_iter_get_xprt() with xprt_iter_get_next()
Link: https://lore.kernel.org/r/20250207204225.594002-5-anna@kernel.org
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
include/linux/sunrpc/xprtmultipath.h
net/sunrpc/sysfs.c
net/sunrpc/xprtmultipath.c

index e411368cdacfa3c0daf5dcfa71ec5f1e9b7151c1..e4db5022fe92b35377aa9a9199dd111b84c95aa1 100644 (file)
@@ -56,6 +56,7 @@ extern void rpc_xprt_switch_add_xprt(struct rpc_xprt_switch *xps,
                struct rpc_xprt *xprt);
 extern void rpc_xprt_switch_remove_xprt(struct rpc_xprt_switch *xps,
                struct rpc_xprt *xprt, bool offline);
+extern struct rpc_xprt *rpc_xprt_switch_get_main_xprt(struct rpc_xprt_switch *xps);
 
 extern void xprt_iter_init(struct rpc_xprt_iter *xpi,
                struct rpc_xprt_switch *xps);
index dcd579eab50af0afac68ee18c69c46be05cbc5af..8fd1975f2fe8090836ae53ee34f0072308404780 100644 (file)
@@ -305,6 +305,55 @@ static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj,
        return ret;
 }
 
+static ssize_t rpc_sysfs_xprt_switch_add_xprt_show(struct kobject *kobj,
+                                                  struct kobj_attribute *attr,
+                                                  char *buf)
+{
+       return sprintf(buf, "# add one xprt to this xprt_switch\n");
+}
+
+static ssize_t rpc_sysfs_xprt_switch_add_xprt_store(struct kobject *kobj,
+                                                   struct kobj_attribute *attr,
+                                                   const char *buf, size_t count)
+{
+       struct rpc_xprt_switch *xprt_switch =
+               rpc_sysfs_xprt_switch_kobj_get_xprt(kobj);
+       struct xprt_create xprt_create_args;
+       struct rpc_xprt *xprt, *new;
+
+       if (!xprt_switch)
+               return 0;
+
+       xprt = rpc_xprt_switch_get_main_xprt(xprt_switch);
+       if (!xprt)
+               goto out;
+
+       xprt_create_args.ident = xprt->xprt_class->ident;
+       xprt_create_args.net = xprt->xprt_net;
+       xprt_create_args.dstaddr = (struct sockaddr *)&xprt->addr;
+       xprt_create_args.addrlen = xprt->addrlen;
+       xprt_create_args.servername = xprt->servername;
+       xprt_create_args.bc_xprt = xprt->bc_xprt;
+       xprt_create_args.xprtsec = xprt->xprtsec;
+       xprt_create_args.connect_timeout = xprt->connect_timeout;
+       xprt_create_args.reconnect_timeout = xprt->max_reconnect_timeout;
+
+       new = xprt_create_transport(&xprt_create_args);
+       if (IS_ERR_OR_NULL(new)) {
+               count = PTR_ERR(new);
+               goto out_put_xprt;
+       }
+
+       rpc_xprt_switch_add_xprt(xprt_switch, new);
+       xprt_put(new);
+
+out_put_xprt:
+       xprt_put(xprt);
+out:
+       xprt_switch_put(xprt_switch);
+       return count;
+}
+
 static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj,
                                            struct kobj_attribute *attr,
                                            const char *buf, size_t count)
@@ -523,8 +572,13 @@ ATTRIBUTE_GROUPS(rpc_sysfs_xprt);
 static struct kobj_attribute rpc_sysfs_xprt_switch_info =
        __ATTR(xprt_switch_info, 0444, rpc_sysfs_xprt_switch_info_show, NULL);
 
+static struct kobj_attribute rpc_sysfs_xprt_switch_add_xprt =
+       __ATTR(add_xprt, 0644, rpc_sysfs_xprt_switch_add_xprt_show,
+               rpc_sysfs_xprt_switch_add_xprt_store);
+
 static struct attribute *rpc_sysfs_xprt_switch_attrs[] = {
        &rpc_sysfs_xprt_switch_info.attr,
+       &rpc_sysfs_xprt_switch_add_xprt.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(rpc_sysfs_xprt_switch);
index 7e98d4dd9f10aa51a078906abe054e3be75b8f94..4c5e08b0aa649e5f7462acfda9fd83a3b135c907 100644 (file)
@@ -92,6 +92,27 @@ void rpc_xprt_switch_remove_xprt(struct rpc_xprt_switch *xps,
        xprt_put(xprt);
 }
 
+/**
+ * rpc_xprt_switch_get_main_xprt - Get the 'main' xprt for an xprt switch.
+ * @xps: pointer to struct rpc_xprt_switch.
+ */
+struct rpc_xprt *rpc_xprt_switch_get_main_xprt(struct rpc_xprt_switch *xps)
+{
+       struct rpc_xprt_iter xpi;
+       struct rpc_xprt *xprt;
+
+       xprt_iter_init_listall(&xpi, xps);
+
+       xprt = xprt_iter_get_next(&xpi);
+       while (xprt && !xprt->main) {
+               xprt_put(xprt);
+               xprt = xprt_iter_get_next(&xpi);
+       }
+
+       xprt_iter_destroy(&xpi);
+       return xprt;
+}
+
 static DEFINE_IDA(rpc_xprtswitch_ids);
 
 void xprt_multipath_cleanup_ids(void)