On Mon, 2022-06-20 at 11:24 -0400, Olga Kornievskaia wrote: > From: Olga Kornievskaia <kolga@xxxxxxxxxx> > > For only offline transports, attempt to check connectivity via > a NULL call and, if that succeeds, call a provided session trunking > detection function. > > Signed-off-by: Olga Kornievskaia <kolga@xxxxxxxxxx> > --- > fs/nfs/nfs4proc.c | 2 +- > include/linux/sunrpc/clnt.h | 3 ++- > net/sunrpc/clnt.c | 47 +++++++++++++++++++++++++++++++++-- > -- > net/sunrpc/debugfs.c | 3 ++- > net/sunrpc/stats.c | 2 +- > 5 files changed, 48 insertions(+), 9 deletions(-) > > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c > index 152da2bc5100..00778f351283 100644 > --- a/fs/nfs/nfs4proc.c > +++ b/fs/nfs/nfs4proc.c > @@ -8533,7 +8533,7 @@ int nfs4_proc_bind_conn_to_session(struct > nfs_client *clp, const struct cred *cr > .cred = cred, > }; > return rpc_clnt_iterate_for_each_xprt(clp->cl_rpcclient, > NULL, > - nfs4_proc_bind_conn_to_session_callback, > &data); > + nfs4_proc_bind_conn_to_session_callback, > &data, false); > } > > /* > diff --git a/include/linux/sunrpc/clnt.h > b/include/linux/sunrpc/clnt.h > index ac1024da86c5..a0160b83d4a4 100644 > --- a/include/linux/sunrpc/clnt.h > +++ b/include/linux/sunrpc/clnt.h > @@ -215,7 +215,7 @@ int rpc_localaddr(struct rpc_clnt *, > struct sockaddr *, size_t); > int rpc_clnt_iterate_for_each_xprt(struct rpc_clnt *clnt, > int (*setup)(struct rpc_clnt *, struct > rpc_xprt_iter *), > int (*fn)(struct rpc_clnt *, struct rpc_xprt > *, void *), > - void *data); > + void *data, bool do_rewind); > > int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt, > struct rpc_xprt_switch *xps, > @@ -236,6 +236,7 @@ > int rpc_clnt_setup_test_and_add_xprt(struct rpc_clnt *, > struct rpc_xprt *, > void *); > void rpc_clnt_manage_trunked_xprts(struct rpc_clnt *, void > *); > +void rpc_probe_trunked_xprts(struct rpc_clnt *, void *); > > const char *rpc_proc_name(const struct rpc_task *task); > > diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c > index 6b04b29bf842..348d0772c91d 100644 > --- a/net/sunrpc/clnt.c > +++ b/net/sunrpc/clnt.c > @@ -830,7 +830,7 @@ int rpc_clnt_xprt_iter_offline_init(struct > rpc_clnt *clnt, > int rpc_clnt_iterate_for_each_xprt(struct rpc_clnt *clnt, > int (*setup)(struct rpc_clnt *, struct rpc_xprt_iter > *), > int (*fn)(struct rpc_clnt *, struct rpc_xprt *, void > *), > - void *data) > + void *data, bool do_rewind) > { > struct rpc_xprt_iter xpi; > int ret; > @@ -850,6 +850,9 @@ int rpc_clnt_iterate_for_each_xprt(struct > rpc_clnt *clnt, > xprt_put(xprt); > if (ret < 0) > break; > + > + if (do_rewind) > + xprt_iter_rewind(&xpi); This really needs to be another separate function. You are not iterating over each xprt here, you are always looking at the first valid entry. > } > xprt_iter_destroy(&xpi); > return ret; > @@ -3032,6 +3035,40 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt, > } > EXPORT_SYMBOL_GPL(rpc_clnt_add_xprt); > > +static int rpc_xprt_probe_trunked(struct rpc_clnt *clnt, > + struct rpc_xprt *xprt, > + void *data) > +{ > + struct rpc_xprt_switch *xps; > + struct rpc_xprt *main_xprt; > + int status = 0; > + > + xprt_get(xprt); > + > + rcu_read_lock(); > + main_xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); > + xps = xprt_switch_get(rcu_dereference(clnt- > >cl_xpi.xpi_xpswitch)); > + status = rpc_cmp_addr_port((struct sockaddr *)&xprt->addr, > + (struct sockaddr *)&main_xprt->addr); > + rcu_read_unlock(); > + xprt_put(main_xprt); > + if (status || !test_bit(XPRT_OFFLINE, &xprt->state)) > + goto out; > + > + status = rpc_clnt_add_xprt_helper(clnt, xprt, data); > +out: > + xprt_put(xprt); > + xprt_switch_put(xps); > + return status; > +} > + > +void rpc_probe_trunked_xprts(struct rpc_clnt *clnt, void *data) 'data' is not a 'void *'. You patch 447574a510fc ("SUNRPC restructure rpc_clnt_setup_test_and_add_xprt") means that only a 'struct rpc_add_xprt_test' argument is allowed here. > +{ > + rpc_clnt_iterate_for_each_xprt(clnt, > rpc_clnt_xprt_iter_offline_init, > + rpc_xprt_probe_trunked, data, true); > +} > +EXPORT_SYMBOL_GPL(rpc_probe_trunked_xprts); > + > static int rpc_xprt_offline_destroy(struct rpc_clnt *clnt, > struct rpc_xprt *xprt, > void *data) > @@ -3071,7 +3108,7 @@ static int rpc_xprt_offline_destroy(struct > rpc_clnt *clnt, > void rpc_clnt_manage_trunked_xprts(struct rpc_clnt *clnt, void > *data) > { > rpc_clnt_iterate_for_each_xprt(clnt, NULL, > rpc_xprt_offline_destroy, > - data); > + data, false); > } > EXPORT_SYMBOL_GPL(rpc_clnt_manage_trunked_xprts); > > @@ -3105,7 +3142,7 @@ rpc_set_connect_timeout(struct rpc_clnt *clnt, > }; > rpc_clnt_iterate_for_each_xprt(clnt, NULL, > rpc_xprt_set_connect_timeout, > - &timeout); > + &timeout, false); > } > EXPORT_SYMBOL_GPL(rpc_set_connect_timeout); > > @@ -3228,7 +3265,7 @@ rpc_clnt_swap_activate(struct rpc_clnt *clnt) > clnt = clnt->cl_parent; > if (atomic_inc_return(&clnt->cl_swapper) == 1) > return rpc_clnt_iterate_for_each_xprt(clnt, NULL, > - rpc_clnt_swap_activate_callback, > NULL); > + rpc_clnt_swap_activate_callback, > NULL, false); > return 0; > } > EXPORT_SYMBOL_GPL(rpc_clnt_swap_activate); > @@ -3247,7 +3284,7 @@ rpc_clnt_swap_deactivate(struct rpc_clnt *clnt) > { > if (atomic_dec_if_positive(&clnt->cl_swapper) == 0) > rpc_clnt_iterate_for_each_xprt(clnt, NULL, > - rpc_clnt_swap_deactivate_callback, > NULL); > + rpc_clnt_swap_deactivate_callback, > NULL, false); > } > EXPORT_SYMBOL_GPL(rpc_clnt_swap_deactivate); > #endif /* CONFIG_SUNRPC_SWAP */ > diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c > index ab60b4d3deb2..9c700bad1ec5 100644 > --- a/net/sunrpc/debugfs.c > +++ b/net/sunrpc/debugfs.c > @@ -160,7 +160,8 @@ rpc_clnt_debugfs_register(struct rpc_clnt *clnt) > debugfs_create_file("tasks", S_IFREG | 0400, clnt- > >cl_debugfs, clnt, > &tasks_fops); > > - rpc_clnt_iterate_for_each_xprt(clnt, NULL, do_xprt_debugfs, > &xprtnum); > + rpc_clnt_iterate_for_each_xprt(clnt, NULL, do_xprt_debugfs, > &xprtnum, > + false); > } > > void > diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c > index e50f73a4aca5..60e2d738a8f1 100644 > --- a/net/sunrpc/stats.c > +++ b/net/sunrpc/stats.c > @@ -258,7 +258,7 @@ void rpc_clnt_show_stats(struct seq_file *seq, > struct rpc_clnt *clnt) > seq_printf(seq, "p/v: %u/%u (%s)\n", > clnt->cl_prog, clnt->cl_vers, clnt- > >cl_program->name); > > - rpc_clnt_iterate_for_each_xprt(clnt, NULL, do_print_stats, > seq); > + rpc_clnt_iterate_for_each_xprt(clnt, NULL, do_print_stats, > seq, false); > > seq_printf(seq, "\tper-op statistics\n"); > for (op = 0; op < maxproc; op++) { -- Trond Myklebust Linux NFS client maintainer, Hammerspace trond.myklebust@xxxxxxxxxxxxxxx