Merge branch 'multipath_tcp'
This commit is contained in:
@@ -528,6 +528,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
|
||||
.bc_xprt = args->bc_xprt,
|
||||
};
|
||||
char servername[48];
|
||||
struct rpc_clnt *clnt;
|
||||
int i;
|
||||
|
||||
if (args->bc_xprt) {
|
||||
WARN_ON_ONCE(!(args->protocol & XPRT_TRANSPORT_BC));
|
||||
@@ -590,7 +592,15 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
|
||||
if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT)
|
||||
xprt->resvport = 0;
|
||||
|
||||
return rpc_create_xprt(args, xprt);
|
||||
clnt = rpc_create_xprt(args, xprt);
|
||||
if (IS_ERR(clnt) || args->nconnect <= 1)
|
||||
return clnt;
|
||||
|
||||
for (i = 0; i < args->nconnect - 1; i++) {
|
||||
if (rpc_clnt_add_xprt(clnt, &xprtargs, NULL, NULL) < 0)
|
||||
break;
|
||||
}
|
||||
return clnt;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpc_create);
|
||||
|
||||
@@ -968,13 +978,65 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpc_bind_new_program);
|
||||
|
||||
static struct rpc_xprt *
|
||||
rpc_task_get_xprt(struct rpc_clnt *clnt)
|
||||
{
|
||||
struct rpc_xprt_switch *xps;
|
||||
struct rpc_xprt *xprt= xprt_iter_get_next(&clnt->cl_xpi);
|
||||
|
||||
if (!xprt)
|
||||
return NULL;
|
||||
rcu_read_lock();
|
||||
xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
|
||||
atomic_long_inc(&xps->xps_queuelen);
|
||||
rcu_read_unlock();
|
||||
atomic_long_inc(&xprt->queuelen);
|
||||
|
||||
return xprt;
|
||||
}
|
||||
|
||||
static struct rpc_xprt *
|
||||
rpc_task_get_first_xprt(struct rpc_clnt *clnt)
|
||||
{
|
||||
struct rpc_xprt_switch *xps;
|
||||
struct rpc_xprt *xprt;
|
||||
|
||||
rcu_read_lock();
|
||||
xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
|
||||
if (xprt) {
|
||||
atomic_long_inc(&xprt->queuelen);
|
||||
xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
|
||||
atomic_long_inc(&xps->xps_queuelen);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return xprt;
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_task_release_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
|
||||
{
|
||||
struct rpc_xprt_switch *xps;
|
||||
|
||||
atomic_long_dec(&xprt->queuelen);
|
||||
rcu_read_lock();
|
||||
xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
|
||||
atomic_long_dec(&xps->xps_queuelen);
|
||||
rcu_read_unlock();
|
||||
|
||||
xprt_put(xprt);
|
||||
}
|
||||
|
||||
void rpc_task_release_transport(struct rpc_task *task)
|
||||
{
|
||||
struct rpc_xprt *xprt = task->tk_xprt;
|
||||
|
||||
if (xprt) {
|
||||
task->tk_xprt = NULL;
|
||||
xprt_put(xprt);
|
||||
if (task->tk_client)
|
||||
rpc_task_release_xprt(task->tk_client, xprt);
|
||||
else
|
||||
xprt_put(xprt);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpc_task_release_transport);
|
||||
@@ -983,6 +1045,7 @@ void rpc_task_release_client(struct rpc_task *task)
|
||||
{
|
||||
struct rpc_clnt *clnt = task->tk_client;
|
||||
|
||||
rpc_task_release_transport(task);
|
||||
if (clnt != NULL) {
|
||||
/* Remove from client task list */
|
||||
spin_lock(&clnt->cl_lock);
|
||||
@@ -992,14 +1055,17 @@ void rpc_task_release_client(struct rpc_task *task)
|
||||
|
||||
rpc_release_client(clnt);
|
||||
}
|
||||
rpc_task_release_transport(task);
|
||||
}
|
||||
|
||||
static
|
||||
void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
|
||||
{
|
||||
if (!task->tk_xprt)
|
||||
task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi);
|
||||
if (task->tk_xprt)
|
||||
return;
|
||||
if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN)
|
||||
task->tk_xprt = rpc_task_get_first_xprt(clnt);
|
||||
else
|
||||
task->tk_xprt = rpc_task_get_xprt(clnt);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -2696,6 +2762,10 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
|
||||
return -ENOMEM;
|
||||
data->xps = xprt_switch_get(xps);
|
||||
data->xprt = xprt_get(xprt);
|
||||
if (rpc_xprt_switch_has_addr(data->xps, (struct sockaddr *)&xprt->addr)) {
|
||||
rpc_cb_add_xprt_release(data);
|
||||
goto success;
|
||||
}
|
||||
|
||||
task = rpc_call_null_helper(clnt, xprt, NULL,
|
||||
RPC_TASK_SOFT|RPC_TASK_SOFTCONN|RPC_TASK_ASYNC|RPC_TASK_NULLCREDS,
|
||||
@@ -2703,6 +2773,7 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
|
||||
if (IS_ERR(task))
|
||||
return PTR_ERR(task);
|
||||
rpc_put_task(task);
|
||||
success:
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpc_clnt_test_and_add_xprt);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/**
|
||||
/*
|
||||
* debugfs interface for sunrpc
|
||||
*
|
||||
* (c) 2014 Jeff Layton <jlayton@primarydata.com>
|
||||
@@ -118,12 +118,38 @@ static const struct file_operations tasks_fops = {
|
||||
.release = tasks_release,
|
||||
};
|
||||
|
||||
static int do_xprt_debugfs(struct rpc_clnt *clnt, struct rpc_xprt *xprt, void *numv)
|
||||
{
|
||||
int len;
|
||||
char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */
|
||||
char link[9]; /* enough for 8 hex digits + NULL */
|
||||
int *nump = numv;
|
||||
|
||||
if (IS_ERR_OR_NULL(xprt->debugfs))
|
||||
return 0;
|
||||
len = snprintf(name, sizeof(name), "../../rpc_xprt/%s",
|
||||
xprt->debugfs->d_name.name);
|
||||
if (len > sizeof(name))
|
||||
return -1;
|
||||
if (*nump == 0)
|
||||
strcpy(link, "xprt");
|
||||
else {
|
||||
len = snprintf(link, sizeof(link), "xprt%d", *nump);
|
||||
if (len > sizeof(link))
|
||||
return -1;
|
||||
}
|
||||
if (!debugfs_create_symlink(link, clnt->cl_debugfs, name))
|
||||
return -1;
|
||||
(*nump)++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
|
||||
{
|
||||
int len;
|
||||
char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */
|
||||
struct rpc_xprt *xprt;
|
||||
char name[9]; /* enough for 8 hex digits + NULL */
|
||||
int xprtnum = 0;
|
||||
|
||||
/* Already registered? */
|
||||
if (clnt->cl_debugfs || !rpc_clnt_dir)
|
||||
@@ -143,21 +169,7 @@ rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
|
||||
clnt, &tasks_fops))
|
||||
goto out_err;
|
||||
|
||||
rcu_read_lock();
|
||||
xprt = rcu_dereference(clnt->cl_xprt);
|
||||
/* no "debugfs" dentry? Don't bother with the symlink. */
|
||||
if (IS_ERR_OR_NULL(xprt->debugfs)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
len = snprintf(name, sizeof(name), "../../rpc_xprt/%s",
|
||||
xprt->debugfs->d_name.name);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (len >= sizeof(name))
|
||||
goto out_err;
|
||||
|
||||
if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name))
|
||||
if (rpc_clnt_iterate_for_each_xprt(clnt, do_xprt_debugfs, &xprtnum) < 0)
|
||||
goto out_err;
|
||||
|
||||
return;
|
||||
|
@@ -240,9 +240,16 @@ static void _print_rpc_iostats(struct seq_file *seq, struct rpc_iostats *stats,
|
||||
stats->om_error_status);
|
||||
}
|
||||
|
||||
static int do_print_stats(struct rpc_clnt *clnt, struct rpc_xprt *xprt, void *seqv)
|
||||
{
|
||||
struct seq_file *seq = seqv;
|
||||
|
||||
xprt->ops->print_stats(xprt, seq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rpc_clnt_show_stats(struct seq_file *seq, struct rpc_clnt *clnt)
|
||||
{
|
||||
struct rpc_xprt *xprt;
|
||||
unsigned int op, maxproc = clnt->cl_maxproc;
|
||||
|
||||
if (!clnt->cl_metrics)
|
||||
@@ -252,11 +259,7 @@ void rpc_clnt_show_stats(struct seq_file *seq, struct rpc_clnt *clnt)
|
||||
seq_printf(seq, "p/v: %u/%u (%s)\n",
|
||||
clnt->cl_prog, clnt->cl_vers, clnt->cl_program->name);
|
||||
|
||||
rcu_read_lock();
|
||||
xprt = rcu_dereference(clnt->cl_xprt);
|
||||
if (xprt)
|
||||
xprt->ops->print_stats(xprt, seq);
|
||||
rcu_read_unlock();
|
||||
rpc_clnt_iterate_for_each_xprt(clnt, do_print_stats, seq);
|
||||
|
||||
seq_printf(seq, "\tper-op statistics\n");
|
||||
for (op = 0; op < maxproc; op++) {
|
||||
|
@@ -36,6 +36,7 @@ static void xprt_switch_add_xprt_locked(struct rpc_xprt_switch *xps,
|
||||
if (xps->xps_nxprts == 0)
|
||||
xps->xps_net = xprt->xprt_net;
|
||||
xps->xps_nxprts++;
|
||||
xps->xps_nactive++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,8 +52,7 @@ void rpc_xprt_switch_add_xprt(struct rpc_xprt_switch *xps,
|
||||
if (xprt == NULL)
|
||||
return;
|
||||
spin_lock(&xps->xps_lock);
|
||||
if ((xps->xps_net == xprt->xprt_net || xps->xps_net == NULL) &&
|
||||
!rpc_xprt_switch_has_addr(xps, (struct sockaddr *)&xprt->addr))
|
||||
if (xps->xps_net == xprt->xprt_net || xps->xps_net == NULL)
|
||||
xprt_switch_add_xprt_locked(xps, xprt);
|
||||
spin_unlock(&xps->xps_lock);
|
||||
}
|
||||
@@ -62,6 +62,7 @@ static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps,
|
||||
{
|
||||
if (unlikely(xprt == NULL))
|
||||
return;
|
||||
xps->xps_nactive--;
|
||||
xps->xps_nxprts--;
|
||||
if (xps->xps_nxprts == 0)
|
||||
xps->xps_net = NULL;
|
||||
@@ -317,8 +318,24 @@ struct rpc_xprt *xprt_switch_find_next_entry_roundrobin(struct list_head *head,
|
||||
static
|
||||
struct rpc_xprt *xprt_iter_next_entry_roundrobin(struct rpc_xprt_iter *xpi)
|
||||
{
|
||||
return xprt_iter_next_entry_multiple(xpi,
|
||||
struct rpc_xprt_switch *xps = rcu_dereference(xpi->xpi_xpswitch);
|
||||
struct rpc_xprt *xprt;
|
||||
unsigned long xprt_queuelen;
|
||||
unsigned long xps_queuelen;
|
||||
unsigned long xps_avglen;
|
||||
|
||||
do {
|
||||
xprt = xprt_iter_next_entry_multiple(xpi,
|
||||
xprt_switch_find_next_entry_roundrobin);
|
||||
if (xprt == NULL)
|
||||
break;
|
||||
xprt_queuelen = atomic_long_read(&xprt->queuelen);
|
||||
if (xprt_queuelen <= 2)
|
||||
break;
|
||||
xps_queuelen = atomic_long_read(&xps->xps_queuelen);
|
||||
xps_avglen = DIV_ROUND_UP(xps_queuelen, xps->xps_nactive);
|
||||
} while (xprt_queuelen > xps_avglen);
|
||||
return xprt;
|
||||
}
|
||||
|
||||
static
|
||||
|
Reference in New Issue
Block a user