Merge branch 'multipath_tcp'
This commit is contained in:
commit
c98ebe2937
|
@ -176,6 +176,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
|
|||
clp->cl_rpcclient = ERR_PTR(-EINVAL);
|
||||
|
||||
clp->cl_proto = cl_init->proto;
|
||||
clp->cl_nconnect = cl_init->nconnect;
|
||||
clp->cl_net = get_net(cl_init->net);
|
||||
|
||||
clp->cl_principal = "*";
|
||||
|
@ -494,6 +495,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
|
|||
struct rpc_create_args args = {
|
||||
.net = clp->cl_net,
|
||||
.protocol = clp->cl_proto,
|
||||
.nconnect = clp->cl_nconnect,
|
||||
.address = (struct sockaddr *)&clp->cl_addr,
|
||||
.addrsize = clp->cl_addrlen,
|
||||
.timeout = cl_init->timeparms,
|
||||
|
@ -659,6 +661,7 @@ static int nfs_init_server(struct nfs_server *server,
|
|||
.net = data->net,
|
||||
.timeparms = &timeparms,
|
||||
.cred = server->cred,
|
||||
.nconnect = data->nfs_server.nconnect,
|
||||
};
|
||||
struct nfs_client *clp;
|
||||
int error;
|
||||
|
|
|
@ -82,6 +82,7 @@ struct nfs_client_initdata {
|
|||
struct nfs_subversion *nfs_mod;
|
||||
int proto;
|
||||
u32 minorversion;
|
||||
unsigned int nconnect;
|
||||
struct net *net;
|
||||
const struct rpc_timeout *timeparms;
|
||||
const struct cred *cred;
|
||||
|
@ -123,6 +124,7 @@ struct nfs_parsed_mount_data {
|
|||
char *export_path;
|
||||
int port;
|
||||
unsigned short protocol;
|
||||
unsigned short nconnect;
|
||||
} nfs_server;
|
||||
|
||||
void *lsm_opts;
|
||||
|
|
|
@ -102,6 +102,9 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
|
|||
return ERR_PTR(-EINVAL);
|
||||
cl_init.hostname = buf;
|
||||
|
||||
if (mds_clp->cl_nconnect > 1 && ds_proto == XPRT_TRANSPORT_TCP)
|
||||
cl_init.nconnect = mds_clp->cl_nconnect;
|
||||
|
||||
if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
|
||||
set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
|
||||
|
||||
|
|
|
@ -859,7 +859,8 @@ static int nfs4_set_client(struct nfs_server *server,
|
|||
const size_t addrlen,
|
||||
const char *ip_addr,
|
||||
int proto, const struct rpc_timeout *timeparms,
|
||||
u32 minorversion, struct net *net)
|
||||
u32 minorversion, unsigned int nconnect,
|
||||
struct net *net)
|
||||
{
|
||||
struct nfs_client_initdata cl_init = {
|
||||
.hostname = hostname,
|
||||
|
@ -875,6 +876,8 @@ static int nfs4_set_client(struct nfs_server *server,
|
|||
};
|
||||
struct nfs_client *clp;
|
||||
|
||||
if (minorversion > 0 && proto == XPRT_TRANSPORT_TCP)
|
||||
cl_init.nconnect = nconnect;
|
||||
if (server->flags & NFS_MOUNT_NORESVPORT)
|
||||
set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
|
||||
if (server->options & NFS_OPTION_MIGRATION)
|
||||
|
@ -941,6 +944,9 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
|
|||
return ERR_PTR(-EINVAL);
|
||||
cl_init.hostname = buf;
|
||||
|
||||
if (mds_clp->cl_nconnect > 1 && ds_proto == XPRT_TRANSPORT_TCP)
|
||||
cl_init.nconnect = mds_clp->cl_nconnect;
|
||||
|
||||
if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
|
||||
__set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
|
||||
|
||||
|
@ -1074,6 +1080,7 @@ static int nfs4_init_server(struct nfs_server *server,
|
|||
data->nfs_server.protocol,
|
||||
&timeparms,
|
||||
data->minorversion,
|
||||
data->nfs_server.nconnect,
|
||||
data->net);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
@ -1163,6 +1170,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
|
|||
XPRT_TRANSPORT_RDMA,
|
||||
parent_server->client->cl_timeout,
|
||||
parent_client->cl_mvops->minor_version,
|
||||
parent_client->cl_nconnect,
|
||||
parent_client->cl_net);
|
||||
if (!error)
|
||||
goto init_server;
|
||||
|
@ -1176,6 +1184,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
|
|||
XPRT_TRANSPORT_TCP,
|
||||
parent_server->client->cl_timeout,
|
||||
parent_client->cl_mvops->minor_version,
|
||||
parent_client->cl_nconnect,
|
||||
parent_client->cl_net);
|
||||
if (error < 0)
|
||||
goto error;
|
||||
|
@ -1271,7 +1280,8 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
|
|||
set_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
|
||||
error = nfs4_set_client(server, hostname, sap, salen, buf,
|
||||
clp->cl_proto, clnt->cl_timeout,
|
||||
clp->cl_minorversion, net);
|
||||
clp->cl_minorversion,
|
||||
clp->cl_nconnect, net);
|
||||
clear_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
|
||||
if (error != 0) {
|
||||
nfs_server_insert_lists(server);
|
||||
|
|
|
@ -5992,7 +5992,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
|
|||
.rpc_message = &msg,
|
||||
.callback_ops = &nfs4_setclientid_ops,
|
||||
.callback_data = &setclientid,
|
||||
.flags = RPC_TASK_TIMEOUT,
|
||||
.flags = RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN,
|
||||
};
|
||||
int status;
|
||||
|
||||
|
@ -6058,7 +6058,8 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
|
|||
dprintk("NFS call setclientid_confirm auth=%s, (client ID %llx)\n",
|
||||
clp->cl_rpcclient->cl_auth->au_ops->au_name,
|
||||
clp->cl_clientid);
|
||||
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
||||
status = rpc_call_sync(clp->cl_rpcclient, &msg,
|
||||
RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN);
|
||||
trace_nfs4_setclientid_confirm(clp, status);
|
||||
dprintk("NFS reply setclientid_confirm: %d\n", status);
|
||||
return status;
|
||||
|
@ -7639,7 +7640,7 @@ static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct
|
|||
NFS_SP4_MACH_CRED_SECINFO, &clnt, &msg);
|
||||
|
||||
status = nfs4_call_sync(clnt, NFS_SERVER(dir), &msg, &args.seq_args,
|
||||
&res.seq_res, 0);
|
||||
&res.seq_res, RPC_TASK_NO_ROUND_ROBIN);
|
||||
dprintk("NFS reply secinfo: %d\n", status);
|
||||
|
||||
put_cred(cred);
|
||||
|
@ -7977,7 +7978,7 @@ nfs4_run_exchange_id(struct nfs_client *clp, const struct cred *cred,
|
|||
.rpc_client = clp->cl_rpcclient,
|
||||
.callback_ops = &nfs4_exchange_id_call_ops,
|
||||
.rpc_message = &msg,
|
||||
.flags = RPC_TASK_TIMEOUT,
|
||||
.flags = RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN,
|
||||
};
|
||||
struct nfs41_exchange_id_data *calldata;
|
||||
int status;
|
||||
|
@ -8202,7 +8203,8 @@ static int _nfs4_proc_destroy_clientid(struct nfs_client *clp,
|
|||
};
|
||||
int status;
|
||||
|
||||
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
||||
status = rpc_call_sync(clp->cl_rpcclient, &msg,
|
||||
RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN);
|
||||
trace_nfs4_destroy_clientid(clp, status);
|
||||
if (status)
|
||||
dprintk("NFS: Got error %d from the server %s on "
|
||||
|
@ -8481,7 +8483,8 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
|
|||
nfs4_init_channel_attrs(&args, clp->cl_rpcclient);
|
||||
args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
|
||||
|
||||
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
||||
status = rpc_call_sync(session->clp->cl_rpcclient, &msg,
|
||||
RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN);
|
||||
trace_nfs4_create_session(clp, status);
|
||||
|
||||
switch (status) {
|
||||
|
@ -8557,7 +8560,8 @@ int nfs4_proc_destroy_session(struct nfs4_session *session,
|
|||
if (!test_and_clear_bit(NFS4_SESSION_ESTABLISHED, &session->session_state))
|
||||
return 0;
|
||||
|
||||
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
||||
status = rpc_call_sync(session->clp->cl_rpcclient, &msg,
|
||||
RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN);
|
||||
trace_nfs4_destroy_session(session->clp, status);
|
||||
|
||||
if (status)
|
||||
|
@ -8811,7 +8815,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp,
|
|||
.rpc_client = clp->cl_rpcclient,
|
||||
.rpc_message = &msg,
|
||||
.callback_ops = &nfs4_reclaim_complete_call_ops,
|
||||
.flags = RPC_TASK_ASYNC,
|
||||
.flags = RPC_TASK_ASYNC | RPC_TASK_NO_ROUND_ROBIN,
|
||||
};
|
||||
int status = -ENOMEM;
|
||||
|
||||
|
@ -9330,7 +9334,7 @@ _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
|||
|
||||
dprintk("--> %s\n", __func__);
|
||||
status = nfs4_call_sync(clnt, server, &msg, &args.seq_args,
|
||||
&res.seq_res, 0);
|
||||
&res.seq_res, RPC_TASK_NO_ROUND_ROBIN);
|
||||
dprintk("<-- %s status=%d\n", __func__, status);
|
||||
|
||||
put_cred(cred);
|
||||
|
|
|
@ -77,6 +77,8 @@
|
|||
#define NFS_DEFAULT_VERSION 2
|
||||
#endif
|
||||
|
||||
#define NFS_MAX_CONNECTIONS 16
|
||||
|
||||
enum {
|
||||
/* Mount options that take no arguments */
|
||||
Opt_soft, Opt_softerr, Opt_hard,
|
||||
|
@ -108,6 +110,7 @@ enum {
|
|||
Opt_nfsvers,
|
||||
Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
|
||||
Opt_addr, Opt_mountaddr, Opt_clientaddr,
|
||||
Opt_nconnect,
|
||||
Opt_lookupcache,
|
||||
Opt_fscache_uniq,
|
||||
Opt_local_lock,
|
||||
|
@ -181,6 +184,8 @@ static const match_table_t nfs_mount_option_tokens = {
|
|||
{ Opt_mounthost, "mounthost=%s" },
|
||||
{ Opt_mountaddr, "mountaddr=%s" },
|
||||
|
||||
{ Opt_nconnect, "nconnect=%s" },
|
||||
|
||||
{ Opt_lookupcache, "lookupcache=%s" },
|
||||
{ Opt_fscache_uniq, "fsc=%s" },
|
||||
{ Opt_local_lock, "local_lock=%s" },
|
||||
|
@ -673,6 +678,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
|
|||
seq_printf(m, ",proto=%s",
|
||||
rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID));
|
||||
rcu_read_unlock();
|
||||
if (clp->cl_nconnect > 0)
|
||||
seq_printf(m, ",nconnect=%u", clp->cl_nconnect);
|
||||
if (version == 4) {
|
||||
if (nfss->port != NFS_PORT)
|
||||
seq_printf(m, ",port=%u", nfss->port);
|
||||
|
@ -1549,6 +1556,11 @@ static int nfs_parse_mount_options(char *raw,
|
|||
if (mnt->mount_server.addrlen == 0)
|
||||
goto out_invalid_address;
|
||||
break;
|
||||
case Opt_nconnect:
|
||||
if (nfs_get_option_ul_bound(args, &option, 1, NFS_MAX_CONNECTIONS))
|
||||
goto out_invalid_value;
|
||||
mnt->nfs_server.nconnect = option;
|
||||
break;
|
||||
case Opt_lookupcache:
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
|
|
|
@ -58,6 +58,7 @@ struct nfs_client {
|
|||
struct nfs_subversion * cl_nfs_mod; /* pointer to nfs version module */
|
||||
|
||||
u32 cl_minorversion;/* NFSv4 minorversion */
|
||||
unsigned int cl_nconnect; /* Number of connections */
|
||||
const char * cl_principal; /* used for machine cred */
|
||||
|
||||
#if IS_ENABLED(CONFIG_NFS_V4)
|
||||
|
|
|
@ -124,6 +124,7 @@ struct rpc_create_args {
|
|||
u32 prognumber; /* overrides program->number */
|
||||
u32 version;
|
||||
rpc_authflavor_t authflavor;
|
||||
u32 nconnect;
|
||||
unsigned long flags;
|
||||
char *client_name;
|
||||
struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */
|
||||
|
|
|
@ -126,6 +126,7 @@ struct rpc_task_setup {
|
|||
#define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */
|
||||
#define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */
|
||||
#define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */
|
||||
#define RPC_TASK_NO_ROUND_ROBIN 0x0100 /* send requests on "main" xprt */
|
||||
#define RPC_TASK_SOFT 0x0200 /* Use soft timeouts */
|
||||
#define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */
|
||||
#define RPC_TASK_SENT 0x0800 /* message was sent */
|
||||
|
|
|
@ -238,6 +238,7 @@ struct rpc_xprt {
|
|||
/*
|
||||
* Send stuff
|
||||
*/
|
||||
atomic_long_t queuelen;
|
||||
spinlock_t transport_lock; /* lock transport info */
|
||||
spinlock_t reserve_lock; /* lock slot table */
|
||||
spinlock_t queue_lock; /* send/receive queue lock */
|
||||
|
|
|
@ -15,6 +15,8 @@ struct rpc_xprt_switch {
|
|||
struct kref xps_kref;
|
||||
|
||||
unsigned int xps_nxprts;
|
||||
unsigned int xps_nactive;
|
||||
atomic_long_t xps_queuelen;
|
||||
struct list_head xps_xprt_list;
|
||||
|
||||
struct net * xps_net;
|
||||
|
|
|
@ -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 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
|
|||
}
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue