Convert the semaphore to a mutex in net/tipc/socket.c
Subsystems (3)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 Convert the semaphore to a mutex in net/tipc/socket.c
To: Andrew Morton <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Per Liden <[email protected]>
Cc: Jon Maloy <[email protected]>
Cc: Allan Stephens <[email protected]>
Cc: [email protected]
Cc: [email protected]
Note also that in the release method, down_interruptible() was being called without checking the return value. I converted it to mutex_lock_interruptible() and made the interrupted case return -ERESTARTSYS, as was done for all other calls to down_interruptible() in the file.
--- net/tipc/socket.c | 56 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-)
net/tipc/socket.c +28 -28
@@ -63,7 +63,7 @@struct tipc_sock {struct sock sk;struct tipc_port *p; -struct semaphore sem; +struct mutex lock; };#define tipc_sk (sk) ((struct tipc_sock*)sk)
@@ -217,7 +217,7 @@ static int tipc_create(struct net *net, tsock->p = port; port->usr_handle = tsock; -init_MUTEX (&tsock->sem); +mutex_init (&tsock->lock);dbg ("sock_create: %x\n" ,tsock);
@@ -253,9 +253,10 @@ static int release(struct socket *sock)dbg ("sock_delete: %x\n" ,tsock);if (!tsock)return 0 ; -down_interruptible (&tsock->sem); +if (mutex_lock_interruptible (&tsock->lock)) +return -ERESTARTSYS ;if (!sock->sk) { -up (&tsock->sem); +mutex_unlock (&tsock->lock);return 0 ; }
@@ -288,7 +289,7 @@ static int release(struct socket *sock)atomic_dec (&tipc_queue_size); } -up (&tsock->sem); +mutex_unlock (&tsock->lock);sock_put (sk);
@@ -315,7 +316,7 @@ static int bind(struct socket *sock, strstruct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;int res; -if (down_interruptible (&tsock->sem)) +if (mutex_lock_interruptible (&tsock->lock))return -ERESTARTSYS ;if (unlikely (!uaddr_len)) {
@@ -346,7 +347,7 @@ static int bind(struct socket *sock, str res =tipc_withdraw (tsock->p->ref, -addr->scope, &addr->addr.nameseq); exit: -up (&tsock->sem); +mutex_unlock (&tsock->lock);return res; }
@@ -367,7 +368,7 @@ static int get_name(struct socket *sock,struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;u32 res; -if (down_interruptible (&tsock->sem)) +if (mutex_lock_interruptible (&tsock->lock))return -ERESTARTSYS ; *uaddr_len =sizeof (*addr);
@@ -380,7 +381,7 @@ static int get_name(struct socket *sock, res =tipc_ownidentity (tsock->p->ref, &addr->addr.id); addr->addr.name.domain =0 ; -up (&tsock->sem); +mutex_unlock (&tsock->lock);return res; }
@@ -477,7 +478,7 @@ static int send_msg(struct kiocb *iocb, } } -if (down_interruptible (&tsock->sem)) +if (mutex_lock_interruptible (&tsock->lock))return -ERESTARTSYS ;if (needs_conn) {
@@ -523,7 +524,7 @@ static int send_msg(struct kiocb *iocb, }if (likely (res != -ELINKCONG )) { exit: -up (&tsock->sem); +mutex_unlock (&tsock->lock);return res; }if (m->msg_flags &MSG_DONTWAIT ) {
@@ -562,9 +563,8 @@ static int send_packet(struct kiocb *iocif (unlikely (dest))return send_msg (iocb, sock, m, total_len); -if (down_interruptible (&tsock->sem)) { +if (mutex_lock_interruptible (&tsock->lock))return -ERESTARTSYS ; - } do { if (unlikely(sock->state != SS_CONNECTED)) {
@@ -578,7 +578,7 @@ static int send_packet(struct kiocb *ioc res =tipc_send (tsock->p->ref, m->msg_iovlen, m->msg_iov);if (likely (res != -ELINKCONG )) { exit: -up (&tsock->sem); +mutex_unlock (&tsock->lock);return res; }if (m->msg_flags &MSG_DONTWAIT ) {
@@ -846,7 +846,7 @@ static int recv_msg(struct kiocb *iocb,/* Look for a message in receive queue; wait if necessary */ -if (unlikely (down_interruptible (&tsock->sem))) +if (unlikely (mutex_lock_interruptible (&tsock->lock)))return -ERESTARTSYS ; restart:
@@ -930,7 +930,7 @@ restart:advance_queue (tsock); } exit: -up (&tsock->sem); +mutex_unlock (&tsock->lock);return res; }
@@ -981,7 +981,7 @@ static int recv_stream(struct kiocb *ioc/* Look for a message in receive queue; wait if necessary */ -if (unlikely (down_interruptible (&tsock->sem))) +if (unlikely (mutex_lock_interruptible (&tsock->lock)))return -ERESTARTSYS ; restart:
@@ -1077,7 +1077,7 @@ restart: goto restart; exit: -up (&tsock->sem); +mutex_unlock (&tsock->lock);return sz_copied ? sz_copied : res; }
@@ -1293,7 +1293,7 @@ static int connect(struct socket *sock,return res; } -if (down_interruptible (&tsock->sem)) +if (mutex_lock_interruptible (&tsock->lock))return -ERESTARTSYS ;/* Wait for destination's 'ACK' response */
@@ -1317,7 +1317,7 @@ static int connect(struct socket *sock, sock->state =SS_DISCONNECTING ; } -up (&tsock->sem); +mutex_unlock (&tsock->lock);return res; }
@@ -1365,7 +1365,7 @@ static int accept(struct socket *sock, s (flags & O_NONBLOCK)))return -EWOULDBLOCK ; -if (down_interruptible (&tsock->sem)) +if (mutex_lock_interruptible (&tsock->lock))return -ERESTARTSYS ; if (wait_event_interruptible(*sock->sk->sk_sleep,
@@ -1412,7 +1412,7 @@ static int accept(struct socket *sock, s } } exit: -up (&tsock->sem); +mutex_unlock (&tsock->lock);return res; }
@@ -1434,7 +1434,7 @@ static int shutdown(struct socket *sock,/* Could return -EINVAL for an invalid "how", but why bother? */ -if (down_interruptible (&tsock->sem)) +if (mutex_lock_interruptible (&tsock->lock))return -ERESTARTSYS ;sock_lock (tsock);
@@ -1484,7 +1484,7 @@ restart:sock_unlock (tsock); -up (&tsock->sem); +mutex_unlock (&tsock->lock);return res; }
@@ -1518,7 +1518,7 @@ static int setsockopt(struct socket *socif ((res =get_user (value, (u32 __user *)ov)))return res; -if (down_interruptible (&tsock->sem)) +if (mutex_lock_interruptible (&tsock->lock))return -ERESTARTSYS ;switch (opt) {
@@ -1541,7 +1541,7 @@ static int setsockopt(struct socket *soc res = -EINVAL ; } -up (&tsock->sem); +mutex_unlock (&tsock->lock);return res; }
@@ -1574,7 +1574,7 @@ static int getsockopt(struct socket *socif ((res =get_user (len, ol)))return res; -if (down_interruptible (&tsock->sem)) +if (mutex_lock_interruptible (&tsock->lock))return -ERESTARTSYS ;switch (opt) {
@@ -1607,7 +1607,7 @@ static int getsockopt(struct socket *soc res =put_user (sizeof (value), ol); } -up (&tsock->sem); +mutex_unlock (&tsock->lock);return res; }
Quoted 4 lines · On Sun, 09 Dec 2007 21:17:42 -0400 Kevin Winchester <[email protected]>…
Note also that in the release method,
down_interruptible()was being called without checking the return value. I converted it tomutex_lock_interruptible()and made the interrupted case return-ERESTARTSYS, as was done for all other calls todown_interruptible()in the file.
That's an outright bug.
static int release(struct socket *sock)
{
struct tipc_sock *tsock = tipc_sk(sock->sk);
struct sock *sk = sock->sk;
int res = TIPC_OK;
struct sk_buff *buf;
dbg("sock_delete: %x\n",tsock);
if (!tsock)
return 0;
down_interruptible(&tsock->sem);
if (!sock->sk) {
up(&tsock->sem);
return 0;
}
...
up(&tsock->sem);
...
}So if the calling process has signal_pending(), down_interruptible() will return without having downed the semaphore and then we merrily proceed to do up() on it, so a subsequent down() won't actually take the lock and things will deteriorate from there.
So I'd propose this:
net/tipc/socket.c renamed from net/tipc/socket.c~a +1 -1
@@ -253,7 +253,7 @@ static int release(struct socket *sock)dbg ("sock_delete: %x\n" ,tsock);if (!tsock)return 0 ; -down_interruptible (&tsock->sem); +down (&tsock->sem);if (!sock->sk) {up (&tsock->sem);return 0 ;
_
as a for-2.6.24 bugfix. And for 2.6.23. But someone who knows what they're doing should take a look at this...
From: Andrew Morton <[email protected]>
Date: Tue, 11 Dec 2007 16:44:45 -0800
Quoted 1 line
So I'd propose this:
I've applied this to net-2.6, thanks Andrew.
-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace