Commit ca52b664 authored by David S. Miller's avatar David S. Miller

Merge branch 'tipc'

Jon Maloy says:

====================
tipc: clean up media and bearer layer

This commit series aims at facilitating future changes to the
locking policy around nodes, links and bearers.

Currently, we have a big read/write lock (net_lock) that is used for
serializing all changes to the node, link and bearer lists, as well
as to their mutual pointers and references.

But, in order to allow for concurrent access to the contents of these
structures, net_lock is only used in read mode by the data path code,
and hence a finer granular locking policy must be applied inside the
scope of net_lock: a spinlock (node_lock) for each node structure,
and another one (bearer_lock) for protection of bearer structures.

This locking policy has proved hard to maintain. We have several
times encountered contention problems between node_lock and
bearer_lock, and with the advent of the RCU locking mechanism we
feel it is anyway obsolete and ripe for improvements.

We now plan to replace net_lock with an RCU lock, as well as
getting rid of bearer_lock altogether. This will both reduce data
path overhead and make the code more manageable, while reducing the
risk of future lock contention problems.

Prior to these changes, we need to do some necessary cleanup and
code consolidation. This is what we do with this commit series,
before we finally remove bearer_lock. In a later series we will
replace net_lock with an RCU lock.

v2:
 - Re-inserted a removed kerneldoc entry in commit#5, based on
   feedback from D. Miller.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b3f0f5c3 e099e86c
