2022-02-28 20:42:21

by Olga Kornievskaia

[permalink] [raw]
Subject: [RFC PATCH 0/3] approach to deal with changes in trunking membership

From: Olga Kornievskaia <[email protected]>

A client needs to deal with changes to trunking group membership,
specially when a particular connection (endpoint) is no longer a part
of the trunking group membership. On such occasion, the attempts of
using such transports result in BAD_SESSION error as the endpoint no
longer shares session state with the others.

To deal with such situation, this series proposes to destroy trunking
connections when the client destroys the session.

Olga Kornievskaia (3):
SUNRPC provide accessible functions for offline remote xprt
functionality
SUNRPC add function to offline remote trunkable transports
NFSv4.1 destroy trunkable transport when destroying the session

fs/nfs/nfs4proc.c | 1 +
include/linux/sunrpc/clnt.h | 1 +
include/linux/sunrpc/xprt.h | 2 ++
net/sunrpc/clnt.c | 39 +++++++++++++++++++++++++++++++++++++
net/sunrpc/sysfs.c | 23 +++++-----------------
net/sunrpc/xprt.c | 25 ++++++++++++++++++++++++
6 files changed, 73 insertions(+), 18 deletions(-)

--
2.27.0


2022-02-28 20:42:24

by Olga Kornievskaia

[permalink] [raw]
Subject: [RFC PATCH 2/3] SUNRPC add function to offline remote trunkable transports

From: Olga Kornievskaia <[email protected]>

Interate thru available transports in the xprt_switch for all
trunkable transports offline and remote them.

Signed-off-by: Olga Kornievskaia <[email protected]>
---
include/linux/sunrpc/clnt.h | 1 +
net/sunrpc/clnt.c | 39 +++++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 267b7aeaf1a6..273e507c5c87 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -233,6 +233,7 @@ int rpc_clnt_setup_test_and_add_xprt(struct rpc_clnt *,
struct rpc_xprt_switch *,
struct rpc_xprt *,
void *);
+void rpc_clnt_destroy_trunked_xprts(struct rpc_clnt *);

const char *rpc_proc_name(const struct rpc_task *task);

diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 97165a545cb3..6bb317caa128 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -2946,6 +2946,45 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
}
EXPORT_SYMBOL_GPL(rpc_clnt_add_xprt);

+static int rpc_xprt_destroy(struct rpc_clnt *clnt, struct rpc_xprt *xprt, void *data)
+{
+ struct rpc_xprt *main_xprt;
+ struct rpc_xprt_switch *xps;
+ int err = 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));
+ err = rpc_cmp_addr_port((struct sockaddr *)&xprt->addr,
+ (struct sockaddr *)&main_xprt->addr);
+ rcu_read_unlock();
+ xprt_put(main_xprt);
+ if (err)
+ goto out;
+
+ if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
+ err = -EINTR;
+ goto out;
+ }
+ xprt_set_offline_locked(xprt, xps);
+ xprt_delete_locked(xprt, xps);
+
+ xprt_release_write(xprt, NULL);
+out:
+ xprt_put(xprt);
+ xprt_switch_put(xps);
+ return err;
+}
+
+void rpc_clnt_destroy_trunked_xprts(struct rpc_clnt *clnt)
+{
+ rpc_clnt_iterate_for_each_xprt(clnt, rpc_xprt_destroy, NULL);
+ return;
+}
+EXPORT_SYMBOL_GPL(rpc_clnt_destroy_trunked_xprts);
+
struct connect_timeout_data {
unsigned long connect_timeout;
unsigned long reconnect_timeout;
--
2.27.0

2022-02-28 20:43:02

by Olga Kornievskaia

[permalink] [raw]
Subject: [RFC PATCH 1/3] SUNRPC provide accessible functions for offline remote xprt functionality

From: Olga Kornievskaia <[email protected]>

Re-arrange the code that make offline transport and delete transport
callable functions.

Signed-off-by: Olga Kornievskaia <[email protected]>
---
include/linux/sunrpc/xprt.h | 2 ++
net/sunrpc/sysfs.c | 23 +++++------------------
net/sunrpc/xprt.c | 25 +++++++++++++++++++++++++
3 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 955ea4d7af0b..201c58991d4a 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -502,4 +502,6 @@ static inline int xprt_test_and_set_binding(struct rpc_xprt *xprt)
return test_and_set_bit(XPRT_BINDING, &xprt->state);
}

