tangled
alpha
login
or
join now
tjh.dev
/
kernel
1
fork
atom
Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1
fork
atom
overview
issues
pulls
pipelines
Merge branch 'multipath_tcp'
Trond Myklebust
6 years ago
c98ebe29
28ade856
+186
-43
15 changed files
expand all
collapse all
unified
split
fs
nfs
client.c
internal.h
nfs3client.c
nfs4client.c
nfs4proc.c
super.c
include
linux
nfs_fs_sb.h
sunrpc
clnt.h
sched.h
xprt.h
xprtmultipath.h
net
sunrpc
clnt.c
debugfs.c
stats.c
xprtmultipath.c
+3
fs/nfs/client.c
reviewed
···
176
176
clp->cl_rpcclient = ERR_PTR(-EINVAL);
177
177
178
178
clp->cl_proto = cl_init->proto;
179
179
+
clp->cl_nconnect = cl_init->nconnect;
179
180
clp->cl_net = get_net(cl_init->net);
180
181
181
182
clp->cl_principal = "*";
···
495
494
struct rpc_create_args args = {
496
495
.net = clp->cl_net,
497
496
.protocol = clp->cl_proto,
497
497
+
.nconnect = clp->cl_nconnect,
498
498
.address = (struct sockaddr *)&clp->cl_addr,
499
499
.addrsize = clp->cl_addrlen,
500
500
.timeout = cl_init->timeparms,
···
661
659
.net = data->net,
662
660
.timeparms = &timeparms,
663
661
.cred = server->cred,
662
662
+
.nconnect = data->nfs_server.nconnect,
664
663
};
665
664
struct nfs_client *clp;
666
665
int error;
+2
fs/nfs/internal.h
reviewed
···
82
82
struct nfs_subversion *nfs_mod;
83
83
int proto;
84
84
u32 minorversion;
85
85
+
unsigned int nconnect;
85
86
struct net *net;
86
87
const struct rpc_timeout *timeparms;
87
88
const struct cred *cred;
···
124
123
char *export_path;
125
124
int port;
126
125
unsigned short protocol;
126
126
+
unsigned short nconnect;
127
127
} nfs_server;
128
128
129
129
void *lsm_opts;
+3
fs/nfs/nfs3client.c
reviewed
···
102
102
return ERR_PTR(-EINVAL);
103
103
cl_init.hostname = buf;
104
104
105
105
+
if (mds_clp->cl_nconnect > 1 && ds_proto == XPRT_TRANSPORT_TCP)
106
106
+
cl_init.nconnect = mds_clp->cl_nconnect;
107
107
+
105
108
if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
106
109
set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
107
110
+12
-2
fs/nfs/nfs4client.c
reviewed
···
859
859
const size_t addrlen,
860
860
const char *ip_addr,
861
861
int proto, const struct rpc_timeout *timeparms,
862
862
-
u32 minorversion, struct net *net)
862
862
+
u32 minorversion, unsigned int nconnect,
863
863
+
struct net *net)
863
864
{
864
865
struct nfs_client_initdata cl_init = {
865
866
.hostname = hostname,
···
876
875
};
877
876
struct nfs_client *clp;
878
877
878
878
+
if (minorversion > 0 && proto == XPRT_TRANSPORT_TCP)
879
879
+
cl_init.nconnect = nconnect;
879
880
if (server->flags & NFS_MOUNT_NORESVPORT)
880
881
set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
881
882
if (server->options & NFS_OPTION_MIGRATION)
···
943
940
if (rpc_ntop(ds_addr, buf, sizeof(buf)) <= 0)
944
941
return ERR_PTR(-EINVAL);
945
942
cl_init.hostname = buf;
943
943
+
944
944
+
if (mds_clp->cl_nconnect > 1 && ds_proto == XPRT_TRANSPORT_TCP)
945
945
+
cl_init.nconnect = mds_clp->cl_nconnect;
946
946
947
947
if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
948
948
__set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
···
1080
1074
data->nfs_server.protocol,
1081
1075
&timeparms,
1082
1076
data->minorversion,
1077
1077
+
data->nfs_server.nconnect,
1083
1078
data->net);
1084
1079
if (error < 0)
1085
1080
return error;
···
1170
1163
XPRT_TRANSPORT_RDMA,
1171
1164
parent_server->client->cl_timeout,
1172
1165
parent_client->cl_mvops->minor_version,
1166
1166
+
parent_client->cl_nconnect,
1173
1167
parent_client->cl_net);
1174
1168
if (!error)
1175
1169
goto init_server;
···
1184
1176
XPRT_TRANSPORT_TCP,
1185
1177
parent_server->client->cl_timeout,
1186
1178
parent_client->cl_mvops->minor_version,
1179
1179
+
parent_client->cl_nconnect,
1187
1180
parent_client->cl_net);
1188
1181
if (error < 0)
1189
1182
goto error;
···
1280
1271
set_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
1281
1272
error = nfs4_set_client(server, hostname, sap, salen, buf,
1282
1273
clp->cl_proto, clnt->cl_timeout,
1283
1283
-
clp->cl_minorversion, net);
1274
1274
+
clp->cl_minorversion,
1275
1275
+
clp->cl_nconnect, net);
1284
1276
clear_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
1285
1277
if (error != 0) {
1286
1278
nfs_server_insert_lists(server);
+13
-9
fs/nfs/nfs4proc.c
reviewed
···
5992
5992
.rpc_message = &msg,
5993
5993
.callback_ops = &nfs4_setclientid_ops,
5994
5994
.callback_data = &setclientid,
5995
5995
-
.flags = RPC_TASK_TIMEOUT,
5995
5995
+
.flags = RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN,
5996
5996
};
5997
5997
int status;
5998
5998
···
6058
6058
dprintk("NFS call setclientid_confirm auth=%s, (client ID %llx)\n",
6059
6059
clp->cl_rpcclient->cl_auth->au_ops->au_name,
6060
6060
clp->cl_clientid);
6061
6061
-
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
6061
6061
+
status = rpc_call_sync(clp->cl_rpcclient, &msg,
6062
6062
+
RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN);
6062
6063
trace_nfs4_setclientid_confirm(clp, status);
6063
6064
dprintk("NFS reply setclientid_confirm: %d\n", status);
6064
6065
return status;
···
7640
7639
NFS_SP4_MACH_CRED_SECINFO, &clnt, &msg);
7641
7640
7642
7641
status = nfs4_call_sync(clnt, NFS_SERVER(dir), &msg, &args.seq_args,
7643
7643
-
&res.seq_res, 0);
7642
7642
+
&res.seq_res, RPC_TASK_NO_ROUND_ROBIN);
7644
7643
dprintk("NFS reply secinfo: %d\n", status);
7645
7644
7646
7645
put_cred(cred);
···
7978
7977
.rpc_client = clp->cl_rpcclient,
7979
7978
.callback_ops = &nfs4_exchange_id_call_ops,
7980
7979
.rpc_message = &msg,
7981
7981
-
.flags = RPC_TASK_TIMEOUT,
7980
7980
+
.flags = RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN,
7982
7981
};
7983
7982
struct nfs41_exchange_id_data *calldata;
7984
7983
int status;
···
8203
8202
};
8204
8203
int status;
8205
8204
8206
8206
-
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
8205
8205
+
status = rpc_call_sync(clp->cl_rpcclient, &msg,
8206
8206
+
RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN);
8207
8207
trace_nfs4_destroy_clientid(clp, status);
8208
8208
if (status)
8209
8209
dprintk("NFS: Got error %d from the server %s on "
···
8483
8481
nfs4_init_channel_attrs(&args, clp->cl_rpcclient);
8484
8482
args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
8485
8483
8486
8486
-
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
8484
8484
+
status = rpc_call_sync(session->clp->cl_rpcclient, &msg,
8485
8485
+
RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN);
8487
8486
trace_nfs4_create_session(clp, status);
8488
8487
8489
8488
switch (status) {
···
8560
8557
if (!test_and_clear_bit(NFS4_SESSION_ESTABLISHED, &session->session_state))
8561
8558
return 0;
8562
8559
8563
8563
-
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
8560
8560
+
status = rpc_call_sync(session->clp->cl_rpcclient, &msg,
8561
8561
+
RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN);
8564
8562
trace_nfs4_destroy_session(session->clp, status);
8565
8563
8566
8564
if (status)
···
8815
8811
.rpc_client = clp->cl_rpcclient,
8816
8812
.rpc_message = &msg,
8817
8813
.callback_ops = &nfs4_reclaim_complete_call_ops,
8818
8818
-
.flags = RPC_TASK_ASYNC,
8814
8814
+
.flags = RPC_TASK_ASYNC | RPC_TASK_NO_ROUND_ROBIN,
8819
8815
};
8820
8816
int status = -ENOMEM;
8821
8817
···
9334
9330
9335
9331
dprintk("--> %s\n", __func__);
9336
9332
status = nfs4_call_sync(clnt, server, &msg, &args.seq_args,
9337
9337
-
&res.seq_res, 0);
9333
9333
+
&res.seq_res, RPC_TASK_NO_ROUND_ROBIN);
9338
9334
dprintk("<-- %s status=%d\n", __func__, status);
9339
9335
9340
9336
put_cred(cred);
+12
fs/nfs/super.c
reviewed
···
77
77
#define NFS_DEFAULT_VERSION 2
78
78
#endif
79
79
80
80
+
#define NFS_MAX_CONNECTIONS 16
81
81
+
80
82
enum {
81
83
/* Mount options that take no arguments */
82
84
Opt_soft, Opt_softerr, Opt_hard,
···
110
108
Opt_nfsvers,
111
109
Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
112
110
Opt_addr, Opt_mountaddr, Opt_clientaddr,
111
111
+
Opt_nconnect,
113
112
Opt_lookupcache,
114
113
Opt_fscache_uniq,
115
114
Opt_local_lock,
···
183
180
{ Opt_clientaddr, "clientaddr=%s" },
184
181
{ Opt_mounthost, "mounthost=%s" },
185
182
{ Opt_mountaddr, "mountaddr=%s" },
183
183
+
184
184
+
{ Opt_nconnect, "nconnect=%s" },
186
185
187
186
{ Opt_lookupcache, "lookupcache=%s" },
188
187
{ Opt_fscache_uniq, "fsc=%s" },
···
678
673
seq_printf(m, ",proto=%s",
679
674
rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID));
680
675
rcu_read_unlock();
676
676
+
if (clp->cl_nconnect > 0)
677
677
+
seq_printf(m, ",nconnect=%u", clp->cl_nconnect);
681
678
if (version == 4) {
682
679
if (nfss->port != NFS_PORT)
683
680
seq_printf(m, ",port=%u", nfss->port);
···
1555
1548
kfree(string);
1556
1549
if (mnt->mount_server.addrlen == 0)
1557
1550
goto out_invalid_address;
1551
1551
+
break;
1552
1552
+
case Opt_nconnect:
1553
1553
+
if (nfs_get_option_ul_bound(args, &option, 1, NFS_MAX_CONNECTIONS))
1554
1554
+
goto out_invalid_value;
1555
1555
+
mnt->nfs_server.nconnect = option;
1558
1556
break;
1559
1557
case Opt_lookupcache:
1560
1558
string = match_strdup(args);
+1
include/linux/nfs_fs_sb.h
reviewed
···
58
58
struct nfs_subversion * cl_nfs_mod; /* pointer to nfs version module */
59
59
60
60
u32 cl_minorversion;/* NFSv4 minorversion */
61
61
+
unsigned int cl_nconnect; /* Number of connections */
61
62
const char * cl_principal; /* used for machine cred */
62
63
63
64
#if IS_ENABLED(CONFIG_NFS_V4)
+1
include/linux/sunrpc/clnt.h
reviewed
···
124
124
u32 prognumber; /* overrides program->number */
125
125
u32 version;
126
126
rpc_authflavor_t authflavor;
127
127
+
u32 nconnect;
127
128
unsigned long flags;
128
129
char *client_name;
129
130
struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */
+1
include/linux/sunrpc/sched.h
reviewed
···
126
126
#define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */
127
127
#define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */
128
128
#define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */
129
129
+
#define RPC_TASK_NO_ROUND_ROBIN 0x0100 /* send requests on "main" xprt */
129
130
#define RPC_TASK_SOFT 0x0200 /* Use soft timeouts */
130
131
#define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */
131
132
#define RPC_TASK_SENT 0x0800 /* message was sent */
+1
include/linux/sunrpc/xprt.h
reviewed
···
238
238
/*
239
239
* Send stuff
240
240
*/
241
241
+
atomic_long_t queuelen;
241
242
spinlock_t transport_lock; /* lock transport info */
242
243
spinlock_t reserve_lock; /* lock slot table */
243
244
spinlock_t queue_lock; /* send/receive queue lock */
+2
include/linux/sunrpc/xprtmultipath.h
reviewed
···
15
15
struct kref xps_kref;
16
16
17
17
unsigned int xps_nxprts;
18
18
+
unsigned int xps_nactive;
19
19
+
atomic_long_t xps_queuelen;
18
20
struct list_head xps_xprt_list;
19
21
20
22
struct net * xps_net;
+76
-5
net/sunrpc/clnt.c
reviewed
···
528
528
.bc_xprt = args->bc_xprt,
529
529
};
530
530
char servername[48];
531
531
+
struct rpc_clnt *clnt;
532
532
+
int i;
531
533
532
534
if (args->bc_xprt) {
533
535
WARN_ON_ONCE(!(args->protocol & XPRT_TRANSPORT_BC));
···
592
590
if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT)
593
591
xprt->resvport = 0;
594
592
595
595
-
return rpc_create_xprt(args, xprt);
593
593
+
clnt = rpc_create_xprt(args, xprt);
594
594
+
if (IS_ERR(clnt) || args->nconnect <= 1)
595
595
+
return clnt;
596
596
+
597
597
+
for (i = 0; i < args->nconnect - 1; i++) {
598
598
+
if (rpc_clnt_add_xprt(clnt, &xprtargs, NULL, NULL) < 0)
599
599
+
break;
600
600
+
}
601
601
+
return clnt;
596
602
}
597
603
EXPORT_SYMBOL_GPL(rpc_create);
598
604
···
978
968
}
979
969
EXPORT_SYMBOL_GPL(rpc_bind_new_program);
980
970
971
971
+
static struct rpc_xprt *
972
972
+
rpc_task_get_xprt(struct rpc_clnt *clnt)
973
973
+
{
974
974
+
struct rpc_xprt_switch *xps;
975
975
+
struct rpc_xprt *xprt= xprt_iter_get_next(&clnt->cl_xpi);
976
976
+
977
977
+
if (!xprt)
978
978
+
return NULL;
979
979
+
rcu_read_lock();
980
980
+
xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
981
981
+
atomic_long_inc(&xps->xps_queuelen);
982
982
+
rcu_read_unlock();
983
983
+
atomic_long_inc(&xprt->queuelen);
984
984
+
985
985
+
return xprt;
986
986
+
}
987
987
+
988
988
+
static struct rpc_xprt *
989
989
+
rpc_task_get_first_xprt(struct rpc_clnt *clnt)
990
990
+
{
991
991
+
struct rpc_xprt_switch *xps;
992
992
+
struct rpc_xprt *xprt;
993
993
+
994
994
+
rcu_read_lock();
995
995
+
xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
996
996
+
if (xprt) {
997
997
+
atomic_long_inc(&xprt->queuelen);
998
998
+
xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
999
999
+
atomic_long_inc(&xps->xps_queuelen);
1000
1000
+
}
1001
1001
+
rcu_read_unlock();
1002
1002
+
1003
1003
+
return xprt;
1004
1004
+
}
1005
1005
+
1006
1006
+
static void
1007
1007
+
rpc_task_release_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
1008
1008
+
{
1009
1009
+
struct rpc_xprt_switch *xps;
1010
1010
+
1011
1011
+
atomic_long_dec(&xprt->queuelen);
1012
1012
+
rcu_read_lock();
1013
1013
+
xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
1014
1014
+
atomic_long_dec(&xps->xps_queuelen);
1015
1015
+
rcu_read_unlock();
1016
1016
+
1017
1017
+
xprt_put(xprt);
1018
1018
+
}
1019
1019
+
981
1020
void rpc_task_release_transport(struct rpc_task *task)
982
1021
{
983
1022
struct rpc_xprt *xprt = task->tk_xprt;
984
1023
985
1024
if (xprt) {
986
1025
task->tk_xprt = NULL;
987
987
-
xprt_put(xprt);
1026
1026
+
if (task->tk_client)
1027
1027
+
rpc_task_release_xprt(task->tk_client, xprt);
1028
1028
+
else
1029
1029
+
xprt_put(xprt);
988
1030
}
989
1031
}
990
1032
EXPORT_SYMBOL_GPL(rpc_task_release_transport);
···
1045
983
{
1046
984
struct rpc_clnt *clnt = task->tk_client;
1047
985
986
986
+
rpc_task_release_transport(task);
1048
987
if (clnt != NULL) {
1049
988
/* Remove from client task list */
1050
989
spin_lock(&clnt->cl_lock);
···
1055
992
1056
993
rpc_release_client(clnt);
1057
994
}
1058
1058
-
rpc_task_release_transport(task);
1059
995
}
1060
996
1061
997
static
1062
998
void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
1063
999
{
1064
1064
-
if (!task->tk_xprt)
1065
1065
-
task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi);
1000
1000
+
if (task->tk_xprt)
1001
1001
+
return;
1002
1002
+
if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN)
1003
1003
+
task->tk_xprt = rpc_task_get_first_xprt(clnt);
1004
1004
+
else
1005
1005
+
task->tk_xprt = rpc_task_get_xprt(clnt);
1066
1006
}
1067
1007
1068
1008
static
···
2762
2696
return -ENOMEM;
2763
2697
data->xps = xprt_switch_get(xps);
2764
2698
data->xprt = xprt_get(xprt);
2699
2699
+
if (rpc_xprt_switch_has_addr(data->xps, (struct sockaddr *)&xprt->addr)) {
2700
2700
+
rpc_cb_add_xprt_release(data);
2701
2701
+
goto success;
2702
2702
+
}
2765
2703
2766
2704
task = rpc_call_null_helper(clnt, xprt, NULL,
2767
2705
RPC_TASK_SOFT|RPC_TASK_SOFTCONN|RPC_TASK_ASYNC|RPC_TASK_NULLCREDS,
···
2773
2703
if (IS_ERR(task))
2774
2704
return PTR_ERR(task);
2775
2705
rpc_put_task(task);
2706
2706
+
success:
2776
2707
return 1;
2777
2708
}
2778
2709
EXPORT_SYMBOL_GPL(rpc_clnt_test_and_add_xprt);
+30
-18
net/sunrpc/debugfs.c
reviewed
···
1
1
// SPDX-License-Identifier: GPL-2.0
2
2
-
/**
2
2
+
/*
3
3
* debugfs interface for sunrpc
4
4
*
5
5
* (c) 2014 Jeff Layton <jlayton@primarydata.com>
···
118
118
.release = tasks_release,
119
119
};
120
120
121
121
+
static int do_xprt_debugfs(struct rpc_clnt *clnt, struct rpc_xprt *xprt, void *numv)
122
122
+
{
123
123
+
int len;
124
124
+
char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */
125
125
+
char link[9]; /* enough for 8 hex digits + NULL */
126
126
+
int *nump = numv;
127
127
+
128
128
+
if (IS_ERR_OR_NULL(xprt->debugfs))
129
129
+
return 0;
130
130
+
len = snprintf(name, sizeof(name), "../../rpc_xprt/%s",
131
131
+
xprt->debugfs->d_name.name);
132
132
+
if (len > sizeof(name))
133
133
+
return -1;
134
134
+
if (*nump == 0)
135
135
+
strcpy(link, "xprt");
136
136
+
else {
137
137
+
len = snprintf(link, sizeof(link), "xprt%d", *nump);
138
138
+
if (len > sizeof(link))
139
139
+
return -1;
140
140
+
}
141
141
+
if (!debugfs_create_symlink(link, clnt->cl_debugfs, name))
142
142
+
return -1;
143
143
+
(*nump)++;
144
144
+
return 0;
145
145
+
}
146
146
+
121
147
void
122
148
rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
123
149
{
124
150
int len;
125
125
-
char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */
126
126
-
struct rpc_xprt *xprt;
151
151
+
char name[9]; /* enough for 8 hex digits + NULL */
152
152
+
int xprtnum = 0;
127
153
128
154
/* Already registered? */
129
155
if (clnt->cl_debugfs || !rpc_clnt_dir)
···
169
143
clnt, &tasks_fops))
170
144
goto out_err;
171
145
172
172
-
rcu_read_lock();
173
173
-
xprt = rcu_dereference(clnt->cl_xprt);
174
174
-
/* no "debugfs" dentry? Don't bother with the symlink. */
175
175
-
if (IS_ERR_OR_NULL(xprt->debugfs)) {
176
176
-
rcu_read_unlock();
177
177
-
return;
178
178
-
}
179
179
-
len = snprintf(name, sizeof(name), "../../rpc_xprt/%s",
180
180
-
xprt->debugfs->d_name.name);
181
181
-
rcu_read_unlock();
182
182
-
183
183
-
if (len >= sizeof(name))
184
184
-
goto out_err;
185
185
-
186
186
-
if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name))
146
146
+
if (rpc_clnt_iterate_for_each_xprt(clnt, do_xprt_debugfs, &xprtnum) < 0)
187
147
goto out_err;
188
148
189
149
return;
+9
-6
net/sunrpc/stats.c
reviewed
···
240
240
stats->om_error_status);
241
241
}
242
242
243
243
+
static int do_print_stats(struct rpc_clnt *clnt, struct rpc_xprt *xprt, void *seqv)
244
244
+
{
245
245
+
struct seq_file *seq = seqv;
246
246
+
247
247
+
xprt->ops->print_stats(xprt, seq);
248
248
+
return 0;
249
249
+
}
250
250
+
243
251
void rpc_clnt_show_stats(struct seq_file *seq, struct rpc_clnt *clnt)
244
252
{
245
245
-
struct rpc_xprt *xprt;
246
253
unsigned int op, maxproc = clnt->cl_maxproc;
247
254
248
255
if (!clnt->cl_metrics)
···
259
252
seq_printf(seq, "p/v: %u/%u (%s)\n",
260
253
clnt->cl_prog, clnt->cl_vers, clnt->cl_program->name);
261
254
262
262
-
rcu_read_lock();
263
263
-
xprt = rcu_dereference(clnt->cl_xprt);
264
264
-
if (xprt)
265
265
-
xprt->ops->print_stats(xprt, seq);
266
266
-
rcu_read_unlock();
255
255
+
rpc_clnt_iterate_for_each_xprt(clnt, do_print_stats, seq);
267
256
268
257
seq_printf(seq, "\tper-op statistics\n");
269
258
for (op = 0; op < maxproc; op++) {
+20
-3
net/sunrpc/xprtmultipath.c
reviewed
···
36
36
if (xps->xps_nxprts == 0)
37
37
xps->xps_net = xprt->xprt_net;
38
38
xps->xps_nxprts++;
39
39
+
xps->xps_nactive++;
39
40
}
40
41
41
42
/**
···
52
51
if (xprt == NULL)
53
52
return;
54
53
spin_lock(&xps->xps_lock);
55
55
-
if ((xps->xps_net == xprt->xprt_net || xps->xps_net == NULL) &&
56
56
-
!rpc_xprt_switch_has_addr(xps, (struct sockaddr *)&xprt->addr))
54
54
+
if (xps->xps_net == xprt->xprt_net || xps->xps_net == NULL)
57
55
xprt_switch_add_xprt_locked(xps, xprt);
58
56
spin_unlock(&xps->xps_lock);
59
57
}
···
62
62
{
63
63
if (unlikely(xprt == NULL))
64
64
return;
65
65
+
xps->xps_nactive--;
65
66
xps->xps_nxprts--;
66
67
if (xps->xps_nxprts == 0)
67
68
xps->xps_net = NULL;
···
318
317
static
319
318
struct rpc_xprt *xprt_iter_next_entry_roundrobin(struct rpc_xprt_iter *xpi)
320
319
{
321
321
-
return xprt_iter_next_entry_multiple(xpi,
320
320
+
struct rpc_xprt_switch *xps = rcu_dereference(xpi->xpi_xpswitch);
321
321
+
struct rpc_xprt *xprt;
322
322
+
unsigned long xprt_queuelen;
323
323
+
unsigned long xps_queuelen;
324
324
+
unsigned long xps_avglen;
325
325
+
326
326
+
do {
327
327
+
xprt = xprt_iter_next_entry_multiple(xpi,
322
328
xprt_switch_find_next_entry_roundrobin);
329
329
+
if (xprt == NULL)
330
330
+
break;
331
331
+
xprt_queuelen = atomic_long_read(&xprt->queuelen);
332
332
+
if (xprt_queuelen <= 2)
333
333
+
break;
334
334
+
xps_queuelen = atomic_long_read(&xps->xps_queuelen);
335
335
+
xps_avglen = DIV_ROUND_UP(xps_queuelen, xps->xps_nactive);
336
336
+
} while (xprt_queuelen > xps_avglen);
337
337
+
return xprt;
323
338
}
324
339
325
340
static