...@@ -481,7 +481,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) ...@@ -481,7 +481,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
tipc_link_recv_bundle(buf); tipc_link_recv_bundle(buf);
} else if (msg_user(msg) == MSG_FRAGMENTER) { } else if (msg_user(msg) == MSG_FRAGMENTER) {
int ret; int ret;
ret = tipc_link_recv_fragment(&node->bclink.reasm_head, ret = tipc_link_frag_rcv(&node->bclink.reasm_head,
&node->bclink.reasm_tail, &node->bclink.reasm_tail,
&buf); &buf);
if (ret == LINK_REASM_ERROR) if (ret == LINK_REASM_ERROR)
...@@ -785,7 +785,6 @@ void tipc_bclink_init(void) ...@@ -785,7 +785,6 @@ void tipc_bclink_init(void)
bcl->owner = &bclink->node; bcl->owner = &bclink->node;
bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
spin_lock_init(&bcbearer->bearer.lock);
bcl->b_ptr = &bcbearer->bearer; bcl->b_ptr = &bcbearer->bearer;
bcl->state = WORKING_WORKING; bcl->state = WORKING_WORKING;
strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME); strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME);
......
...@@ -51,7 +51,7 @@ static struct tipc_media * const media_info_array[] = { ...@@ -51,7 +51,7 @@ static struct tipc_media * const media_info_array[] = {
struct tipc_bearer tipc_bearers[MAX_BEARERS]; struct tipc_bearer tipc_bearers[MAX_BEARERS];
static void bearer_disable(struct tipc_bearer *b_ptr); static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
/** /**
* tipc_media_find - locates specified media object by name * tipc_media_find - locates specified media object by name
...@@ -327,12 +327,10 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) ...@@ -327,12 +327,10 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
b_ptr->net_plane = bearer_id + 'A'; b_ptr->net_plane = bearer_id + 'A';
b_ptr->active = 1; b_ptr->active = 1;
b_ptr->priority = priority; b_ptr->priority = priority;
INIT_LIST_HEAD(&b_ptr->links);
spin_lock_init(&b_ptr->lock);
res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr, disc_domain); res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr, disc_domain);
if (res) { if (res) {
bearer_disable(b_ptr); bearer_disable(b_ptr, false);
pr_warn("Bearer <%s> rejected, discovery object creation failed\n", pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
name); name);
goto exit; goto exit;
...@@ -350,20 +348,9 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) ...@@ -350,20 +348,9 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
*/ */
static int tipc_reset_bearer(struct tipc_bearer *b_ptr) static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
{ {
struct tipc_link *l_ptr;
struct tipc_link *temp_l_ptr;
read_lock_bh(&tipc_net_lock); read_lock_bh(&tipc_net_lock);
pr_info("Resetting bearer <%s>\n", b_ptr->name); pr_info("Resetting bearer <%s>\n", b_ptr->name);
spin_lock_bh(&b_ptr->lock); tipc_link_reset_list(b_ptr->identity);
list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
struct tipc_node *n_ptr = l_ptr->owner;
spin_lock_bh(&n_ptr->lock);
tipc_link_reset(l_ptr);
spin_unlock_bh(&n_ptr->lock);
}
spin_unlock_bh(&b_ptr->lock);
read_unlock_bh(&tipc_net_lock); read_unlock_bh(&tipc_net_lock);
return 0; return 0;
} }
...@@ -373,25 +360,14 @@ static int tipc_reset_bearer(struct tipc_bearer *b_ptr) ...@@ -373,25 +360,14 @@ static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
* *
* Note: This routine assumes caller holds tipc_net_lock. * Note: This routine assumes caller holds tipc_net_lock.
*/ */
static void bearer_disable(struct tipc_bearer *b_ptr) static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
{ {
struct tipc_link *l_ptr;
struct tipc_link *temp_l_ptr;
struct tipc_link_req *temp_req;
pr_info("Disabling bearer <%s>\n", b_ptr->name); pr_info("Disabling bearer <%s>\n", b_ptr->name);
spin_lock_bh(&b_ptr->lock);
b_ptr->media->disable_media(b_ptr); b_ptr->media->disable_media(b_ptr);
list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
tipc_link_delete(l_ptr);
}
temp_req = b_ptr->link_req;
b_ptr->link_req = NULL;
spin_unlock_bh(&b_ptr->lock);
if (temp_req)
tipc_disc_delete(temp_req);
tipc_link_delete_list(b_ptr->identity, shutting_down);
if (b_ptr->link_req)
tipc_disc_delete(b_ptr->link_req);
memset(b_ptr, 0, sizeof(struct tipc_bearer)); memset(b_ptr, 0, sizeof(struct tipc_bearer));
} }
...@@ -406,7 +382,7 @@ int tipc_disable_bearer(const char *name) ...@@ -406,7 +382,7 @@ int tipc_disable_bearer(const char *name)
pr_warn("Attempt to disable unknown bearer <%s>\n", name); pr_warn("Attempt to disable unknown bearer <%s>\n", name);
res = -EINVAL; res = -EINVAL;
} else { } else {
bearer_disable(b_ptr); bearer_disable(b_ptr, false);
res = 0; res = 0;
} }
write_unlock_bh(&tipc_net_lock); write_unlock_bh(&tipc_net_lock);
...@@ -626,6 +602,6 @@ void tipc_bearer_stop(void) ...@@ -626,6 +602,6 @@ void tipc_bearer_stop(void)
for (i = 0; i < MAX_BEARERS; i++) { for (i = 0; i < MAX_BEARERS; i++) {
if (tipc_bearers[i].active) if (tipc_bearers[i].active)
bearer_disable(&tipc_bearers[i]); bearer_disable(&tipc_bearers[i], true);
} }
} }
...@@ -107,10 +107,8 @@ struct tipc_media { ...@@ -107,10 +107,8 @@ struct tipc_media {
/** /**
* struct tipc_bearer - Generic TIPC bearer structure * struct tipc_bearer - Generic TIPC bearer structure
* @dev: ptr to associated network device * @media_ptr: pointer to additional media-specific information about bearer
* @usr_handle: pointer to additional media-specific information about bearer
* @mtu: max packet size bearer can support * @mtu: max packet size bearer can support
* @lock: spinlock for controlling access to bearer
* @addr: media-specific address associated with bearer * @addr: media-specific address associated with bearer
* @name: bearer name (format = media:interface) * @name: bearer name (format = media:interface)
* @media: ptr to media structure associated with bearer * @media: ptr to media structure associated with bearer
...@@ -120,7 +118,6 @@ struct tipc_media { ...@@ -120,7 +118,6 @@ struct tipc_media {
* @tolerance: default link tolerance for bearer * @tolerance: default link tolerance for bearer
* @identity: array index of this bearer within TIPC bearer array * @identity: array index of this bearer within TIPC bearer array
* @link_req: ptr to (optional) structure making periodic link setup requests * @link_req: ptr to (optional) structure making periodic link setup requests
* @links: list of non-congested links associated with bearer
* @active: non-zero if bearer structure is represents a bearer * @active: non-zero if bearer structure is represents a bearer
* @net_plane: network plane ('A' through 'H') currently associated with bearer * @net_plane: network plane ('A' through 'H') currently associated with bearer
* @nodes: indicates which nodes in cluster can be reached through bearer * @nodes: indicates which nodes in cluster can be reached through bearer
...@@ -134,7 +131,6 @@ struct tipc_bearer { ...@@ -134,7 +131,6 @@ struct tipc_bearer {
u32 mtu; /* initalized by media */ u32 mtu; /* initalized by media */
struct tipc_media_addr addr; /* initalized by media */ struct tipc_media_addr addr; /* initalized by media */
char name[TIPC_MAX_BEARER_NAME]; char name[TIPC_MAX_BEARER_NAME];
spinlock_t lock;
struct tipc_media *media; struct tipc_media *media;
struct tipc_media_addr bcast_addr; struct tipc_media_addr bcast_addr;
u32 priority; u32 priority;
...@@ -142,7 +138,6 @@ struct tipc_bearer { ...@@ -142,7 +138,6 @@ struct tipc_bearer {
u32 tolerance; u32 tolerance;
u32 identity; u32 identity;
struct tipc_link_req *link_req; struct tipc_link_req *link_req;
struct list_head links;
int active; int active;
char net_plane; char net_plane;
struct tipc_node_map nodes; struct tipc_node_map nodes;
......
/* /*
* net/tipc/core.c: TIPC module code * net/tipc/core.c: TIPC module code
* *
* Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2003-2006, 2013, Ericsson AB
* Copyright (c) 2005-2006, 2010-2013, Wind River Systems * Copyright (c) 2005-2006, 2010-2013, Wind River Systems
* All rights reserved. * All rights reserved.
* *
......
This diff is collapsed.
/* /*
* net/tipc/link.h: Include file for TIPC link code * net/tipc/link.h: Include file for TIPC link code
* *
* Copyright (c) 1995-2006, Ericsson AB * Copyright (c) 1995-2006, 2013, Ericsson AB
* Copyright (c) 2004-2005, 2010-2011, Wind River Systems * Copyright (c) 2004-2005, 2010-2011, Wind River Systems
* All rights reserved. * All rights reserved.
* *
...@@ -40,27 +40,28 @@ ...@@ -40,27 +40,28 @@
#include "msg.h" #include "msg.h"
#include "node.h" #include "node.h"
/* /* Link reassembly status codes
* Link reassembly status codes
*/ */
#define LINK_REASM_ERROR -1 #define LINK_REASM_ERROR -1
#define LINK_REASM_COMPLETE 1 #define LINK_REASM_COMPLETE 1
/* /* Out-of-range value for link sequence numbers
* Out-of-range value for link sequence numbers
*/ */
#define INVALID_LINK_SEQ 0x10000 #define INVALID_LINK_SEQ 0x10000
/* /* Link working states
* Link states
*/ */
#define WORKING_WORKING 560810u #define WORKING_WORKING 560810u
#define WORKING_UNKNOWN 560811u #define WORKING_UNKNOWN 560811u
#define RESET_UNKNOWN 560812u #define RESET_UNKNOWN 560812u
#define RESET_RESET 560813u #define RESET_RESET 560813u
/* /* Link endpoint execution states
* Starting value for maximum packet size negotiation on unicast links */
#define LINK_STARTED 0x0001
#define LINK_STOPPED 0x0002
/* Starting value for maximum packet size negotiation on unicast links
* (unless bearer MTU is less) * (unless bearer MTU is less)
*/ */
#define MAX_PKT_DEFAULT 1500 #define MAX_PKT_DEFAULT 1500
...@@ -102,8 +103,7 @@ struct tipc_stats { ...@@ -102,8 +103,7 @@ struct tipc_stats {
* @media_addr: media address to use when sending messages over link * @media_addr: media address to use when sending messages over link
* @timer: link timer * @timer: link timer
* @owner: pointer to peer node * @owner: pointer to peer node
* @link_list: adjacent links in bearer's list of links * @flags: execution state flags for link endpoint instance
* @started: indicates if link has been started
* @checkpoint: reference point for triggering link continuity checking * @checkpoint: reference point for triggering link continuity checking
* @peer_session: link session # being used by peer end of link * @peer_session: link session # being used by peer end of link
* @peer_bearer_id: bearer id used by link's peer endpoint * @peer_bearer_id: bearer id used by link's peer endpoint
...@@ -149,10 +149,9 @@ struct tipc_link { ...@@ -149,10 +149,9 @@ struct tipc_link {
struct tipc_media_addr media_addr; struct tipc_media_addr media_addr;
struct timer_list timer; struct timer_list timer;
struct tipc_node *owner; struct tipc_node *owner;
struct list_head link_list;
/* Management and link supervision data */ /* Management and link supervision data */
int started; unsigned int flags;
u32 checkpoint; u32 checkpoint;
u32 peer_session; u32 peer_session;
u32 peer_bearer_id; u32 peer_bearer_id;
...@@ -215,7 +214,7 @@ struct tipc_port; ...@@ -215,7 +214,7 @@ struct tipc_port;
struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
struct tipc_bearer *b_ptr, struct tipc_bearer *b_ptr,
const struct tipc_media_addr *media_addr); const struct tipc_media_addr *media_addr);
void tipc_link_delete(struct tipc_link *l_ptr); void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down);
void tipc_link_failover_send_queue(struct tipc_link *l_ptr); void tipc_link_failover_send_queue(struct tipc_link *l_ptr);
void tipc_link_dup_send_queue(struct tipc_link *l_ptr, void tipc_link_dup_send_queue(struct tipc_link *l_ptr,
struct tipc_link *dest); struct tipc_link *dest);
...@@ -231,6 +230,7 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, ...@@ -231,6 +230,7 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area,
struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area,
int req_tlv_space); int req_tlv_space);
void tipc_link_reset(struct tipc_link *l_ptr); void tipc_link_reset(struct tipc_link *l_ptr);
void tipc_link_reset_list(unsigned int bearer_id);
int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector); int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector);
void tipc_link_send_names(struct list_head *message_list, u32 dest); void tipc_link_send_names(struct list_head *message_list, u32 dest);
int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf); int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf);
...@@ -239,7 +239,7 @@ int tipc_link_send_sections_fast(struct tipc_port *sender, ...@@ -239,7 +239,7 @@ int tipc_link_send_sections_fast(struct tipc_port *sender,
struct iovec const *msg_sect, struct iovec const *msg_sect,
unsigned int len, u32 destnode); unsigned int len, u32 destnode);
void tipc_link_recv_bundle(struct sk_buff *buf); void tipc_link_recv_bundle(struct sk_buff *buf);
int tipc_link_recv_fragment(struct sk_buff **reasm_head, int tipc_link_frag_rcv(struct sk_buff **reasm_head,
struct sk_buff **reasm_tail, struct sk_buff **reasm_tail,
struct sk_buff **fbuf); struct sk_buff **fbuf);
void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, int prob, void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, int prob,
......
...@@ -249,7 +249,13 @@ void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) ...@@ -249,7 +249,13 @@ void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
{ {
n_ptr->links[l_ptr->b_ptr->identity] = NULL; int i;
for (i = 0; i < MAX_BEARERS; i++) {
if (l_ptr == n_ptr->links[i])
break;
}
n_ptr->links[i] = NULL;
atomic_dec(&tipc_num_links); atomic_dec(&tipc_num_links);
n_ptr->link_cnt--; n_ptr->link_cnt--;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment