diff --git a/net/tipc/config.c b/net/tipc/config.c index 2b42403ad33a690221456ff25fb4be50a2235255..876f4c6a2631b35eba2b9927430b30c34d125c87 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -35,7 +35,7 @@ */ #include "core.h" -#include "port.h" +#include "socket.h" #include "name_table.h" #include "config.h" #include "server.h" @@ -266,7 +266,7 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area rep_tlv_buf = tipc_media_get_names(); break; case TIPC_CMD_SHOW_PORTS: - rep_tlv_buf = tipc_port_get_ports(); + rep_tlv_buf = tipc_sk_socks_show(); break; case TIPC_CMD_SHOW_STATS: rep_tlv_buf = tipc_show_stats(); diff --git a/net/tipc/net.c b/net/tipc/net.c index 7fcc94998feae6eb1427dd25ac965fece340227a..421dd89152ac7d815f432a9e850eb8f1d5cf637a 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -111,7 +111,7 @@ int tipc_net_start(u32 addr) tipc_own_addr = addr; tipc_named_reinit(); - tipc_port_reinit(); + tipc_sk_reinit(); res = tipc_bclink_init(); if (res) return res; diff --git a/net/tipc/port.c b/net/tipc/port.c index 1efa2982d2d2f2b52cc289a7b10758a55d04cfd0..cea3730fe02660e5a26164a77859c4578c4796cf 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -63,93 +63,6 @@ int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg) (!peernode && (orignode == tipc_own_addr)); } -static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id) -{ - struct publication *publ; - int ret; - - if (full_id) - ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:", - tipc_zone(tipc_own_addr), - tipc_cluster(tipc_own_addr), - tipc_node(tipc_own_addr), p_ptr->ref); - else - ret = tipc_snprintf(buf, len, "%-10u:", p_ptr->ref); - - if (p_ptr->connected) { - u32 dport = tipc_port_peerport(p_ptr); - u32 destnode = tipc_port_peernode(p_ptr); - - ret += tipc_snprintf(buf + ret, len - ret, - " connected to <%u.%u.%u:%u>", - tipc_zone(destnode), - tipc_cluster(destnode), - tipc_node(destnode), dport); - if (p_ptr->conn_type != 0) - ret += tipc_snprintf(buf + ret, len - ret, - " via {%u,%u}", p_ptr->conn_type, - p_ptr->conn_instance); - } else if (p_ptr->published) { - ret += tipc_snprintf(buf + ret, len - ret, " bound to"); - list_for_each_entry(publ, &p_ptr->publications, pport_list) { - if (publ->lower == publ->upper) - ret += tipc_snprintf(buf + ret, len - ret, - " {%u,%u}", publ->type, - publ->lower); - else - ret += tipc_snprintf(buf + ret, len - ret, - " {%u,%u,%u}", publ->type, - publ->lower, publ->upper); - } - } - ret += tipc_snprintf(buf + ret, len - ret, "\n"); - return ret; -} - -struct sk_buff *tipc_port_get_ports(void) -{ - struct sk_buff *buf; - struct tlv_desc *rep_tlv; - char *pb; - int pb_len; - struct tipc_port *p_ptr; - int str_len = 0; - - buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); - if (!buf) - return NULL; - rep_tlv = (struct tlv_desc *)buf->data; - pb = TLV_DATA(rep_tlv); - pb_len = ULTRA_STRING_MAX_LEN; - - spin_lock_bh(&tipc_port_list_lock); - list_for_each_entry(p_ptr, &tipc_socks, port_list) { - spin_lock_bh(p_ptr->lock); - str_len += port_print(p_ptr, pb, pb_len, 0); - spin_unlock_bh(p_ptr->lock); - } - spin_unlock_bh(&tipc_port_list_lock); - str_len += 1; /* for "\0" */ - skb_put(buf, TLV_SPACE(str_len)); - TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); - - return buf; -} - -void tipc_port_reinit(void) -{ - struct tipc_port *p_ptr; - struct tipc_msg *msg; - - spin_lock_bh(&tipc_port_list_lock); - list_for_each_entry(p_ptr, &tipc_socks, port_list) { - msg = &p_ptr->phdr; - msg_set_prevnode(msg, tipc_own_addr); - msg_set_orignode(msg, tipc_own_addr); - } - spin_unlock_bh(&tipc_port_list_lock); -} - int tipc_publish(struct tipc_port *p_ptr, unsigned int scope, struct tipc_name_seq const *seq) { diff --git a/net/tipc/port.h b/net/tipc/port.h index 4c6cfdd363516236b6bc3dbae8478f5a1aa1bda1..4a3c54e5d69c382acc9f2ffc3e0ce67536723227 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -73,7 +73,6 @@ struct tipc_port { u32 max_pkt; u32 ref; struct tipc_msg phdr; - struct list_head port_list; struct list_head publications; u32 pub_count; u32 probing_state; @@ -81,9 +80,6 @@ struct tipc_port { struct timer_list timer; }; -extern struct list_head tipc_socks; -extern spinlock_t tipc_port_list_lock; - /* * TIPC port manipulation routines */ @@ -100,7 +96,6 @@ int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope, int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg); -struct sk_buff *tipc_port_get_ports(void); void tipc_port_reinit(void); /** diff --git a/net/tipc/ref.c b/net/tipc/ref.c index 3d4ecd754eeef578e708e8219d8dc636093ccdfe..7fc2740846e36c642d614a9acacdef8ed6a12f16 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c @@ -264,3 +264,23 @@ void *tipc_ref_lock(u32 ref) } return NULL; } + +/* tipc_ref_lock_next - lock & return next object after referenced one +*/ +void *tipc_ref_lock_next(u32 *ref) +{ + struct reference *entry; + uint index = *ref & tipc_ref_table.index_mask; + + while (++index < tipc_ref_table.capacity) { + entry = &tipc_ref_table.entries[index]; + if (!entry->object) + continue; + spin_lock_bh(&entry->lock); + *ref = entry->ref; + if (entry->object) + return entry->object; + spin_unlock_bh(&entry->lock); + } + return NULL; +} diff --git a/net/tipc/ref.h b/net/tipc/ref.h index d01aa1df63b86e391ed61a2fb2b31ff245fdc87e..e236fa520a1d6e2c7e98f6e463416439a6913e6e 100644 --- a/net/tipc/ref.h +++ b/net/tipc/ref.h @@ -44,5 +44,6 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock); void tipc_ref_discard(u32 ref); void *tipc_ref_lock(u32 ref); +void *tipc_ref_lock_next(u32 *ref); #endif diff --git a/net/tipc/socket.c b/net/tipc/socket.c index f2be4c2e20bbb5dec4a25fe1e0d7894a1770beb3..ddc2f8c6fced8affafeaa4eab8bed904fb92c401 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -40,6 +40,7 @@ #include "node.h" #include "link.h" #include +#include "config.h" #define SS_LISTENING -1 /* socket is listening */ #define SS_READY -2 /* socket is connectionless */ @@ -63,9 +64,6 @@ static const struct proto_ops msg_ops; static struct proto tipc_proto; static struct proto tipc_proto_kern; -DEFINE_SPINLOCK(tipc_port_list_lock); -LIST_HEAD(tipc_socks); - /* * Revised TIPC socket locking policy: * @@ -113,6 +111,17 @@ LIST_HEAD(tipc_socks); #include "socket.h" +/* tipc_sk_lock_next: find & lock next socket in registry from given port number +*/ +static struct tipc_sock *tipc_sk_lock_next(u32 *ref) +{ + struct tipc_port *port = (struct tipc_port *)tipc_ref_lock_next(ref); + + if (!port) + return NULL; + return tipc_port_to_sock(port); +} + /** * advance_rx_queue - discard first buffer in socket receive queue * @@ -203,16 +212,11 @@ static int tipc_sk_create(struct net *net, struct socket *sock, port->max_pkt = MAX_PKT_DEFAULT; port->ref = ref; INIT_LIST_HEAD(&port->publications); - INIT_LIST_HEAD(&port->port_list); - /* Guard against race during node address update */ - spin_lock_bh(&tipc_port_list_lock); msg = &port->phdr; tipc_msg_init(msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG, NAMED_H_SIZE, 0); msg_set_origport(msg, ref); - list_add_tail(&port->port_list, &tipc_socks); - spin_unlock_bh(&tipc_port_list_lock); /* Finish initializing socket data structures */ sock->ops = ops; @@ -377,9 +381,6 @@ static int tipc_release(struct socket *sock) tipc_link_xmit(buf, dnode, port->ref); tipc_node_remove_conn(dnode, port->ref); } - spin_lock_bh(&tipc_port_list_lock); - list_del(&port->port_list); - spin_unlock_bh(&tipc_port_list_lock); k_term_timer(&port->timer); /* Discard any remaining (connection-based) messages in receive queue */ @@ -2043,6 +2044,101 @@ static void tipc_sk_timeout(unsigned long ref) tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg)); } +static int tipc_sk_show(struct tipc_port *port, char *buf, + int len, int full_id) +{ + struct publication *publ; + int ret; + + if (full_id) + ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:", + tipc_zone(tipc_own_addr), + tipc_cluster(tipc_own_addr), + tipc_node(tipc_own_addr), port->ref); + else + ret = tipc_snprintf(buf, len, "%-10u:", port->ref); + + if (port->connected) { + u32 dport = tipc_port_peerport(port); + u32 destnode = tipc_port_peernode(port); + + ret += tipc_snprintf(buf + ret, len - ret, + " connected to <%u.%u.%u:%u>", + tipc_zone(destnode), + tipc_cluster(destnode), + tipc_node(destnode), dport); + if (port->conn_type != 0) + ret += tipc_snprintf(buf + ret, len - ret, + " via {%u,%u}", port->conn_type, + port->conn_instance); + } else if (port->published) { + ret += tipc_snprintf(buf + ret, len - ret, " bound to"); + list_for_each_entry(publ, &port->publications, pport_list) { + if (publ->lower == publ->upper) + ret += tipc_snprintf(buf + ret, len - ret, + " {%u,%u}", publ->type, + publ->lower); + else + ret += tipc_snprintf(buf + ret, len - ret, + " {%u,%u,%u}", publ->type, + publ->lower, publ->upper); + } + } + ret += tipc_snprintf(buf + ret, len - ret, "\n"); + return ret; +} + +struct sk_buff *tipc_sk_socks_show(void) +{ + struct sk_buff *buf; + struct tlv_desc *rep_tlv; + char *pb; + int pb_len; + struct tipc_sock *tsk; + int str_len = 0; + u32 ref = 0; + + buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); + if (!buf) + return NULL; + rep_tlv = (struct tlv_desc *)buf->data; + pb = TLV_DATA(rep_tlv); + pb_len = ULTRA_STRING_MAX_LEN; + + tsk = tipc_sk_lock_next(&ref); + for (; tsk; tsk = tipc_sk_lock_next(&ref)) { + bh_lock_sock(&tsk->sk); + str_len += tipc_sk_show(&tsk->port, pb + str_len, + pb_len - str_len, 0); + bh_unlock_sock(&tsk->sk); + tipc_port_unlock(&tsk->port); + } + str_len += 1; /* for "\0" */ + skb_put(buf, TLV_SPACE(str_len)); + TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); + + return buf; +} + +/* tipc_sk_reinit: set non-zero address in all existing sockets + * when we go from standalone to network mode. + */ +void tipc_sk_reinit(void) +{ + struct tipc_msg *msg; + u32 ref = 0; + struct tipc_sock *tsk = tipc_sk_lock_next(&ref); + + for (; tsk; tsk = tipc_sk_lock_next(&ref)) { + bh_lock_sock(&tsk->sk); + msg = &tsk->port.phdr; + msg_set_prevnode(msg, tipc_own_addr); + msg_set_orignode(msg, tipc_own_addr); + bh_unlock_sock(&tsk->sk); + tipc_port_unlock(&tsk->port); + } +} + /** * tipc_setsockopt - set socket option * @sock: socket structure diff --git a/net/tipc/socket.h b/net/tipc/socket.h index 1405633362f568e0813992554dcd591befe74077..5d515be604a93a7e6e8beae7bcbfcf22ee7611bb 100644 --- a/net/tipc/socket.h +++ b/net/tipc/socket.h @@ -79,7 +79,8 @@ static inline int tipc_sk_conn_cong(struct tipc_sock *tsk) } int tipc_sk_rcv(struct sk_buff *buf); - +struct sk_buff *tipc_sk_socks_show(void); void tipc_sk_mcast_rcv(struct sk_buff *buf); +void tipc_sk_reinit(void); #endif