diff options
Diffstat (limited to 'net/tipc/socket.c')
| -rw-r--r-- | net/tipc/socket.c | 62 | 
1 files changed, 33 insertions, 29 deletions
| diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 230f9ca2ad6..1848693ebb8 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -2,7 +2,7 @@   * net/tipc/socket.c: TIPC socket API   *   * Copyright (c) 2001-2007, Ericsson AB - * Copyright (c) 2004-2007, Wind River Systems + * Copyright (c) 2004-2008, Wind River Systems   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -63,6 +63,7 @@  struct tipc_sock {  	struct sock sk;  	struct tipc_port *p; +	struct tipc_portid peer_name;  };  #define tipc_sk(sk) ((struct tipc_sock *)(sk)) @@ -188,7 +189,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)  	const struct proto_ops *ops;  	socket_state state;  	struct sock *sk; -	u32 portref; +	struct tipc_port *tp_ptr;  	/* Validate arguments */ @@ -224,9 +225,9 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)  	/* Allocate TIPC port for socket to use */ -	portref = tipc_createport_raw(sk, &dispatch, &wakeupdispatch, -				      TIPC_LOW_IMPORTANCE); -	if (unlikely(portref == 0)) { +	tp_ptr = tipc_createport_raw(sk, &dispatch, &wakeupdispatch, +				     TIPC_LOW_IMPORTANCE); +	if (unlikely(!tp_ptr)) {  		sk_free(sk);  		return -ENOMEM;  	} @@ -239,12 +240,14 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)  	sock_init_data(sock, sk);  	sk->sk_rcvtimeo = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT);  	sk->sk_backlog_rcv = backlog_rcv; -	tipc_sk(sk)->p = tipc_get_port(portref); +	tipc_sk(sk)->p = tp_ptr; + +	spin_unlock_bh(tp_ptr->lock);  	if (sock->state == SS_READY) { -		tipc_set_portunreturnable(portref, 1); +		tipc_set_portunreturnable(tp_ptr->ref, 1);  		if (sock->type == SOCK_DGRAM) -			tipc_set_portunreliable(portref, 1); +			tipc_set_portunreliable(tp_ptr->ref, 1);  	}  	atomic_inc(&tipc_user_count); @@ -375,27 +378,29 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)   * @sock: socket structure   * @uaddr: area for returned socket address   * @uaddr_len: area for returned length of socket address - * @peer: 0 to obtain socket name, 1 to obtain peer socket name + * @peer: 0 = own ID, 1 = current peer ID, 2 = current/former peer ID   *   * Returns 0 on success, errno otherwise   * - * NOTE: This routine doesn't need to take the socket lock since it doesn't - *       access any non-constant socket information. + * NOTE: This routine doesn't need to take the socket lock since it only + *       accesses socket information that is unchanging (or which changes in + * 	 a completely predictable manner).   */  static int get_name(struct socket *sock, struct sockaddr *uaddr,  		    int *uaddr_len, int peer)  {  	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; -	u32 portref = tipc_sk_port(sock->sk)->ref; -	u32 res; +	struct tipc_sock *tsock = tipc_sk(sock->sk);  	if (peer) { -		res = tipc_peer(portref, &addr->addr.id); -		if (res) -			return res; +		if ((sock->state != SS_CONNECTED) && +			((peer != 2) || (sock->state != SS_DISCONNECTING))) +			return -ENOTCONN; +		addr->addr.id.ref = tsock->peer_name.ref; +		addr->addr.id.node = tsock->peer_name.node;  	} else { -		tipc_ownidentity(portref, &addr->addr.id); +		tipc_ownidentity(tsock->p->ref, &addr->addr.id);  	}  	*uaddr_len = sizeof(*addr); @@ -764,18 +769,17 @@ exit:  static int auto_connect(struct socket *sock, struct tipc_msg *msg)  { -	struct tipc_port *tport = tipc_sk_port(sock->sk); -	struct tipc_portid peer; +	struct tipc_sock *tsock = tipc_sk(sock->sk);  	if (msg_errcode(msg)) {  		sock->state = SS_DISCONNECTING;  		return -ECONNREFUSED;  	} -	peer.ref = msg_origport(msg); -	peer.node = msg_orignode(msg); -	tipc_connect2port(tport->ref, &peer); -	tipc_set_portimportance(tport->ref, msg_importance(msg)); +	tsock->peer_name.ref = msg_origport(msg); +	tsock->peer_name.node = msg_orignode(msg); +	tipc_connect2port(tsock->p->ref, &tsock->peer_name); +	tipc_set_portimportance(tsock->p->ref, msg_importance(msg));  	sock->state = SS_CONNECTED;  	return 0;  } @@ -1131,7 +1135,7 @@ restart:  	/* Loop around if more data is required */  	if ((sz_copied < buf_len)    /* didn't get all requested data */ -	    && (!skb_queue_empty(&sock->sk->sk_receive_queue) || +	    && (!skb_queue_empty(&sk->sk_receive_queue) ||  		(flags & MSG_WAITALL))  				     /* ... and more is ready or required */  	    && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */ @@ -1527,9 +1531,9 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)  	res = tipc_create(sock_net(sock->sk), new_sock, 0);  	if (!res) {  		struct sock *new_sk = new_sock->sk; -		struct tipc_port *new_tport = tipc_sk_port(new_sk); +		struct tipc_sock *new_tsock = tipc_sk(new_sk); +		struct tipc_port *new_tport = new_tsock->p;  		u32 new_ref = new_tport->ref; -		struct tipc_portid id;  		struct tipc_msg *msg = buf_msg(buf);  		lock_sock(new_sk); @@ -1543,9 +1547,9 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)  		/* Connect new socket to it's peer */ -		id.ref = msg_origport(msg); -		id.node = msg_orignode(msg); -		tipc_connect2port(new_ref, &id); +		new_tsock->peer_name.ref = msg_origport(msg); +		new_tsock->peer_name.node = msg_orignode(msg); +		tipc_connect2port(new_ref, &new_tsock->peer_name);  		new_sock->state = SS_CONNECTED;  		tipc_set_portimportance(new_ref, msg_importance(msg)); | 
