Skip to content

Commit

Permalink
Merge branch 'tipc-next'
Browse files Browse the repository at this point in the history
Ying Xue says:

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

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

Currently, the tipc routing hierarchy comprises the structures 'node',
'link' and 'bearer'. The whole hierarchy is protected by a big
read/write lock (tipc_net_lock), to ensure that nothing is added or
removed while any of these structures is being accessed. Obviously
the locking policy makes node, link and bearer components closely
bound together so that their relationship becomes extremely complex.
In the worst case, such locking policy not only has a negative
influence on performance, but also it's prone to lead to deadlock
occasionally.

In order to decouple the complex relationship between bearer and node
as well as link, the locking policy is adjusted as follows:

- Bearer level
  RTNL lock is used on update side, and RCU is used on read side.
  Meanwhile, all bearer instances including broadcast bearer are
  saved into bearer_list array.

- Node and link level
  All node instances are saved into two tipc_node_list and node_htable
  lists. The two lists are protected by node_list_lock on write side,
  and they are guarded with RCU lock on read side. All members in node
  structure including link instances are protected by node spin lock.

- The relationship between bearer and node
  When link accesses bearer, it first needs to find the bearer with
  its bearer identity from the bearer_list array. When bearer accesses
  node, it can iterate the node_htable hash list with the node address
  to find the corresponding node.

In the new locking policy, every component has its private locking
solution and the relationship between bearer and node is very simple,
that is, they can find each other with node address or bearer identity
from node_htable hash list or bearer_list array.

But, prior to these changes, we need to do some necessary cleanup and
code consolidation. This is what we do with this commit series. In a
later series we will replace net_lock with RTNL as well as RCU lock
to deploy the new locking policy.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 27, 2014
2 parents 1dbe136 + dde2026 commit b5b6bc3
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 217 deletions.
13 changes: 7 additions & 6 deletions net/tipc/bcast.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@
#include "bcast.h"
#include "name_distr.h"

#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */

#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */
#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */
#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */
#define BCBEARER MAX_BEARERS

/**
* struct tipc_bcbearer_pair - a pair of bearers used by broadcast link
Expand Down Expand Up @@ -668,9 +668,8 @@ void tipc_bcbearer_sort(void)
memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp));

for (b_index = 0; b_index < MAX_BEARERS; b_index++) {
struct tipc_bearer *b = &tipc_bearers[b_index];

if (!b->active || !b->nodes.count)
struct tipc_bearer *b = bearer_list[b_index];
if (!b || !b->nodes.count)
continue;

if (!bp_temp[b->priority].primary)
Expand Down Expand Up @@ -785,6 +784,7 @@ void tipc_bclink_init(void)
bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
bcl->b_ptr = &bcbearer->bearer;
bearer_list[BCBEARER] = &bcbearer->bearer;
bcl->state = WORKING_WORKING;
strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME);
}
Expand All @@ -795,6 +795,7 @@ void tipc_bclink_stop(void)
tipc_link_purge_queues(bcl);
spin_unlock_bh(&bc_lock);

bearer_list[BCBEARER] = NULL;
memset(bclink, 0, sizeof(*bclink));
memset(bcbearer, 0, sizeof(*bcbearer));
}
Expand Down
49 changes: 36 additions & 13 deletions net/tipc/bearer.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static struct tipc_media * const media_info_array[] = {
NULL
};

struct tipc_bearer tipc_bearers[MAX_BEARERS];
struct tipc_bearer *bearer_list[MAX_BEARERS + 1];

static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);

Expand Down Expand Up @@ -177,8 +177,9 @@ struct tipc_bearer *tipc_bearer_find(const char *name)
struct tipc_bearer *b_ptr;
u32 i;

for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
if (b_ptr->active && (!strcmp(b_ptr->name, name)))
for (i = 0; i < MAX_BEARERS; i++) {
b_ptr = bearer_list[i];
if (b_ptr && (!strcmp(b_ptr->name, name)))
return b_ptr;
}
return NULL;
Expand All @@ -200,8 +201,10 @@ struct sk_buff *tipc_bearer_get_names(void)
read_lock_bh(&tipc_net_lock);
for (i = 0; media_info_array[i] != NULL; i++) {
for (j = 0; j < MAX_BEARERS; j++) {
b = &tipc_bearers[j];
if (b->active && (b->media == media_info_array[i])) {
b = bearer_list[j];
if (!b)
continue;
if (b->media == media_info_array[i]) {
tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
b->name,
strlen(b->name) + 1);
Expand Down Expand Up @@ -284,16 +287,17 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
bearer_id = MAX_BEARERS;
with_this_prio = 1;
for (i = MAX_BEARERS; i-- != 0; ) {
if (!tipc_bearers[i].active) {
b_ptr = bearer_list[i];
if (!b_ptr) {
bearer_id = i;
continue;
}
if (!strcmp(name, tipc_bearers[i].name)) {
if (!strcmp(name, b_ptr->name)) {
pr_warn("Bearer <%s> rejected, already enabled\n",
name);
goto exit;
}
if ((tipc_bearers[i].priority == priority) &&
if ((b_ptr->priority == priority) &&
(++with_this_prio > 2)) {
if (priority-- == 0) {
pr_warn("Bearer <%s> rejected, duplicate priority\n",
Expand All @@ -311,7 +315,11 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
goto exit;
}

b_ptr = &tipc_bearers[bearer_id];
b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC);
if (!b_ptr) {
res = -ENOMEM;
goto exit;
}
strcpy(b_ptr->name, name);
b_ptr->media = m_ptr;
res = m_ptr->enable_media(b_ptr);
Expand All @@ -325,7 +333,6 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
b_ptr->tolerance = m_ptr->tolerance;
b_ptr->window = m_ptr->window;
b_ptr->net_plane = bearer_id + 'A';
b_ptr->active = 1;
b_ptr->priority = priority;

res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr, disc_domain);
Expand All @@ -335,6 +342,9 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
name);
goto exit;
}

bearer_list[bearer_id] = b_ptr;

pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
name,
tipc_addr_string_fill(addr_string, disc_domain), priority);
Expand Down Expand Up @@ -362,13 +372,22 @@ static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
*/
static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
{
u32 i;

pr_info("Disabling bearer <%s>\n", b_ptr->name);
b_ptr->media->disable_media(b_ptr);

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));

