Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFS pnfs data server multipath session trunking

Try all multipath addresses for a data server. The first address that
successfully connects and creates a session is the DS mount address.
All subsequent addresses are tested for session trunking and
added as aliases.

Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>

authored by

Andy Adamson and committed by
Anna Schumaker
04fa2c6b ad0849a7

+86 -14
+3
fs/nfs/internal.h
··· 572 572 extern int nfs41_walk_client_list(struct nfs_client *clp, 573 573 struct nfs_client **result, 574 574 struct rpc_cred *cred); 575 + extern int nfs4_test_session_trunk(struct rpc_clnt *, 576 + struct rpc_xprt *, 577 + void *); 575 578 576 579 static inline struct inode *nfs_igrab_and_active(struct inode *inode) 577 580 {
+6
fs/nfs/nfs4_fs.h
··· 59 59 struct nfs4_lock_state *); 60 60 struct nfs_seqid * 61 61 (*alloc_seqid)(struct nfs_seqid_counter *, gfp_t); 62 + int (*session_trunk)(struct rpc_clnt *, struct rpc_xprt *, void *); 62 63 const struct rpc_call_ops *call_sync_ops; 63 64 const struct nfs4_state_recovery_ops *reboot_recovery_ops; 64 65 const struct nfs4_state_recovery_ops *nograce_recovery_ops; ··· 202 201 int (*reclaim_complete)(struct nfs_client *, struct rpc_cred *); 203 202 int (*detect_trunking)(struct nfs_client *, struct nfs_client **, 204 203 struct rpc_cred *); 204 + }; 205 + 206 + struct nfs4_add_xprt_data { 207 + struct nfs_client *clp; 208 + struct rpc_cred *cred; 205 209 }; 206 210 207 211 struct nfs4_state_maintenance_ops {
+33
fs/nfs/nfs4proc.c
··· 7353 7353 return _nfs4_proc_exchange_id(clp, cred, SP4_NONE, NULL); 7354 7354 } 7355 7355 7356 + /** 7357 + * nfs4_test_session_trunk 7358 + * 7359 + * This is an add_xprt_test() test function called from 7360 + * rpc_clnt_setup_test_and_add_xprt. 7361 + * 7362 + * The rpc_xprt_switch is referrenced by rpc_clnt_setup_test_and_add_xprt 7363 + * and is dereferrenced in nfs4_exchange_id_release 7364 + * 7365 + * Upon success, add the new transport to the rpc_clnt 7366 + * 7367 + * @clnt: struct rpc_clnt to get new transport 7368 + * @xprt: the rpc_xprt to test 7369 + * @data: call data for _nfs4_proc_exchange_id. 7370 + */ 7371 + int nfs4_test_session_trunk(struct rpc_clnt *clnt, struct rpc_xprt *xprt, 7372 + void *data) 7373 + { 7374 + struct nfs4_add_xprt_data *adata = (struct nfs4_add_xprt_data *)data; 7375 + u32 sp4_how; 7376 + 7377 + dprintk("--> %s try %s\n", __func__, 7378 + xprt->address_strings[RPC_DISPLAY_ADDR]); 7379 + 7380 + sp4_how = (adata->clp->cl_sp4_flags == 0 ? SP4_NONE : SP4_MACH_CRED); 7381 + 7382 + /* Test connection for session trunking. Async exchange_id call */ 7383 + return _nfs4_proc_exchange_id(adata->clp, adata->cred, sp4_how, xprt); 7384 + } 7385 + EXPORT_SYMBOL_GPL(nfs4_test_session_trunk); 7386 + 7356 7387 static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, 7357 7388 struct rpc_cred *cred) 7358 7389 { ··· 8975 8944 .find_root_sec = nfs41_find_root_sec, 8976 8945 .free_lock_state = nfs41_free_lock_state, 8977 8946 .alloc_seqid = nfs_alloc_no_seqid, 8947 + .session_trunk = nfs4_test_session_trunk, 8978 8948 .call_sync_ops = &nfs41_call_sync_ops, 8979 8949 .reboot_recovery_ops = &nfs41_reboot_recovery_ops, 8980 8950 .nograce_recovery_ops = &nfs41_nograce_recovery_ops, ··· 9005 8973 .free_lock_state = nfs41_free_lock_state, 9006 8974 .call_sync_ops = &nfs41_call_sync_ops, 9007 8975 .alloc_seqid = nfs_alloc_no_seqid, 8976 + .session_trunk = nfs4_test_session_trunk, 9008 8977 .reboot_recovery_ops = &nfs41_reboot_recovery_ops, 9009 8978 .nograce_recovery_ops = &nfs41_nograce_recovery_ops, 9010 8979 .state_renewal_ops = &nfs41_state_renewal_ops,
+44 -14
fs/nfs/pnfs_nfs.c
··· 690 690 dprintk("%s: DS %s: trying address %s\n", 691 691 __func__, ds->ds_remotestr, da->da_remotestr); 692 692 693 - clp = nfs4_set_ds_client(mds_srv, 694 - (struct sockaddr *)&da->da_addr, 695 - da->da_addrlen, IPPROTO_TCP, 696 - timeo, retrans, minor_version, 697 - au_flavor); 698 - if (!IS_ERR(clp)) 699 - break; 693 + if (!IS_ERR(clp) && clp->cl_mvops->session_trunk) { 694 + struct xprt_create xprt_args = { 695 + .ident = XPRT_TRANSPORT_TCP, 696 + .net = clp->cl_net, 697 + .dstaddr = (struct sockaddr *)&da->da_addr, 698 + .addrlen = da->da_addrlen, 699 + .servername = clp->cl_hostname, 700 + }; 701 + struct nfs4_add_xprt_data xprtdata = { 702 + .clp = clp, 703 + .cred = nfs4_get_clid_cred(clp), 704 + }; 705 + struct rpc_add_xprt_test rpcdata = { 706 + .add_xprt_test = clp->cl_mvops->session_trunk, 707 + .data = &xprtdata, 708 + }; 709 + 710 + /** 711 + * Test this address for session trunking and 712 + * add as an alias 713 + */ 714 + rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args, 715 + rpc_clnt_setup_test_and_add_xprt, 716 + &rpcdata); 717 + if (xprtdata.cred) 718 + put_rpccred(xprtdata.cred); 719 + } else { 720 + clp = nfs4_set_ds_client(mds_srv, 721 + (struct sockaddr *)&da->da_addr, 722 + da->da_addrlen, IPPROTO_TCP, 723 + timeo, retrans, minor_version, 724 + au_flavor); 725 + if (IS_ERR(clp)) 726 + continue; 727 + 728 + status = nfs4_init_ds_session(clp, 729 + mds_srv->nfs_client->cl_lease_time); 730 + if (status) { 731 + nfs_put_client(clp); 732 + clp = ERR_PTR(-EIO); 733 + continue; 734 + } 735 + 736 + } 700 737 } 701 738 702 739 if (IS_ERR(clp)) { ··· 741 704 goto out; 742 705 } 743 706 744 - status = nfs4_init_ds_session(clp, mds_srv->nfs_client->cl_lease_time); 745 - if (status) 746 - goto out_put; 747 - 748 707 smp_wmb(); 749 708 ds->ds_clp = clp; 750 709 dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr); 751 710 out: 752 711 return status; 753 - out_put: 754 - nfs_put_client(clp); 755 - goto out; 756 712 } 757 713 758 714 /*