Re: [PATCH Version 4 08/10] NFS test and add multipaths for session trunking

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> On May 18, 2016, at 2:23 PM, Schumaker, Anna <Anna.Schumaker@xxxxxxxxxx> wrote:
> 
> Hi Andy,
> 
> On 05/11/2016 03:08 PM, andros@xxxxxxxxxx wrote:
>> From: Andy Adamson <andros@xxxxxxxxxx>
>> 
>> Test the multipath addresses returned by nfs4_get_pseudofs_replicas
>> for session trunking.
>> 
>> Signed-off-by: Andy Adamson <andros@xxxxxxxxxx>
>> ---
>> fs/nfs/nfs4_fs.h           |   7 ++++
>> fs/nfs/nfs4proc.c          | 100 ++++++++++++++++++++++++++++++++++++++++++++-
>> net/sunrpc/xprtmultipath.c |   3 ++
>> 3 files changed, 109 insertions(+), 1 deletion(-)
>> 
> 
> <snip>
> 
>> 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
>> @@ -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);
> 
> I'm curious at what point during _nfs4_proc_exchange_id() these might get released?

I was concerned about the client tearing down the server mount whose rpc_clnt struct hosts the xprt_switch (or otherwise tearing down the rpc_clnt) while the _nfs4_proc_exchange_id is in flight.

AFAICS that is the same concern that the other use of rpc_clnt_add_xprt() in _nfs4_pnfs_v3_ds_connect() has.

rpc_clnt_test_and_add_xprt () references the xprt_switch and the xprt, and rpc_cb_add_xprt_release() dereferences them.

—>Andy


> 
> Thanks,
> Anna
> 
>> +
>> +	/* 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
>> 
> 

��.n��������+%������w��{.n�����{��w���jg��������ݢj����G�������j:+v���w�m������w�������h�����٥




[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux