Skip to content

Commit 11a861d

Browse files
rleondavem330
authored andcommitted
devlink: Use xarray to store devlink instances
We can use xarray instead of linearly organized linked lists for the devlink instances. This will let us revise the locking scheme in favour of internal xarray locking that protects database. Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 437ebfd commit 11a861d

File tree

2 files changed

+50
-22
lines changed

2 files changed

+50
-22
lines changed

include/net/devlink.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct devlink_dev_stats {
3232
struct devlink_ops;
3333

3434
struct devlink {
35-
struct list_head list;
35+
u32 index;
3636
struct list_head port_list;
3737
struct list_head rate_list;
3838
struct list_head sb_list;

net/core/devlink.c

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_
9292
DEVLINK_PORT_FN_STATE_ACTIVE),
9393
};
9494

95-
static LIST_HEAD(devlink_list);
95+
static DEFINE_XARRAY_FLAGS(devlinks, XA_FLAGS_ALLOC);
96+
#define DEVLINK_REGISTERED XA_MARK_1
9697

9798
/* devlink_mutex
9899
*
@@ -123,6 +124,7 @@ static struct devlink *devlink_get_from_attrs(struct net *net,
123124
struct nlattr **attrs)
124125
{
125126
struct devlink *devlink;
127+
unsigned long index;
126128
bool found = false;
127129
char *busname;
128130
char *devname;
@@ -135,7 +137,7 @@ static struct devlink *devlink_get_from_attrs(struct net *net,
135137

136138
lockdep_assert_held(&devlink_mutex);
137139

138-
list_for_each_entry(devlink, &devlink_list, list) {
140+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
139141
if (strcmp(devlink->dev->bus->name, busname) == 0 &&
140142
strcmp(dev_name(devlink->dev), devname) == 0 &&
141143
net_eq(devlink_net(devlink), net)) {
@@ -1087,11 +1089,12 @@ static int devlink_nl_cmd_rate_get_dumpit(struct sk_buff *msg,
10871089
struct devlink_rate *devlink_rate;
10881090
struct devlink *devlink;
10891091
int start = cb->args[0];
1092+
unsigned long index;
10901093
int idx = 0;
10911094
int err = 0;
10921095

10931096
mutex_lock(&devlink_mutex);
1094-
list_for_each_entry(devlink, &devlink_list, list) {
1097+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
10951098
if (!devlink_try_get(devlink))
10961099
continue;
10971100

@@ -1189,11 +1192,12 @@ static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
11891192
{
11901193
struct devlink *devlink;
11911194
int start = cb->args[0];
1195+
unsigned long index;
11921196
int idx = 0;
11931197
int err;
11941198

11951199
mutex_lock(&devlink_mutex);
1196-
list_for_each_entry(devlink, &devlink_list, list) {
1200+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
11971201
if (!devlink_try_get(devlink))
11981202
continue;
11991203

@@ -1251,11 +1255,12 @@ static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
12511255
struct devlink *devlink;
12521256
struct devlink_port *devlink_port;
12531257
int start = cb->args[0];
1258+
unsigned long index;
12541259
int idx = 0;
12551260
int err;
12561261

12571262
mutex_lock(&devlink_mutex);
1258-
list_for_each_entry(devlink, &devlink_list, list) {
1263+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
12591264
if (!devlink_try_get(devlink))
12601265
continue;
12611266

@@ -1916,11 +1921,12 @@ static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
19161921
struct devlink *devlink;
19171922
struct devlink_sb *devlink_sb;
19181923
int start = cb->args[0];
1924+
unsigned long index;
19191925
int idx = 0;
19201926
int err;
19211927

19221928
mutex_lock(&devlink_mutex);
1923-
list_for_each_entry(devlink, &devlink_list, list) {
1929+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
19241930
if (!devlink_try_get(devlink))
19251931
continue;
19261932

@@ -2067,11 +2073,12 @@ static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
20672073
struct devlink *devlink;
20682074
struct devlink_sb *devlink_sb;
20692075
int start = cb->args[0];
2076+
unsigned long index;
20702077
int idx = 0;
20712078
int err = 0;
20722079

20732080
mutex_lock(&devlink_mutex);
2074-
list_for_each_entry(devlink, &devlink_list, list) {
2081+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
20752082
if (!devlink_try_get(devlink))
20762083
continue;
20772084

@@ -2287,11 +2294,12 @@ static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
22872294
struct devlink *devlink;
22882295
struct devlink_sb *devlink_sb;
22892296
int start = cb->args[0];
2297+
unsigned long index;
22902298
int idx = 0;
22912299
int err = 0;
22922300

22932301
mutex_lock(&devlink_mutex);
2294-
list_for_each_entry(devlink, &devlink_list, list) {
2302+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
22952303
if (!devlink_try_get(devlink))
22962304
continue;
22972305

@@ -2535,11 +2543,12 @@ devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
25352543
struct devlink *devlink;
25362544
struct devlink_sb *devlink_sb;
25372545
int start = cb->args[0];
2546+
unsigned long index;
25382547
int idx = 0;
25392548
int err = 0;
25402549

25412550
mutex_lock(&devlink_mutex);
2542-
list_for_each_entry(devlink, &devlink_list, list) {
2551+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
25432552
if (!devlink_try_get(devlink))
25442553
continue;
25452554

@@ -4611,11 +4620,12 @@ static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
46114620
struct devlink_param_item *param_item;
46124621
struct devlink *devlink;
46134622
int start = cb->args[0];
4623+
unsigned long index;
46144624
int idx = 0;
46154625
int err = 0;
46164626

46174627
mutex_lock(&devlink_mutex);
4618-
list_for_each_entry(devlink, &devlink_list, list) {
4628+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
46194629
if (!devlink_try_get(devlink))
46204630
continue;
46214631

@@ -4886,11 +4896,12 @@ static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
48864896
struct devlink_port *devlink_port;
48874897
struct devlink *devlink;
48884898
int start = cb->args[0];
4899+
unsigned long index;
48894900
int idx = 0;
48904901
int err = 0;
48914902

48924903
mutex_lock(&devlink_mutex);
4893-
list_for_each_entry(devlink, &devlink_list, list) {
4904+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
48944905
if (!devlink_try_get(devlink))
48954906
continue;
48964907

@@ -5462,11 +5473,12 @@ static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg,
54625473
{
54635474
struct devlink *devlink;
54645475
int start = cb->args[0];
5476+
unsigned long index;
54655477
int idx = 0;
54665478
int err = 0;
54675479

54685480
mutex_lock(&devlink_mutex);
5469-
list_for_each_entry(devlink, &devlink_list, list) {
5481+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
54705482
if (!devlink_try_get(devlink))
54715483
continue;
54725484

@@ -5995,11 +6007,12 @@ static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
59956007
{
59966008
struct devlink *devlink;
59976009
int start = cb->args[0];
6010+
unsigned long index;
59986011
int idx = 0;
59996012
int err = 0;
60006013

60016014
mutex_lock(&devlink_mutex);
6002-
list_for_each_entry(devlink, &devlink_list, list) {
6015+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
60036016
if (!devlink_try_get(devlink))
60046017
continue;
60056018

@@ -7176,11 +7189,12 @@ devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
71767189
struct devlink_port *port;
71777190
struct devlink *devlink;
71787191
int start = cb->args[0];
7192+
unsigned long index;
71797193
int idx = 0;
71807194
int err;
71817195

71827196
mutex_lock(&devlink_mutex);
7183-
list_for_each_entry(devlink, &devlink_list, list) {
7197+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
71847198
if (!devlink_try_get(devlink))
71857199
continue;
71867200

@@ -7210,7 +7224,7 @@ devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
72107224
devlink_put(devlink);
72117225
}
72127226

7213-
list_for_each_entry(devlink, &devlink_list, list) {
7227+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
72147228
if (!devlink_try_get(devlink))
72157229
continue;
72167230

@@ -7771,11 +7785,12 @@ static int devlink_nl_cmd_trap_get_dumpit(struct sk_buff *msg,
77717785
struct devlink_trap_item *trap_item;
77727786
struct devlink *devlink;
77737787
int start = cb->args[0];
7788+
unsigned long index;
77747789
int idx = 0;
77757790
int err;
77767791

77777792
mutex_lock(&devlink_mutex);
7778-
list_for_each_entry(devlink, &devlink_list, list) {
7793+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
77797794
if (!devlink_try_get(devlink))
77807795
continue;
77817796

@@ -7997,11 +8012,12 @@ static int devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff *msg,
79978012
u32 portid = NETLINK_CB(cb->skb).portid;
79988013
struct devlink *devlink;
79998014
int start = cb->args[0];
8015+
unsigned long index;
80008016
int idx = 0;
80018017
int err;
80028018

80038019
mutex_lock(&devlink_mutex);
8004-
list_for_each_entry(devlink, &devlink_list, list) {
8020+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
80058021
if (!devlink_try_get(devlink))
80068022
continue;
80078023

@@ -8310,11 +8326,12 @@ static int devlink_nl_cmd_trap_policer_get_dumpit(struct sk_buff *msg,
83108326
u32 portid = NETLINK_CB(cb->skb).portid;
83118327
struct devlink *devlink;
83128328
int start = cb->args[0];
8329+
unsigned long index;
83138330
int idx = 0;
83148331
int err;
83158332

83168333
mutex_lock(&devlink_mutex);
8317-
list_for_each_entry(devlink, &devlink_list, list) {
8334+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
83188335
if (!devlink_try_get(devlink))
83198336
continue;
83208337

@@ -8899,6 +8916,8 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
88998916
struct device *dev)
89008917
{
89018918
struct devlink *devlink;
8919+
static u32 last_id;
8920+
int ret;
89028921

89038922
WARN_ON(!ops || !dev);
89048923
if (!devlink_reload_actions_valid(ops))
@@ -8908,6 +8927,13 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
89088927
if (!devlink)
89098928
return NULL;
89108929

8930+
ret = xa_alloc_cyclic(&devlinks, &devlink->index, devlink, xa_limit_31b,
8931+
&last_id, GFP_KERNEL);
8932+
if (ret < 0) {
8933+
kfree(devlink);
8934+
return NULL;
8935+
}
8936+
89118937
devlink->dev = dev;
89128938
devlink->ops = ops;
89138939
xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC);
@@ -8940,7 +8966,7 @@ EXPORT_SYMBOL_GPL(devlink_alloc_ns);
89408966
int devlink_register(struct devlink *devlink)
89418967
{
89428968
mutex_lock(&devlink_mutex);
8943-
list_add_tail(&devlink->list, &devlink_list);
8969+
xa_set_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
89448970
devlink_notify(devlink, DEVLINK_CMD_NEW);
89458971
mutex_unlock(&devlink_mutex);
89468972
return 0;
@@ -8961,7 +8987,7 @@ void devlink_unregister(struct devlink *devlink)
89618987
WARN_ON(devlink_reload_supported(devlink->ops) &&
89628988
devlink->reload_enabled);
89638989
devlink_notify(devlink, DEVLINK_CMD_DEL);
8964-
list_del(&devlink->list);
8990+
xa_clear_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
89658991
mutex_unlock(&devlink_mutex);
89668992
}
89678993
EXPORT_SYMBOL_GPL(devlink_unregister);
@@ -9023,6 +9049,7 @@ void devlink_free(struct devlink *devlink)
90239049
WARN_ON(!list_empty(&devlink->port_list));
90249050

90259051
xa_destroy(&devlink->snapshot_ids);
9052+
xa_erase(&devlinks, devlink->index);
90269053

90279054
kfree(devlink);
90289055
}
@@ -11497,13 +11524,14 @@ static void __net_exit devlink_pernet_pre_exit(struct net *net)
1149711524
{
1149811525
struct devlink *devlink;
1149911526
u32 actions_performed;
11527+
unsigned long index;
1150011528
int err;
1150111529

1150211530
/* In case network namespace is getting destroyed, reload
1150311531
* all devlink instances from this namespace into init_net.
1150411532
*/
1150511533
mutex_lock(&devlink_mutex);
11506-
list_for_each_entry(devlink, &devlink_list, list) {
11534+
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
1150711535
if (!devlink_try_get(devlink))
1150811536
continue;
1150911537

0 commit comments

Comments
 (0)