Skip to content

Commit e099e86

Browse files
Jon Paul Maloydavem330
authored andcommitted
tipc: add node_lock protection to link lookup function
In an earlier commit, ("tipc: remove links list from bearer struct") we described three issues that need to be pre-emptively resolved before we can remove tipc_net_lock. Here we resolve issue a) described in that commit: "a) In access method #2, we access the link before taking the protecting node_lock. This will not work once net_lock is gone, so we will have to change the access order. We will deal with this in a later commit in this series." Here, we change that access order, by ensuring that the function link_find_link() returns only a safe reference for finding the link, i.e., a node pointer and an index into its 'links' array, not the link pointer itself. We also change all callers of this function to first take the node lock before they can check if there still is a valid link pointer at the returned index. Since the function now returns a node pointer rather than a link pointer, we rename it to the more appropriate 'tipc_link_find_owner(). Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent a830452 commit e099e86

File tree

1 file changed

+65
-45
lines changed

1 file changed

+65
-45
lines changed

net/tipc/link.c

Lines changed: 65 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2390,35 +2390,40 @@ void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window)
23902390
l_ptr->queue_limit[MSG_FRAGMENTER] = 4000;
23912391
}
23922392

2393-
/**
2394-
* link_find_link - locate link by name
2395-
* @name: ptr to link name string
2396-
* @node: ptr to area to be filled with ptr to associated node
2397-
*
2393+
/* tipc_link_find_owner - locate owner node of link by link's name
2394+
* @name: pointer to link name string
2395+
* @bearer_id: pointer to index in 'node->links' array where the link was found.
23982396
* Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted;
23992397
* this also prevents link deletion.
24002398
*
2401-
* Returns pointer to link (or 0 if invalid link name).
2399+
* Returns pointer to node owning the link, or 0 if no matching link is found.
24022400
*/
2403-
static struct tipc_link *link_find_link(const char *name,
2404-
struct tipc_node **node)
2401+
static struct tipc_node *tipc_link_find_owner(const char *link_name,
2402+
unsigned int *bearer_id)
24052403
{
24062404
struct tipc_link *l_ptr;
24072405
struct tipc_node *n_ptr;
2406+
struct tipc_node *tmp_n_ptr;
2407+
struct tipc_node *found_node = 0;
2408+
24082409
int i;
24092410

2410-
list_for_each_entry(n_ptr, &tipc_node_list, list) {
2411+
*bearer_id = 0;
2412+
list_for_each_entry_safe(n_ptr, tmp_n_ptr, &tipc_node_list, list) {
2413+
spin_lock(&n_ptr->lock);
24112414
for (i = 0; i < MAX_BEARERS; i++) {
24122415
l_ptr = n_ptr->links[i];
2413-
if (l_ptr && !strcmp(l_ptr->name, name))
2414-
goto found;
2416+
if (l_ptr && !strcmp(l_ptr->name, link_name)) {
2417+
*bearer_id = i;
2418+
found_node = n_ptr;
2419+
break;
2420+
}
24152421
}
2422+
spin_unlock(&n_ptr->lock);
2423+
if (found_node)
2424+
break;
24162425
}
2417-
l_ptr = NULL;
2418-
n_ptr = NULL;
2419-
found:
2420-
*node = n_ptr;
2421-
return l_ptr;
2426+
return found_node;
24222427
}
24232428

24242429
/**
@@ -2460,32 +2465,33 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd)
24602465
struct tipc_link *l_ptr;
24612466
struct tipc_bearer *b_ptr;
24622467
struct tipc_media *m_ptr;
2468+
int bearer_id;
24632469
int res = 0;
24642470

2465-
l_ptr = link_find_link(name, &node);
2466-
if (l_ptr) {
2467-
/*
2468-
* acquire node lock for tipc_link_send_proto_msg().
2469-
* see "TIPC locking policy" in net.c.
2470-
*/
2471+
node = tipc_link_find_owner(name, &bearer_id);
2472+
if (node) {
24712473
tipc_node_lock(node);
2472-
switch (cmd) {
2473-
case TIPC_CMD_SET_LINK_TOL:
2474-
link_set_supervision_props(l_ptr, new_value);
2475-
tipc_link_send_proto_msg(l_ptr,
2476-
STATE_MSG, 0, 0, new_value, 0, 0);
2477-
break;
2478-
case TIPC_CMD_SET_LINK_PRI:
2479-
l_ptr->priority = new_value;
2480-
tipc_link_send_proto_msg(l_ptr,
2481-
STATE_MSG, 0, 0, 0, new_value, 0);
2482-
break;
2483-
case TIPC_CMD_SET_LINK_WINDOW:
2484-
tipc_link_set_queue_limits(l_ptr, new_value);
2485-
break;
2486-
default:
2487-
res = -EINVAL;
2488-
break;
2474+
l_ptr = node->links[bearer_id];
2475+
2476+
if (l_ptr) {
2477+
switch (cmd) {
2478+
case TIPC_CMD_SET_LINK_TOL:
2479+
link_set_supervision_props(l_ptr, new_value);
2480+
tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0,
2481+
0, new_value, 0, 0);
2482+
break;
2483+
case TIPC_CMD_SET_LINK_PRI:
2484+
l_ptr->priority = new_value;
2485+
tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0,
2486+
0, 0, new_value, 0);
2487+
break;
2488+
case TIPC_CMD_SET_LINK_WINDOW:
2489+
tipc_link_set_queue_limits(l_ptr, new_value);
2490+
break;
2491+
default:
2492+
res = -EINVAL;
2493+
break;
2494+
}
24892495
}
24902496
tipc_node_unlock(node);
24912497
return res;
@@ -2580,6 +2586,7 @@ struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_
25802586
char *link_name;
25812587
struct tipc_link *l_ptr;
25822588
struct tipc_node *node;
2589+
unsigned int bearer_id;
25832590

25842591
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
25852592
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -2590,15 +2597,19 @@ struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_
25902597
return tipc_cfg_reply_error_string("link not found");
25912598
return tipc_cfg_reply_none();
25922599
}
2593-
25942600
read_lock_bh(&tipc_net_lock);
2595-
l_ptr = link_find_link(link_name, &node);
2601+
node = tipc_link_find_owner(link_name, &bearer_id);
2602+
if (!node) {
2603+
read_unlock_bh(&tipc_net_lock);
2604+
return tipc_cfg_reply_error_string("link not found");
2605+
}
2606+
spin_lock(&node->lock);
2607+
l_ptr = node->links[bearer_id];
25962608
if (!l_ptr) {
2609+
tipc_node_unlock(node);
25972610
read_unlock_bh(&tipc_net_lock);
25982611
return tipc_cfg_reply_error_string("link not found");
25992612
}
2600-
2601-
tipc_node_lock(node);
26022613
link_reset_statistics(l_ptr);
26032614
tipc_node_unlock(node);
26042615
read_unlock_bh(&tipc_net_lock);
@@ -2628,18 +2639,27 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
26282639
struct tipc_node *node;
26292640
char *status;
26302641
u32 profile_total = 0;
2642+
unsigned int bearer_id;
26312643
int ret;
26322644

26332645
if (!strcmp(name, tipc_bclink_name))
26342646
return tipc_bclink_stats(buf, buf_size);
26352647

26362648
read_lock_bh(&tipc_net_lock);
2637-
l = link_find_link(name, &node);
2638-
if (!l) {
2649+
node = tipc_link_find_owner(name, &bearer_id);
2650+
if (!node) {
26392651
read_unlock_bh(&tipc_net_lock);
26402652
return 0;
26412653
}
26422654
tipc_node_lock(node);
2655+
2656+
l = node->links[bearer_id];
2657+
if (!l) {
2658+
tipc_node_unlock(node);
2659+
read_unlock_bh(&tipc_net_lock);
2660+
return 0;
2661+
}
2662+
26432663
s = &l->stats;
26442664

26452665
if (tipc_link_is_active(l))

0 commit comments

Comments
 (0)