From patchwork Wed May 11 19:08:23 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Adamson X-Patchwork-Id: 9073971 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A131FBF29F for ; Wed, 11 May 2016 19:09:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9397920114 for ; Wed, 11 May 2016 19:09:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4ACEF2017D for ; Wed, 11 May 2016 19:09:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752343AbcEKTI5 (ORCPT ); Wed, 11 May 2016 15:08:57 -0400 Received: from mx144.netapp.com ([216.240.21.25]:33164 "EHLO mx144.netapp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752474AbcEKTI4 (ORCPT ); Wed, 11 May 2016 15:08:56 -0400 X-IronPort-AV: E=Sophos;i="5.24,608,1455004800"; d="scan'208";a="115702825" Received: from vmwexchts02-prd.hq.netapp.com ([10.122.105.23]) by mx144-out.netapp.com with ESMTP; 11 May 2016 12:08:56 -0700 Received: from smtp1.corp.netapp.com (10.57.156.124) by VMWEXCHTS02-PRD.hq.netapp.com (10.122.105.23) with Microsoft SMTP Server id 15.0.1156.6; Wed, 11 May 2016 12:08:55 -0700 Received: from localhost.localdomain (andros-new.vpn.netapp.com [10.55.76.232]) by smtp1.corp.netapp.com (8.13.1/8.13.1/NTAP-1.6) with ESMTP id u4BJ8lX7028221; Wed, 11 May 2016 12:08:54 -0700 (PDT) From: To: CC: , , , Andy Adamson Subject: [PATCH Version 4 08/10] NFS test and add multipaths for session trunking Date: Wed, 11 May 2016 15:08:23 -0400 Message-ID: <1462993705-14673-9-git-send-email-andros@netapp.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1462993705-14673-1-git-send-email-andros@netapp.com> References: <1462993705-14673-1-git-send-email-andros@netapp.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-8.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Andy Adamson Test the multipath addresses returned by nfs4_get_pseudofs_replicas for session trunking. Signed-off-by: Andy Adamson --- fs/nfs/nfs4_fs.h | 7 ++++ fs/nfs/nfs4proc.c | 100 ++++++++++++++++++++++++++++++++++++++++++++- net/sunrpc/xprtmultipath.c | 3 ++ 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index ff8cfcd..e886aa7 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -59,6 +59,8 @@ struct nfs4_minor_version_ops { struct nfs4_lock_state *); struct nfs_seqid * (*alloc_seqid)(struct nfs_seqid_counter *, gfp_t); + int (*session_trunk)(struct rpc_clnt *, struct rpc_xprt_switch *, + struct rpc_xprt *, void *); const struct rpc_call_ops *call_sync_ops; const struct nfs4_state_recovery_ops *reboot_recovery_ops; const struct nfs4_state_recovery_ops *nograce_recovery_ops; @@ -214,6 +216,11 @@ struct nfs4_mig_recovery_ops { int (*fsid_present)(struct inode *, struct rpc_cred *); }; +struct nfs4_add_xprt_data { + struct nfs_client *clp; + struct rpc_cred *cred; +}; + extern const struct dentry_operations nfs4_dentry_operations; /* dir.c */ diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8263ee8..827ae51 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -3303,6 +3304,59 @@ static int nfs4_proc_fs_locations_probe(struct nfs_server *server, return err; } +/** + * Test the multipath addresses returned by nfs4_get_pseudofs_replicas + * for session trunking. + * + * Add session trunking aliases to the cl_rpcclient + */ +void nfs4_test_multipath(struct nfs4_fs_locations *locations, + struct nfs_client *clp) +{ + struct nfs4_add_xprt_data xprtdata = { + .clp = clp, + }; + int i; + + if (!clp->cl_mvops->session_trunk || locations == NULL || + locations->nlocations <= 0) + return; + + xprtdata.cred = nfs4_get_clid_cred(clp); + + for (i = 0; i < locations->nlocations; i++) { + struct nfs4_fs_location *loc = &locations->locations[i]; + int i; + + for (i = 0; i < loc->nservers; i++) { + struct nfs4_string *server = &loc->servers[i]; + struct sockaddr_storage addr; + size_t addrlen; + struct xprt_create xprt_args = { + .ident = XPRT_TRANSPORT_TCP, + .net = clp->cl_net, + }; + + addrlen = rpc_pton(clp->cl_net, server->data, + server->len, (struct sockaddr *)&addr, + sizeof(addr)); + + xprt_args.dstaddr = (struct sockaddr *)&addr; + xprt_args.addrlen = addrlen; + xprt_args.servername = server->data; + + /** + * Check for session trunking. Add this address as + * an alias if session trunking is permitted. + */ + rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args, + clp->cl_mvops->session_trunk, + &xprtdata); + } + } + if (xprtdata.cred) + put_rpccred(xprtdata.cred); +} /** * Probe the pseudo filesystem for an fs_locations replicas list. @@ -3330,7 +3384,8 @@ void nfs4_get_pseudofs_replicas(struct nfs_server *server, if (status != 0) goto out; - /* test replicas for session trunking here */ + /* test replicas for session trunking */ + nfs4_test_multipath(locations, server->nfs_client); out: if (page) __free_page(page); @@ -7291,6 +7346,47 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) return _nfs4_proc_exchange_id(clp, cred, SP4_NONE, NULL); } +/** + * nfs4_test_session_trunk - Test for session trunking with a + * synchronous exchange_id call. Upon success, add a new transport + * to the rpc_clnt + * + * @clnt: struct rpc_clnt to get new transport + * @xps: the rpc_xprt_switch to hold the new transport + * @xprt: the rpc_xprt to test + * @data: call data for _nfs4_proc_exchange_id. + * + */ +int nfs4_test_session_trunk(struct rpc_clnt *clnt, struct rpc_xprt_switch *xps, + struct rpc_xprt *xprt, void *data) +{ + struct nfs4_add_xprt_data *xdata = (struct nfs4_add_xprt_data *)data; + u32 sp4_how; + int status; + + sp4_how = (xdata->clp->cl_sp4_flags == 0 ? SP4_NONE : SP4_MACH_CRED); + + /* Ensure these stick around for the rpc call */ + xps = xprt_switch_get(xps); + xprt = xprt_get(xprt); + + /* Sync call */ + status = _nfs4_proc_exchange_id(xdata->clp, xdata->cred, sp4_how, xprt); + + xprt_put(xprt); + xprt_switch_put(xps); + + if (status) + pr_info("NFS: %s: Session trunking failed for %s status %d\n", + xdata->clp->cl_hostname, + xprt->address_strings[RPC_DISPLAY_ADDR], status); + else + pr_info("NFS: %s: Session trunking succeeded for %s\n", + xdata->clp->cl_hostname, + xprt->address_strings[RPC_DISPLAY_ADDR]); + return status; +} + static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, struct rpc_cred *cred) { @@ -8882,6 +8978,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { .find_root_sec = nfs41_find_root_sec, .free_lock_state = nfs41_free_lock_state, .alloc_seqid = nfs_alloc_no_seqid, + .session_trunk = nfs4_test_session_trunk, .call_sync_ops = &nfs41_call_sync_ops, .reboot_recovery_ops = &nfs41_reboot_recovery_ops, .nograce_recovery_ops = &nfs41_nograce_recovery_ops, @@ -8910,6 +9007,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { .free_lock_state = nfs41_free_lock_state, .call_sync_ops = &nfs41_call_sync_ops, .alloc_seqid = nfs_alloc_no_seqid, + .session_trunk = nfs4_test_session_trunk, .reboot_recovery_ops = &nfs41_reboot_recovery_ops, .nograce_recovery_ops = &nfs41_nograce_recovery_ops, .state_renewal_ops = &nfs41_state_renewal_ops, diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c index e7fd769..360f64c 100644 --- a/net/sunrpc/xprtmultipath.c +++ b/net/sunrpc/xprtmultipath.c @@ -53,6 +53,7 @@ void rpc_xprt_switch_add_xprt(struct rpc_xprt_switch *xps, xprt_switch_add_xprt_locked(xps, xprt); spin_unlock(&xps->xps_lock); } +EXPORT_SYMBOL_GPL(rpc_xprt_switch_add_xprt); static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps, struct rpc_xprt *xprt) @@ -145,6 +146,7 @@ struct rpc_xprt_switch *xprt_switch_get(struct rpc_xprt_switch *xps) return xps; return NULL; } +EXPORT_SYMBOL_GPL(xprt_switch_get); /** * xprt_switch_put - Release a reference to a rpc_xprt_switch @@ -157,6 +159,7 @@ void xprt_switch_put(struct rpc_xprt_switch *xps) if (xps != NULL) kref_put(&xps->xps_kref, xprt_switch_free); } +EXPORT_SYMBOL_GPL(xprt_switch_put); /** * rpc_xprt_switch_set_roundrobin - Set a round-robin policy on rpc_xprt_switch