+void xprt_set_offline_locked(struct rpc_xprt *xprt, struct rpc_xprt_switch *xps);
+void xprt_delete_locked(struct rpc_xprt *xprt, struct rpc_xprt_switch *xps);
#endif /* _LINUX_SUNRPC_XPRT_H */
diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c
index 05c758da6a92..4a6488dd1608 100644
--- a/net/sunrpc/sysfs.c
+++ b/net/sunrpc/sysfs.c
@@ -6,6 +6,7 @@
#include <linux/kobject.h>
#include <linux/sunrpc/addr.h>
#include <linux/sunrpc/xprtsock.h>
+//#include <linux/sunrpc/xprt.h>

#include "sysfs.h"

@@ -312,11 +313,7 @@ static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj,
goto release_tasks;
}
if (offline) {
- if (!test_and_set_bit(XPRT_OFFLINE, &xprt->state)) {
- spin_lock(&xps->xps_lock);
- xps->xps_nactive--;
- spin_unlock(&xps->xps_lock);
- }
+ xprt_set_offline_locked(xprt, xps);
} else if (online) {
if (test_and_clear_bit(XPRT_OFFLINE, &xprt->state)) {
spin_lock(&xps->xps_lock);
@@ -324,20 +321,10 @@ static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj,
spin_unlock(&xps->xps_lock);
}
} else if (remove) {
- if (test_bit(XPRT_OFFLINE, &xprt->state)) {
- if (!test_and_set_bit(XPRT_REMOVE, &xprt->state)) {
- xprt_force_disconnect(xprt);
- if (test_bit(XPRT_CONNECTED, &xprt->state)) {
- if (!xprt->sending.qlen &&
- !xprt->pending.qlen &&
- !xprt->backlog.qlen &&
- !atomic_long_read(&xprt->queuelen))
- rpc_xprt_switch_remove_xprt(xps, xprt);
- }
- }
- } else {
+ if (test_bit(XPRT_OFFLINE, &xprt->state))
+ xprt_delete_locked(xprt, xps);
+ else
count = -EINVAL;
- }
}

release_tasks:
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 9f0025e0742c..16d4435b61b4 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -2151,3 +2151,28 @@ void xprt_put(struct rpc_xprt *xprt)
kref_put(&xprt->kref, xprt_destroy_kref);
}
EXPORT_SYMBOL_GPL(xprt_put);
+
+void xprt_set_offline_locked(struct rpc_xprt *xprt, struct rpc_xprt_switch *xps)
+{
+ if (!test_and_set_bit(XPRT_OFFLINE, &xprt->state)) {
+ spin_lock(&xps->xps_lock);
+ xps->xps_nactive--;
+ spin_unlock(&xps->xps_lock);
+ }
+}
+EXPORT_SYMBOL(xprt_set_offline_locked);
+
+void xprt_delete_locked(struct rpc_xprt *xprt, struct rpc_xprt_switch *xps)
+{
+ if (test_and_set_bit(XPRT_REMOVE, &xprt->state))
+ return;
+
+ xprt_force_disconnect(xprt);
+ if (!test_bit(XPRT_CONNECTED, &xprt->state))
+ return;
+
+ if (!xprt->sending.qlen && !xprt->pending.qlen &&
+ !xprt->backlog.qlen && !atomic_long_read(&xprt->queuelen))
+ rpc_xprt_switch_remove_xprt(xps, xprt);
+}
+EXPORT_SYMBOL(xprt_delete_locked);
--
2.27.0

2022-02-28 20:43:31

by Olga Kornievskaia

[permalink] [raw]
Subject: [RFC PATCH 3/3] NFSv4.1 destroy trunkable transport when destroying the session

From: Olga Kornievskaia <[email protected]>

Trunking connections to different IPs represending the same server
are initially discovered and associated with a session. It stands
to reason that once the session is destroyed those connections
might no longer be representing the same server for the newly
created session.

This patch proposed that when the sesssion is destroyed, also iterate
thru available transports and terminate any trunkable connections.
Main transport and nconnect connections are not effected.

Signed-off-by: Olga Kornievskaia <[email protected]>
---
fs/nfs/nfs4proc.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 73a9b6de666c..08597e2e0571 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -9193,6 +9193,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session,
if (status)
dprintk("NFS: Got error %d from the server on DESTROY_SESSION. "
"Session has been destroyed regardless...\n", status);
+ rpc_clnt_destroy_trunked_xprts(session->clp->cl_rpcclient);
return status;
}

--
2.27.0