for (i = 0; i < MAX_BEARERS; i++) {
if (b_ptr == bearer_list[i]) {
bearer_list[i] = NULL;
break;
}
}
kfree(b_ptr);
}

int tipc_disable_bearer(const char *name)
Expand Down Expand Up @@ -603,10 +622,14 @@ void tipc_bearer_cleanup(void)

void tipc_bearer_stop(void)
{
struct tipc_bearer *b_ptr;
u32 i;

for (i = 0; i < MAX_BEARERS; i++) {
if (tipc_bearers[i].active)
bearer_disable(&tipc_bearers[i], true);
b_ptr = bearer_list[i];
if (b_ptr) {
bearer_disable(b_ptr, true);
bearer_list[i] = NULL;
}
}
}
4 changes: 1 addition & 3 deletions net/tipc/bearer.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ struct tipc_media {
* @tolerance: default link tolerance for bearer
* @identity: array index of this bearer within TIPC bearer array
* @link_req: ptr to (optional) structure making periodic link setup requests
* @active: non-zero if bearer structure is represents a bearer
* @net_plane: network plane ('A' through 'H') currently associated with bearer
* @nodes: indicates which nodes in cluster can be reached through bearer
*
Expand All @@ -138,7 +137,6 @@ struct tipc_bearer {
u32 tolerance;
u32 identity;
struct tipc_link_req *link_req;
int active;
char net_plane;
struct tipc_node_map nodes;
};
Expand All @@ -150,7 +148,7 @@ struct tipc_bearer_names {

struct tipc_link;

extern struct tipc_bearer tipc_bearers[];
extern struct tipc_bearer *bearer_list[];

/*
* TIPC routines available to supported media types
Expand Down
107 changes: 3 additions & 104 deletions net/tipc/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,11 @@
#define REPLY_TRUNCATED "<truncated>\n"

static DEFINE_MUTEX(config_mutex);
static struct tipc_server cfgsrv;

static const void *req_tlv_area; /* request message TLV area */
static int req_tlv_space; /* request message TLV area size */
static int rep_headroom; /* reply message headroom to use */


struct sk_buff *tipc_cfg_reply_alloc(int payload_size)
{
struct sk_buff *buf;
Expand Down Expand Up @@ -185,18 +183,6 @@ static struct sk_buff *cfg_set_own_addr(void)
return tipc_cfg_reply_none();
}

static struct sk_buff *cfg_set_remote_mng(void)
{
u32 value;

if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);

value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
tipc_remote_management = (value != 0);
return tipc_cfg_reply_none();
}

static struct sk_buff *cfg_set_max_ports(void)
{
u32 value;
Expand Down Expand Up @@ -247,21 +233,10 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
/* Check command authorization */
if (likely(in_own_node(orig_node))) {
/* command is permitted */
} else if (cmd >= 0x8000) {
} else {
rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (cannot be done remotely)");
goto exit;
} else if (!tipc_remote_management) {
rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE);
goto exit;
} else if (cmd >= 0x4000) {
u32 domain = 0;

if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) ||
(domain != orig_node)) {
rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR);
goto exit;
}
}

