Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fda0ab41 authored by Andy Adamson's avatar Andy Adamson Committed by Anna Schumaker
Browse files

SUNRPC: rpc_clnt_add_xprt setup function for NFS layer



Use a setup function to call into the NFS layer to test an rpc_xprt
for session trunking so as to not leak the rpc_xprt_switch into
the nfs layer.

Search for the address in the rpc_xprt_switch first so as not to
put an unnecessary EXCHANGE_ID on the wire.

Signed-off-by: default avatarAndy Adamson <andros@netapp.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 39e5d2df
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -125,6 +125,13 @@ struct rpc_create_args {
	struct svc_xprt		*bc_xprt;	/* NFSv4.1 backchannel */
	struct svc_xprt		*bc_xprt;	/* NFSv4.1 backchannel */
};
};


struct rpc_add_xprt_test {
	int (*add_xprt_test)(struct rpc_clnt *,
		struct rpc_xprt *,
		void *calldata);
	void *data;
};

/* Values for "flags" field */
/* Values for "flags" field */
#define RPC_CLNT_CREATE_HARDRTRY	(1UL << 0)
#define RPC_CLNT_CREATE_HARDRTRY	(1UL << 0)
#define RPC_CLNT_CREATE_AUTOBIND	(1UL << 2)
#define RPC_CLNT_CREATE_AUTOBIND	(1UL << 2)
@@ -198,6 +205,11 @@ int rpc_clnt_add_xprt(struct rpc_clnt *, struct xprt_create *,
void		rpc_cap_max_reconnect_timeout(struct rpc_clnt *clnt,
void		rpc_cap_max_reconnect_timeout(struct rpc_clnt *clnt,
			unsigned long timeo);
			unsigned long timeo);


int		rpc_clnt_setup_test_and_add_xprt(struct rpc_clnt *,
			struct rpc_xprt_switch *,
			struct rpc_xprt *,
			void *);

const char *rpc_proc_name(const struct rpc_task *task);
const char *rpc_proc_name(const struct rpc_task *task);


void rpc_clnt_xprt_switch_put(struct rpc_clnt *);
void rpc_clnt_xprt_switch_put(struct rpc_clnt *);
+64 −0
Original line number Original line Diff line number Diff line
@@ -2613,6 +2613,70 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
}
}
EXPORT_SYMBOL_GPL(rpc_clnt_test_and_add_xprt);
EXPORT_SYMBOL_GPL(rpc_clnt_test_and_add_xprt);


/**
 * rpc_clnt_setup_test_and_add_xprt()
 *
 * This is an rpc_clnt_add_xprt setup() function which returns 1 so:
 *   1) caller of the test function must dereference the rpc_xprt_switch
 *   and the rpc_xprt.
 *   2) test function must call rpc_xprt_switch_add_xprt, usually in
 *   the rpc_call_done routine.
 *
 * Upon success (return of 1), the test function adds the new
 * transport to the rpc_clnt xprt switch
 *
 * @clnt: struct rpc_clnt to get the new transport
 * @xps:  the rpc_xprt_switch to hold the new transport
 * @xprt: the rpc_xprt to test
 * @data: a struct rpc_add_xprt_test pointer that holds the test function
 *        and test function call data
 */
int rpc_clnt_setup_test_and_add_xprt(struct rpc_clnt *clnt,
				     struct rpc_xprt_switch *xps,
				     struct rpc_xprt *xprt,
				     void *data)
{
	struct rpc_cred *cred;
	struct rpc_task *task;
	struct rpc_add_xprt_test *xtest = (struct rpc_add_xprt_test *)data;
	int status = -EADDRINUSE;

	xprt = xprt_get(xprt);
	xprt_switch_get(xps);

	if (rpc_xprt_switch_has_addr(xps, (struct sockaddr *)&xprt->addr))
		goto out_err;

	/* Test the connection */
	cred = authnull_ops.lookup_cred(NULL, NULL, 0);
	task = rpc_call_null_helper(clnt, xprt, cred,
				    RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
				    NULL, NULL);
	put_rpccred(cred);
	if (IS_ERR(task)) {
		status = PTR_ERR(task);
		goto out_err;
	}
	status = task->tk_status;
	rpc_put_task(task);

	if (status < 0)
		goto out_err;

	/* rpc_xprt_switch and rpc_xprt are deferrenced by add_xprt_test() */
	xtest->add_xprt_test(clnt, xprt, xtest->data);

	/* so that rpc_clnt_add_xprt does not call rpc_xprt_switch_add_xprt */
	return 1;
out_err:
	xprt_put(xprt);
	xprt_switch_put(xps);
	pr_info("RPC:   rpc_clnt_test_xprt failed: %d addr %s not added\n",
		status, xprt->address_strings[RPC_DISPLAY_ADDR]);
	return status;
}
EXPORT_SYMBOL_GPL(rpc_clnt_setup_test_and_add_xprt);

/**
/**
 * rpc_clnt_add_xprt - Add a new transport to a rpc_clnt
 * rpc_clnt_add_xprt - Add a new transport to a rpc_clnt
 * @clnt: pointer to struct rpc_clnt
 * @clnt: pointer to struct rpc_clnt