Message ID | 20250108213632.260498-4-anna@kernel.org (mailing list archive) |
---|---|
State | Handled Elsewhere |
Headers | show |
Series | NFS & SUNRPC Sysfs Improvements | expand |
On 8 Jan 2025, at 16:36, Anna Schumaker wrote: > From: Anna Schumaker <anna.schumaker@oracle.com> > > Writing to this file will clone the 'main' xprt of an xprt_switch and > add it to be used as an additional connection. I like this too! I'd prefer it was ./add_xprt instead of ./xprt_switch_add_xprt, since the directory already gives the context that you're operating on the xprt_switch. After happily adding a bunch of xprts, I did have to look up the source to re-learn how to remove them which wasn't obvious from the sysfs structure. You have to write "offline", then "remove" to the xprt_state file. This made me wish there was just a ./xprt-N-tcp/del_xprt that would do both of those.. .. and in stark contrast to my previous preference on less dynamic sysfs, I think that the ./del_xprt shouldn't appear for the "main" xprt (since you can't remove/delete them). .. all just thoughts, these look good! > > Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> > --- > include/linux/sunrpc/xprtmultipath.h | 1 + > net/sunrpc/sysfs.c | 54 ++++++++++++++++++++++++++++ > net/sunrpc/xprtmultipath.c | 21 +++++++++++ > 3 files changed, 76 insertions(+) > > diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h > index c0514c684b2c..c827c6ef0bc5 100644 > --- a/include/linux/sunrpc/xprtmultipath.h > +++ b/include/linux/sunrpc/xprtmultipath.h > @@ -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); > diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c > index dc3b7cd70000..ce7dae140770 100644 > --- a/net/sunrpc/sysfs.c > +++ b/net/sunrpc/sysfs.c > @@ -250,6 +250,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) > @@ -451,8 +500,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(xprt_switch_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); > diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c > index 720d3ba742ec..a07b81ce93c3 100644 > --- a/net/sunrpc/xprtmultipath.c > +++ b/net/sunrpc/xprtmultipath.c > @@ -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_xprt(&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) > -- > 2.47.1
On 1/9/25 10:10 AM, Benjamin Coddington wrote: > On 8 Jan 2025, at 16:36, Anna Schumaker wrote: > >> From: Anna Schumaker <anna.schumaker@oracle.com> >> >> Writing to this file will clone the 'main' xprt of an xprt_switch and >> add it to be used as an additional connection. > > I like this too! I'd prefer it was ./add_xprt instead of > ./xprt_switch_add_xprt, since the directory already gives the context that > you're operating on the xprt_switch. I'd prefer that too, actually. I don't know what I was thinking going with the longer name, and I've made that change for v2. > > After happily adding a bunch of xprts, I did have to look up the source to > re-learn how to remove them which wasn't obvious from the sysfs structure. > You have to write "offline", then "remove" to the xprt_state file. This > made me wish there was just a ./xprt-N-tcp/del_xprt that would do both of > those.. `rpcctl xprt remove` will already do both of those in one step, if that helps. But I can look at adding in 'del_xprt' if you still think it would help. > > .. and in stark contrast to my previous preference on less dynamic sysfs, I > think that the ./del_xprt shouldn't appear for the "main" xprt (since you > can't remove/delete them). > > .. all just thoughts, these look good! Thanks! Anna > >> >> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> >> --- >> include/linux/sunrpc/xprtmultipath.h | 1 + >> net/sunrpc/sysfs.c | 54 ++++++++++++++++++++++++++++ >> net/sunrpc/xprtmultipath.c | 21 +++++++++++ >> 3 files changed, 76 insertions(+) >> >> diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h >> index c0514c684b2c..c827c6ef0bc5 100644 >> --- a/include/linux/sunrpc/xprtmultipath.h >> +++ b/include/linux/sunrpc/xprtmultipath.h >> @@ -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); >> diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c >> index dc3b7cd70000..ce7dae140770 100644 >> --- a/net/sunrpc/sysfs.c >> +++ b/net/sunrpc/sysfs.c >> @@ -250,6 +250,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) >> @@ -451,8 +500,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(xprt_switch_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); >> diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c >> index 720d3ba742ec..a07b81ce93c3 100644 >> --- a/net/sunrpc/xprtmultipath.c >> +++ b/net/sunrpc/xprtmultipath.c >> @@ -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_xprt(&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) >> -- >> 2.47.1 >
On Wed, Jan 8, 2025 at 4:36 PM Anna Schumaker <anna@kernel.org> wrote: > > From: Anna Schumaker <anna.schumaker@oracle.com> > > Writing to this file will clone the 'main' xprt of an xprt_switch and > add it to be used as an additional connection. > > Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> > --- > include/linux/sunrpc/xprtmultipath.h | 1 + > net/sunrpc/sysfs.c | 54 ++++++++++++++++++++++++++++ > net/sunrpc/xprtmultipath.c | 21 +++++++++++ > 3 files changed, 76 insertions(+) > > diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h > index c0514c684b2c..c827c6ef0bc5 100644 > --- a/include/linux/sunrpc/xprtmultipath.h > +++ b/include/linux/sunrpc/xprtmultipath.h > @@ -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); > diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c > index dc3b7cd70000..ce7dae140770 100644 > --- a/net/sunrpc/sysfs.c > +++ b/net/sunrpc/sysfs.c > @@ -250,6 +250,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); Before adding a new transport don't we need to check that we are not at or over the limit of how many connections we currently have (not over nconnect limit and/or over the session trunking limit)? > + 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) > @@ -451,8 +500,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(xprt_switch_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); > diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c > index 720d3ba742ec..a07b81ce93c3 100644 > --- a/net/sunrpc/xprtmultipath.c > +++ b/net/sunrpc/xprtmultipath.c > @@ -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_xprt(&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) > -- > 2.47.1 > >
Hi Olga, On 1/13/25 9:10 AM, Olga Kornievskaia wrote: > On Wed, Jan 8, 2025 at 4:36 PM Anna Schumaker <anna@kernel.org> wrote: >> >> From: Anna Schumaker <anna.schumaker@oracle.com> >> >> Writing to this file will clone the 'main' xprt of an xprt_switch and >> add it to be used as an additional connection. >> >> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> >> --- >> include/linux/sunrpc/xprtmultipath.h | 1 + >> net/sunrpc/sysfs.c | 54 ++++++++++++++++++++++++++++ >> net/sunrpc/xprtmultipath.c | 21 +++++++++++ >> 3 files changed, 76 insertions(+) >> >> diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h >> index c0514c684b2c..c827c6ef0bc5 100644 >> --- a/include/linux/sunrpc/xprtmultipath.h >> +++ b/include/linux/sunrpc/xprtmultipath.h >> @@ -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); >> diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c >> index dc3b7cd70000..ce7dae140770 100644 >> --- a/net/sunrpc/sysfs.c >> +++ b/net/sunrpc/sysfs.c >> @@ -250,6 +250,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); > > Before adding a new transport don't we need to check that we are not > at or over the limit of how many connections we currently have (not > over nconnect limit and/or over the session trunking limit)? That's a good thought, but I'm not really seeing how to do that from inside the sunrpc code. Those are configuration values for the NFS client, and don't get passed down to sunrpc, so sunrpc has no knownledge of them. If you think that'll be a problem, I can look into adding those checks for the next posting. Anna > >> + 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) >> @@ -451,8 +500,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(xprt_switch_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); >> diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c >> index 720d3ba742ec..a07b81ce93c3 100644 >> --- a/net/sunrpc/xprtmultipath.c >> +++ b/net/sunrpc/xprtmultipath.c >> @@ -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_xprt(&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) >> -- >> 2.47.1 >> >>
On Mon, Jan 13, 2025 at 4:52 PM Anna Schumaker <anna.schumaker@oracle.com> wrote: > > Hi Olga, > > On 1/13/25 9:10 AM, Olga Kornievskaia wrote: > > On Wed, Jan 8, 2025 at 4:36 PM Anna Schumaker <anna@kernel.org> wrote: > >> > >> From: Anna Schumaker <anna.schumaker@oracle.com> > >> > >> Writing to this file will clone the 'main' xprt of an xprt_switch and > >> add it to be used as an additional connection. > >> > >> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> > >> --- > >> include/linux/sunrpc/xprtmultipath.h | 1 + > >> net/sunrpc/sysfs.c | 54 ++++++++++++++++++++++++++++ > >> net/sunrpc/xprtmultipath.c | 21 +++++++++++ > >> 3 files changed, 76 insertions(+) > >> > >> diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h > >> index c0514c684b2c..c827c6ef0bc5 100644 > >> --- a/include/linux/sunrpc/xprtmultipath.h > >> +++ b/include/linux/sunrpc/xprtmultipath.h > >> @@ -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); > >> diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c > >> index dc3b7cd70000..ce7dae140770 100644 > >> --- a/net/sunrpc/sysfs.c > >> +++ b/net/sunrpc/sysfs.c > >> @@ -250,6 +250,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); > > > > Before adding a new transport don't we need to check that we are not > > at or over the limit of how many connections we currently have (not > > over nconnect limit and/or over the session trunking limit)? > > That's a good thought, but I'm not really seeing how to do that from inside the sunrpc code. Those are configuration values for the NFS client, and don't get passed down to sunrpc, so sunrpc has no knownledge of them. If you think that'll be a problem, I can look into adding those checks for the next posting. Seems incorrect to allow going over a limit we enforce at the nfs layer? So I think it is a problem. The other thing that sticks out. Given that this is version agnostic what happens for v3/v4 and the bc_xprt? > > Anna > > > > >> + 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) > >> @@ -451,8 +500,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(xprt_switch_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); > >> diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c > >> index 720d3ba742ec..a07b81ce93c3 100644 > >> --- a/net/sunrpc/xprtmultipath.c > >> +++ b/net/sunrpc/xprtmultipath.c > >> @@ -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_xprt(&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) > >> -- > >> 2.47.1 > >> > >> >
Hi Anna, kernel test robot noticed the following build warnings: https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Anna-Schumaker/NFS-Add-implid-to-sysfs/20250109-053732 base: git://git.linux-nfs.org/projects/trondmy/linux-nfs.git linux-next patch link: https://lore.kernel.org/r/20250108213632.260498-4-anna%40kernel.org patch subject: [PATCH 3/3] sunrpc: Add a sysfs file for adding a new xprt config: x86_64-randconfig-r073-20250119 (https://download.01.org/0day-ci/archive/20250120/202501200000.40Rg2rc6-lkp@intel.com/config) compiler: gcc-12 (Debian 12.2.0-14) 12.2.0 If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Reported-by: Dan Carpenter <dan.carpenter@linaro.org> | Closes: https://lore.kernel.org/r/202501200000.40Rg2rc6-lkp@intel.com/ New smatch warnings: net/sunrpc/sysfs.c:288 rpc_sysfs_xprt_switch_add_xprt_store() warn: passing zero to 'PTR_ERR' vim +/PTR_ERR +288 net/sunrpc/sysfs.c 2b155d9a088aee Anna Schumaker 2025-01-08 260 static ssize_t rpc_sysfs_xprt_switch_add_xprt_store(struct kobject *kobj, 2b155d9a088aee Anna Schumaker 2025-01-08 261 struct kobj_attribute *attr, 2b155d9a088aee Anna Schumaker 2025-01-08 262 const char *buf, size_t count) 2b155d9a088aee Anna Schumaker 2025-01-08 263 { 2b155d9a088aee Anna Schumaker 2025-01-08 264 struct rpc_xprt_switch *xprt_switch = 2b155d9a088aee Anna Schumaker 2025-01-08 265 rpc_sysfs_xprt_switch_kobj_get_xprt(kobj); 2b155d9a088aee Anna Schumaker 2025-01-08 266 struct xprt_create xprt_create_args; 2b155d9a088aee Anna Schumaker 2025-01-08 267 struct rpc_xprt *xprt, *new; 2b155d9a088aee Anna Schumaker 2025-01-08 268 2b155d9a088aee Anna Schumaker 2025-01-08 269 if (!xprt_switch) 2b155d9a088aee Anna Schumaker 2025-01-08 270 return 0; 2b155d9a088aee Anna Schumaker 2025-01-08 271 2b155d9a088aee Anna Schumaker 2025-01-08 272 xprt = rpc_xprt_switch_get_main_xprt(xprt_switch); 2b155d9a088aee Anna Schumaker 2025-01-08 273 if (!xprt) 2b155d9a088aee Anna Schumaker 2025-01-08 274 goto out; 2b155d9a088aee Anna Schumaker 2025-01-08 275 2b155d9a088aee Anna Schumaker 2025-01-08 276 xprt_create_args.ident = xprt->xprt_class->ident; 2b155d9a088aee Anna Schumaker 2025-01-08 277 xprt_create_args.net = xprt->xprt_net; 2b155d9a088aee Anna Schumaker 2025-01-08 278 xprt_create_args.dstaddr = (struct sockaddr *)&xprt->addr; 2b155d9a088aee Anna Schumaker 2025-01-08 279 xprt_create_args.addrlen = xprt->addrlen; 2b155d9a088aee Anna Schumaker 2025-01-08 280 xprt_create_args.servername = xprt->servername; 2b155d9a088aee Anna Schumaker 2025-01-08 281 xprt_create_args.bc_xprt = xprt->bc_xprt; 2b155d9a088aee Anna Schumaker 2025-01-08 282 xprt_create_args.xprtsec = xprt->xprtsec; 2b155d9a088aee Anna Schumaker 2025-01-08 283 xprt_create_args.connect_timeout = xprt->connect_timeout; 2b155d9a088aee Anna Schumaker 2025-01-08 284 xprt_create_args.reconnect_timeout = xprt->max_reconnect_timeout; 2b155d9a088aee Anna Schumaker 2025-01-08 285 2b155d9a088aee Anna Schumaker 2025-01-08 286 new = xprt_create_transport(&xprt_create_args); 2b155d9a088aee Anna Schumaker 2025-01-08 287 if (IS_ERR_OR_NULL(new)) { This should just be if (IS_ERR(new)) {, otherwise we end up with a nonsense debate about whether impossible NULL returns should be handled as a error or a success. 2b155d9a088aee Anna Schumaker 2025-01-08 @288 count = PTR_ERR(new); 2b155d9a088aee Anna Schumaker 2025-01-08 289 goto out_put_xprt; 2b155d9a088aee Anna Schumaker 2025-01-08 290 } 2b155d9a088aee Anna Schumaker 2025-01-08 291 2b155d9a088aee Anna Schumaker 2025-01-08 292 rpc_xprt_switch_add_xprt(xprt_switch, new); 2b155d9a088aee Anna Schumaker 2025-01-08 293 xprt_put(new); 2b155d9a088aee Anna Schumaker 2025-01-08 294 2b155d9a088aee Anna Schumaker 2025-01-08 295 out_put_xprt: 2b155d9a088aee Anna Schumaker 2025-01-08 296 xprt_put(xprt); 2b155d9a088aee Anna Schumaker 2025-01-08 297 out: 2b155d9a088aee Anna Schumaker 2025-01-08 298 xprt_switch_put(xprt_switch); 2b155d9a088aee Anna Schumaker 2025-01-08 299 return count; 2b155d9a088aee Anna Schumaker 2025-01-08 300 }
diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h index c0514c684b2c..c827c6ef0bc5 100644 --- a/include/linux/sunrpc/xprtmultipath.h +++ b/include/linux/sunrpc/xprtmultipath.h @@ -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); diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c index dc3b7cd70000..ce7dae140770 100644 --- a/net/sunrpc/sysfs.c +++ b/net/sunrpc/sysfs.c @@ -250,6 +250,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) @@ -451,8 +500,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(xprt_switch_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); diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c index 720d3ba742ec..a07b81ce93c3 100644 --- a/net/sunrpc/xprtmultipath.c +++ b/net/sunrpc/xprtmultipath.c @@ -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_xprt(&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)