SUNRPC enforce creation of no more than max_connect xprts
authorOlga Kornievskaia <kolga@netapp.com>
Fri, 27 Aug 2021 18:37:18 +0000 (14:37 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Fri, 27 Aug 2021 20:37:29 +0000 (16:37 -0400)
If we are adding new transports via rpc_clnt_test_and_add_xprt()
then check if we've reached the limit. Currently only pnfs path
adds transports via that function but this is done in
preparation when the client would add new transports when
session trunking is detected. A warning is logged if the
limit is reached.

Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/client.c
include/linux/sunrpc/clnt.h
net/sunrpc/clnt.c

index 486dec59972bdfaf36f2992f3dc2700103fc1a21..23e165d5ec9cabfe7297f1f5158f73ef6e16f184 100644 (file)
@@ -541,6 +541,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
 
        clnt->cl_principal = clp->cl_principal;
        clp->cl_rpcclient = clnt;
+       clnt->cl_max_connect = clp->cl_max_connect;
        return 0;
 }
 EXPORT_SYMBOL_GPL(nfs_create_rpc_client);
index b2edd5fc2f0cb8393b253df692304cf9cd7d86e4..a4661646adc9c665ff0b9f5cceb5307ecb30a7d5 100644 (file)
@@ -82,6 +82,7 @@ struct rpc_clnt {
                struct work_struct      cl_work;
        };
        const struct cred       *cl_cred;
+       unsigned int            cl_max_connect; /* max number of transports not to the same IP */
 };
 
 /*
@@ -136,6 +137,7 @@ struct rpc_create_args {
        char                    *client_name;
        struct svc_xprt         *bc_xprt;       /* NFSv4.1 backchannel */
        const struct cred       *cred;
+       unsigned int            max_connect;
 };
 
 struct rpc_add_xprt_test {
index 451ac7d031db2f3586201bab38b6da540bc8d74c..f056ff93144427da8f9dcf5c74da2629b1f66b0a 100644 (file)
@@ -2787,6 +2787,15 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
        struct rpc_cb_add_xprt_calldata *data;
        struct rpc_task *task;
 
+       if (xps->xps_nunique_destaddr_xprts + 1 > clnt->cl_max_connect) {
+               rcu_read_lock();
+               pr_warn("SUNRPC: reached max allowed number (%d) did not add "
+                       "transport to server: %s\n", clnt->cl_max_connect,
+                       rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR));
+               rcu_read_unlock();
+               return -EINVAL;
+       }
+
        data = kmalloc(sizeof(*data), GFP_NOFS);
        if (!data)
                return -ENOMEM;