NFSv4.1 test and add 4.1 trunking transport
authorOlga Kornievskaia <kolga@netapp.com>
Thu, 9 Dec 2021 19:53:35 +0000 (14:53 -0500)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Thu, 13 Jan 2022 14:36:58 +0000 (09:36 -0500)
For each location returned in FS_LOCATION query, establish a
transport to the server, send EXCHANGE_ID and test for trunking,
if successful, add the transport to the exiting client.

Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/nfs4proc.c

index fc4629d2d2abde84f5de67d1d07b7cd818a31a58..b18f31b2c9e7c9c38cff1a90d6736cc26d2d16cb 100644 (file)
@@ -3935,6 +3935,56 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
        return err;
 }
 
+static void test_fs_location_for_trunking(struct nfs4_fs_location *location,
+                                         struct nfs_client *clp,
+                                         struct nfs_server *server)
+{
+       int i;
+
+       for (i = 0; i < location->nservers; i++) {
+               struct nfs4_string *srv_loc = &location->servers[i];
+               struct sockaddr addr;
+               size_t addrlen;
+               struct xprt_create xprt_args = {
+                       .ident = 0,
+                       .net = clp->cl_net,
+               };
+               struct nfs4_add_xprt_data xprtdata = {
+                       .clp = clp,
+               };
+               struct rpc_add_xprt_test rpcdata = {
+                       .add_xprt_test = clp->cl_mvops->session_trunk,
+                       .data = &xprtdata,
+               };
+               char *servername = NULL;
+
+               if (!srv_loc->len)
+                       continue;
+
+               addrlen = nfs_parse_server_name(srv_loc->data, srv_loc->len,
+                                               &addr, sizeof(addr),
+                                               clp->cl_net, server->port);
+               if (!addrlen)
+                       return;
+               xprt_args.dstaddr = &addr;
+               xprt_args.addrlen = addrlen;
+               servername = kmalloc(srv_loc->len + 1, GFP_KERNEL);
+               if (!servername)
+                       return;
+               memcpy(servername, srv_loc->data, srv_loc->len);
+               servername[srv_loc->len] = '\0';
+               xprt_args.servername = servername;
+
+               xprtdata.cred = nfs4_get_clid_cred(clp);
+               rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args,
+                                 rpc_clnt_setup_test_and_add_xprt,
+                                 &rpcdata);
+               if (xprtdata.cred)
+                       put_cred(xprtdata.cred);
+               kfree(servername);
+       }
+}
+
 static int _nfs4_discover_trunking(struct nfs_server *server,
                                   struct nfs_fh *fhandle)
 {
@@ -3944,7 +3994,7 @@ static int _nfs4_discover_trunking(struct nfs_server *server,
        struct nfs_client *clp = server->nfs_client;
        const struct nfs4_state_maintenance_ops *ops =
                clp->cl_mvops->state_renewal_ops;
-       int status = -ENOMEM;
+       int status = -ENOMEM, i;
 
        cred = ops->get_state_renewal_cred(clp);
        if (cred == NULL) {
@@ -3962,6 +4012,10 @@ static int _nfs4_discover_trunking(struct nfs_server *server,
                                         cred);
        if (status)
                goto out;
+
+       for (i = 0; i < locations->nlocations; i++)
+               test_fs_location_for_trunking(&locations->locations[i], clp,
+                                             server);
 out:
        if (page)
                __free_page(page);