#define MAX_REJECT_SIZE 1024
-DEFINE_SPINLOCK(tipc_port_list_lock);
-
-static LIST_HEAD(ports);
-
/**
* tipc_port_peer_msg - verify message was sent by connected port's peer
*
(!peernode && (orignode == tipc_own_addr));
}
-/* tipc_port_init - intiate TIPC port and lock it
- *
- * Returns obtained reference if initialization is successful, zero otherwise
- */
-u32 tipc_port_init(struct tipc_port *p_ptr,
- const unsigned int importance)
-{
- struct tipc_msg *msg;
- u32 ref;
-
- ref = tipc_ref_acquire(p_ptr, &p_ptr->lock);
- if (!ref) {
- pr_warn("Port registration failed, ref. table exhausted\n");
- return 0;
- }
-
- p_ptr->max_pkt = MAX_PKT_DEFAULT;
- p_ptr->ref = ref;
- INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
- INIT_LIST_HEAD(&p_ptr->publications);
- INIT_LIST_HEAD(&p_ptr->port_list);
-
- /*
- * Must hold port list lock while initializing message header template
- * to ensure a change to node's own network address doesn't result
- * in template containing out-dated network address information
- */
- spin_lock_bh(&tipc_port_list_lock);
- msg = &p_ptr->phdr;
- tipc_msg_init(msg, importance, TIPC_NAMED_MSG, NAMED_H_SIZE, 0);
- msg_set_origport(msg, ref);
- list_add_tail(&p_ptr->port_list, &ports);
- spin_unlock_bh(&tipc_port_list_lock);
- return ref;
-}
-
-void tipc_port_destroy(struct tipc_port *p_ptr)
-{
- struct sk_buff *buf = NULL;
- struct tipc_msg *msg = NULL;
- u32 peer_node;
-
- tipc_withdraw(p_ptr, 0, NULL);
-
- spin_lock_bh(p_ptr->lock);
- tipc_ref_discard(p_ptr->ref);
- spin_unlock_bh(p_ptr->lock);
-
- k_cancel_timer(&p_ptr->timer);
- if (p_ptr->connected) {
- peer_node = tipc_port_peernode(p_ptr);
- buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG,
- SHORT_H_SIZE, 0, peer_node,
- tipc_own_addr, tipc_port_peerport(p_ptr),
- p_ptr->ref, TIPC_ERR_NO_PORT);
- if (buf) {
- msg = buf_msg(buf);
- tipc_link_xmit(buf, peer_node, msg_link_selector(msg));
- }
- tipc_node_remove_conn(peer_node, p_ptr->ref);
- }
- spin_lock_bh(&tipc_port_list_lock);
- list_del(&p_ptr->port_list);
- spin_unlock_bh(&tipc_port_list_lock);
- k_term_timer(&p_ptr->timer);
-}
-
static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id)
{
struct publication *publ;
pb_len = ULTRA_STRING_MAX_LEN;
spin_lock_bh(&tipc_port_list_lock);
- list_for_each_entry(p_ptr, &ports, port_list) {
+ 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);
struct tipc_msg *msg;
spin_lock_bh(&tipc_port_list_lock);
- list_for_each_entry(p_ptr, &ports, port_list) {
+ 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);
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:
*
struct sock *sk;
struct tipc_sock *tsk;
struct tipc_port *port;
+ struct tipc_msg *msg;
u32 ref;
/* Validate arguments */
tsk = tipc_sk(sk);
port = &tsk->port;
-
- ref = tipc_port_init(port, TIPC_LOW_IMPORTANCE);
+ ref = tipc_ref_acquire(port, &port->lock);
if (!ref) {
- pr_warn("Socket registration failed, ref. table exhausted\n");
- sk_free(sk);
+ pr_warn("Socket create failed; reference table exhausted\n");
return -ENOMEM;
}
+ 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;
sock->state = state;
-
sock_init_data(sock, sk);
k_init_timer(&port->timer, (Handler)tipc_sk_timeout, ref);
sk->sk_backlog_rcv = tipc_backlog_rcv;
* Reject all unreceived messages, except on an active connection
* (which disconnects locally & sends a 'FIN+' to peer)
*/
+ dnode = tipc_port_peernode(port);
while (sock->state != SS_DISCONNECTING) {
buf = __skb_dequeue(&sk->sk_receive_queue);
if (buf == NULL)
(sock->state == SS_CONNECTED)) {
sock->state = SS_DISCONNECTING;
port->connected = 0;
- tipc_node_remove_conn(tipc_port_peernode(port),
- port->ref);
+ tipc_node_remove_conn(dnode, port->ref);
}
if (tipc_msg_reverse(buf, &dnode, TIPC_ERR_NO_PORT))
tipc_link_xmit(buf, dnode, 0);
}
}
- /* Destroy TIPC port; also disconnects an active connection and
- * sends a 'FIN-' to peer.
- */
- tipc_port_destroy(port);
+ tipc_withdraw(port, 0, NULL);
+ spin_lock_bh(port->lock);
+ tipc_ref_discard(port->ref);
+ spin_unlock_bh(port->lock);
+ k_cancel_timer(&port->timer);
+ if (port->connected) {
+ buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG,
+ SHORT_H_SIZE, 0, dnode, tipc_own_addr,
+ tipc_port_peerport(port),
+ port->ref, TIPC_ERR_NO_PORT);
+ if (buf)
+ 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 */
__skb_queue_purge(&sk->sk_receive_queue);
/* Reject any messages that accumulated in backlog queue */
sock->state = SS_DISCONNECTING;
release_sock(sk);
-
sock_put(sk);
sock->sk = NULL;