NFSv4 introduce max_connect mount options
authorOlga Kornievskaia <kolga@netapp.com>
Fri, 27 Aug 2021 18:37:17 +0000 (14:37 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Fri, 27 Aug 2021 20:37:17 +0000 (16:37 -0400)
This option will control up to how many xprts can the client
establish to the server with a distinct address (that means
nconnect connections are not counted towards this new limit).
This patch is setting up nfs structures to keeep track of the
max_connect limit (does not enforce it).

The default value is kept at 1 so that no current mounts that
don't want any additional connections would be effected. The
maximum value is set at 16.

Mounts to DS are not limited to default value of 1 but instead
set to the maximum default value of 16 (NFS_MAX_TRANSPORTS).

Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/client.c
fs/nfs/fs_context.c
fs/nfs/internal.h
fs/nfs/nfs4client.c
fs/nfs/super.c
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h

index 330f657..486dec5 100644 (file)
@@ -179,6 +179,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
 
        clp->cl_proto = cl_init->proto;
        clp->cl_nconnect = cl_init->nconnect;
+       clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1;
        clp->cl_net = get_net(cl_init->net);
 
        clp->cl_principal = "*";
index d95c9a3..0d444a9 100644 (file)
@@ -60,6 +60,7 @@ enum nfs_param {
        Opt_mountvers,
        Opt_namelen,
        Opt_nconnect,
+       Opt_max_connect,
        Opt_port,
        Opt_posix,
        Opt_proto,
@@ -158,6 +159,7 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = {
        fsparam_u32   ("mountvers",     Opt_mountvers),
        fsparam_u32   ("namlen",        Opt_namelen),
        fsparam_u32   ("nconnect",      Opt_nconnect),
+       fsparam_u32   ("max_connect",   Opt_max_connect),
        fsparam_string("nfsvers",       Opt_vers),
        fsparam_u32   ("port",          Opt_port),
        fsparam_flag_no("posix",        Opt_posix),
@@ -770,6 +772,11 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
                        goto out_of_bounds;
                ctx->nfs_server.nconnect = result.uint_32;
                break;
+       case Opt_max_connect:
+               if (result.uint_32 < 1 || result.uint_32 > NFS_MAX_TRANSPORTS)
+                       goto out_of_bounds;
+               ctx->nfs_server.max_connect = result.uint_32;
+               break;
        case Opt_lookupcache:
                switch (result.uint_32) {
                case Opt_lookupcache_all:
index a36af04..66fc936 100644 (file)
@@ -67,6 +67,7 @@ struct nfs_client_initdata {
        int proto;
        u32 minorversion;
        unsigned int nconnect;
+       unsigned int max_connect;
        struct net *net;
        const struct rpc_timeout *timeparms;
        const struct cred *cred;
@@ -121,6 +122,7 @@ struct nfs_fs_context {
                int                     port;
                unsigned short          protocol;
                unsigned short          nconnect;
+               unsigned short          max_connect;
                unsigned short          export_path_len;
        } nfs_server;
 
index 28431ac..270caa1 100644 (file)
@@ -865,6 +865,7 @@ static int nfs4_set_client(struct nfs_server *server,
                const char *ip_addr,
                int proto, const struct rpc_timeout *timeparms,
                u32 minorversion, unsigned int nconnect,
+               unsigned int max_connect,
                struct net *net)
 {
        struct nfs_client_initdata cl_init = {
@@ -883,6 +884,8 @@ static int nfs4_set_client(struct nfs_server *server,
 
        if (minorversion == 0)
                __set_bit(NFS_CS_REUSEPORT, &cl_init.init_flags);
+       else
+               cl_init.max_connect = max_connect;
        if (proto == XPRT_TRANSPORT_TCP)
                cl_init.nconnect = nconnect;
 
@@ -952,8 +955,10 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
                return ERR_PTR(-EINVAL);
        cl_init.hostname = buf;
 
-       if (mds_clp->cl_nconnect > 1 && ds_proto == XPRT_TRANSPORT_TCP)
+       if (mds_clp->cl_nconnect > 1 && ds_proto == XPRT_TRANSPORT_TCP) {
                cl_init.nconnect = mds_clp->cl_nconnect;
+               cl_init.max_connect = NFS_MAX_TRANSPORTS;
+       }
 
        if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
                __set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
@@ -1122,6 +1127,7 @@ static int nfs4_init_server(struct nfs_server *server, struct fs_context *fc)
                                &timeparms,
                                ctx->minorversion,
                                ctx->nfs_server.nconnect,
+                               ctx->nfs_server.max_connect,
                                fc->net_ns);
        if (error < 0)
                return error;
@@ -1211,6 +1217,7 @@ struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
                                parent_server->client->cl_timeout,
                                parent_client->cl_mvops->minor_version,
                                parent_client->cl_nconnect,
+                               parent_client->cl_max_connect,
                                parent_client->cl_net);
        if (!error)
                goto init_server;
@@ -1226,6 +1233,7 @@ struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
                                parent_server->client->cl_timeout,
                                parent_client->cl_mvops->minor_version,
                                parent_client->cl_nconnect,
+                               parent_client->cl_max_connect,
                                parent_client->cl_net);
        if (error < 0)
                goto error;
@@ -1323,7 +1331,7 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
        error = nfs4_set_client(server, hostname, sap, salen, buf,
                                clp->cl_proto, clnt->cl_timeout,
                                clp->cl_minorversion,
-                               clp->cl_nconnect, net);
+                               clp->cl_nconnect, clp->cl_max_connect, net);
        clear_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
        if (error != 0) {
                nfs_server_insert_lists(server);
index fe58525..e65c834 100644 (file)
@@ -480,6 +480,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
        if (clp->cl_nconnect > 0)
                seq_printf(m, ",nconnect=%u", clp->cl_nconnect);
        if (version == 4) {
+               if (clp->cl_max_connect > 1)
+                       seq_printf(m, ",max_connect=%u", clp->cl_max_connect);
                if (nfss->port != NFS_PORT)
                        seq_printf(m, ",port=%u", nfss->port);
        } else
index ce64745..b9a8b92 100644 (file)
 #include <linux/mempool.h>
 
 /*
+ * These are the default for number of transports to different server IPs
+ */
+#define NFS_MAX_TRANSPORTS 16
+
+/*
  * These are the default flags for swap requests
  */
 #define NFS_RPC_SWAPFLAGS              (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS)
index d71a0e9..2a9acbf 100644 (file)
@@ -62,6 +62,7 @@ struct nfs_client {
 
        u32                     cl_minorversion;/* NFSv4 minorversion */
        unsigned int            cl_nconnect;    /* Number of connections */
+       unsigned int            cl_max_connect; /* max number of xprts allowed */
        const char *            cl_principal;  /* used for machine cred */
 
 #if IS_ENABLED(CONFIG_NFS_V4)