/* Call appropriate processing routine */
Expand Down Expand Up @@ -310,18 +285,12 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
case TIPC_CMD_SET_NODE_ADDR:
rep_tlv_buf = cfg_set_own_addr();
break;
case TIPC_CMD_SET_REMOTE_MNG:
rep_tlv_buf = cfg_set_remote_mng();
break;
case TIPC_CMD_SET_MAX_PORTS:
rep_tlv_buf = cfg_set_max_ports();
break;
case TIPC_CMD_SET_NETID:
rep_tlv_buf = cfg_set_netid();
break;
case TIPC_CMD_GET_REMOTE_MNG:
rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management);
break;
case TIPC_CMD_GET_MAX_PORTS:
rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports);
break;
Expand All @@ -345,6 +314,8 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
case TIPC_CMD_SET_MAX_PUBL:
case TIPC_CMD_GET_MAX_PUBL:
case TIPC_CMD_SET_LOG_SIZE:
case TIPC_CMD_SET_REMOTE_MNG:
case TIPC_CMD_GET_REMOTE_MNG:
case TIPC_CMD_DUMP_LOG:
rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (obsolete command)");
Expand All @@ -369,75 +340,3 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
mutex_unlock(&config_mutex);
return rep_tlv_buf;
}

static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr,
void *usr_data, void *buf, size_t len)
{
struct tipc_cfg_msg_hdr *req_hdr;
struct tipc_cfg_msg_hdr *rep_hdr;
struct sk_buff *rep_buf;

/* Validate configuration message header (ignore invalid message) */
req_hdr = (struct tipc_cfg_msg_hdr *)buf;
if ((len < sizeof(*req_hdr)) ||
(len != TCM_ALIGN(ntohl(req_hdr->tcm_len))) ||
(ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) {
pr_warn("Invalid configuration message discarded\n");
return;
}

/* Generate reply for request (if can't, return request) */
rep_buf = tipc_cfg_do_cmd(addr->addr.id.node, ntohs(req_hdr->tcm_type),
buf + sizeof(*req_hdr),
len - sizeof(*req_hdr),
BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr));
if (rep_buf) {
skb_push(rep_buf, sizeof(*rep_hdr));
rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data;
memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr));
rep_hdr->tcm_len = htonl(rep_buf->len);
rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST);
tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data,
rep_buf->len);
kfree_skb(rep_buf);
}
}

static struct sockaddr_tipc cfgsrv_addr __read_mostly = {
.family = AF_TIPC,
.addrtype = TIPC_ADDR_NAMESEQ,
.addr.nameseq.type = TIPC_CFG_SRV,
.addr.nameseq.lower = 0,
.addr.nameseq.upper = 0,
.scope = TIPC_ZONE_SCOPE
};

static struct tipc_server cfgsrv __read_mostly = {
.saddr = &cfgsrv_addr,
.imp = TIPC_CRITICAL_IMPORTANCE,
.type = SOCK_RDM,
.max_rcvbuf_size = 64 * 1024,
.name = "cfg_server",
.tipc_conn_recvmsg = cfg_conn_msg_event,
.tipc_conn_new = NULL,
.tipc_conn_shutdown = NULL
};

int tipc_cfg_init(void)
{
return tipc_server_start(&cfgsrv);
}

void tipc_cfg_reinit(void)
{
tipc_server_stop(&cfgsrv);

cfgsrv_addr.addr.nameseq.lower = tipc_own_addr;
cfgsrv_addr.addr.nameseq.upper = tipc_own_addr;
tipc_server_start(&cfgsrv);
}

void tipc_cfg_stop(void)
{
tipc_server_stop(&cfgsrv);
}
5 changes: 0 additions & 5 deletions net/tipc/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,4 @@ static inline struct sk_buff *tipc_cfg_reply_ultra_string(char *string)
struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd,
const void *req_tlv_area, int req_tlv_space,
int headroom);

int tipc_cfg_init(void);
void tipc_cfg_reinit(void);
void tipc_cfg_stop(void);

#endif
Loading

0 comments on commit b5b6bc3

Please sign in to comment.