aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-02-17 22:26:36 -0500
committerDavid S. Miller <davem@davemloft.net>2011-02-22 13:19:31 -0500
commiteaefd1105bc431ef329599e307a07f2a36ae7872 (patch)
tree658eeed417654c8f6015d4d5f957f5a1b5e9521f
parent04cfa852ff8dab923640500ee850d19e75bacabc (diff)
net: add __rcu annotations to sk_wq and wq
Add proper RCU annotations/verbs to sk_wq and wq members Fix __sctp_write_space() sk_sleep() abuse (and sock->wq access) Fix sunrpc sk_sleep() abuse too Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/net.h3
-rw-r--r--include/net/sock.h7
-rw-r--r--net/sctp/socket.c9
-rw-r--r--net/socket.c23
-rw-r--r--net/sunrpc/svcsock.c32
-rw-r--r--net/unix/af_unix.c2
6 files changed, 46 insertions, 30 deletions
diff --git a/include/linux/net.h b/include/linux/net.h
index 16faa130088c..94de83c0f877 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -118,6 +118,7 @@ enum sock_shutdown_cmd {
118}; 118};
119 119
120struct socket_wq { 120struct socket_wq {
121 /* Note: wait MUST be first field of socket_wq */
121 wait_queue_head_t wait; 122 wait_queue_head_t wait;
122 struct fasync_struct *fasync_list; 123 struct fasync_struct *fasync_list;
123 struct rcu_head rcu; 124 struct rcu_head rcu;
@@ -142,7 +143,7 @@ struct socket {
142 143
143 unsigned long flags; 144 unsigned long flags;
144 145
145 struct socket_wq *wq; 146 struct socket_wq __rcu *wq;
146 147
147 struct file *file; 148 struct file *file;
148 struct sock *sk; 149 struct sock *sk;
diff --git a/include/net/sock.h b/include/net/sock.h
index e3893a2b5d25..da0534d3401c 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -281,7 +281,7 @@ struct sock {
281 int sk_rcvbuf; 281 int sk_rcvbuf;
282 282
283 struct sk_filter __rcu *sk_filter; 283 struct sk_filter __rcu *sk_filter;
284 struct socket_wq *sk_wq; 284 struct socket_wq __rcu *sk_wq;
285 285
286#ifdef CONFIG_NET_DMA 286#ifdef CONFIG_NET_DMA
287 struct sk_buff_head sk_async_wait_queue; 287 struct sk_buff_head sk_async_wait_queue;
@@ -1266,7 +1266,8 @@ static inline void sk_set_socket(struct sock *sk, struct socket *sock)
1266 1266
1267static inline wait_queue_head_t *sk_sleep(struct sock *sk) 1267static inline wait_queue_head_t *sk_sleep(struct sock *sk)
1268{ 1268{
1269 return &sk->sk_wq->wait; 1269 BUILD_BUG_ON(offsetof(struct socket_wq, wait) != 0);
1270 return &rcu_dereference_raw(sk->sk_wq)->wait;
1270} 1271}
1271/* Detach socket from process context. 1272/* Detach socket from process context.
1272 * Announce socket dead, detach it from wait queue and inode. 1273 * Announce socket dead, detach it from wait queue and inode.
@@ -1287,7 +1288,7 @@ static inline void sock_orphan(struct sock *sk)
1287static inline void sock_graft(struct sock *sk, struct socket *parent) 1288static inline void sock_graft(struct sock *sk, struct socket *parent)
1288{ 1289{
1289 write_lock_bh(&sk->sk_callback_lock); 1290 write_lock_bh(&sk->sk_callback_lock);
1290 rcu_assign_pointer(sk->sk_wq, parent->wq); 1291 sk->sk_wq = parent->wq;
1291 parent->sk = sk; 1292 parent->sk = sk;
1292 sk_set_socket(sk, parent); 1293 sk_set_socket(sk, parent);
1293 security_sock_graft(sk, parent); 1294 security_sock_graft(sk, parent);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 8e02550ff3e8..b53b2ebbb198 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6102,15 +6102,16 @@ static void __sctp_write_space(struct sctp_association *asoc)
6102 wake_up_interruptible(&asoc->wait); 6102 wake_up_interruptible(&asoc->wait);
6103 6103
6104 if (sctp_writeable(sk)) { 6104 if (sctp_writeable(sk)) {
6105 if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) 6105 wait_queue_head_t *wq = sk_sleep(sk);
6106 wake_up_interruptible(sk_sleep(sk)); 6106
6107 if (wq && waitqueue_active(wq))
6108 wake_up_interruptible(wq);
6107 6109
6108 /* Note that we try to include the Async I/O support 6110 /* Note that we try to include the Async I/O support
6109 * here by modeling from the current TCP/UDP code. 6111 * here by modeling from the current TCP/UDP code.
6110 * We have not tested with it yet. 6112 * We have not tested with it yet.
6111 */ 6113 */
6112 if (sock->wq->fasync_list && 6114 if (!(sk->sk_shutdown & SEND_SHUTDOWN))
6113 !(sk->sk_shutdown & SEND_SHUTDOWN))
6114 sock_wake_async(sock, 6115 sock_wake_async(sock,
6115 SOCK_WAKE_SPACE, POLL_OUT); 6116 SOCK_WAKE_SPACE, POLL_OUT);
6116 } 6117 }
diff --git a/net/socket.c b/net/socket.c
index ac2219f90d5d..9fa1e3b4366e 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -240,17 +240,19 @@ static struct kmem_cache *sock_inode_cachep __read_mostly;
240static struct inode *sock_alloc_inode(struct super_block *sb) 240static struct inode *sock_alloc_inode(struct super_block *sb)
241{ 241{
242 struct socket_alloc *ei; 242 struct socket_alloc *ei;
243 struct socket_wq *wq;
243 244
244 ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); 245 ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
245 if (!ei) 246 if (!ei)
246 return NULL; 247 return NULL;
247 ei->socket.wq = kmalloc(sizeof(struct socket_wq), GFP_KERNEL); 248 wq = kmalloc(sizeof(*wq), GFP_KERNEL);
248 if (!ei->socket.wq) { 249 if (!wq) {
249 kmem_cache_free(sock_inode_cachep, ei); 250 kmem_cache_free(sock_inode_cachep, ei);
250 return NULL; 251 return NULL;
251 } 252 }
252 init_waitqueue_head(&ei->socket.wq->wait); 253 init_waitqueue_head(&wq->wait);
253 ei->socket.wq->fasync_list = NULL; 254 wq->fasync_list = NULL;
255 RCU_INIT_POINTER(ei->socket.wq, wq);
254 256
255 ei->socket.state = SS_UNCONNECTED; 257 ei->socket.state = SS_UNCONNECTED;
256 ei->socket.flags = 0; 258 ei->socket.flags = 0;
@@ -273,9 +275,11 @@ static void wq_free_rcu(struct rcu_head *head)
273static void sock_destroy_inode(struct inode *inode) 275static void sock_destroy_inode(struct inode *inode)
274{ 276{
275 struct socket_alloc *ei; 277 struct socket_alloc *ei;
278 struct socket_wq *wq;
276 279
277 ei = container_of(inode, struct socket_alloc, vfs_inode); 280 ei = container_of(inode, struct socket_alloc, vfs_inode);
278 call_rcu(&ei->socket.wq->rcu, wq_free_rcu); 281 wq = rcu_dereference_protected(ei->socket.wq, 1);
282 call_rcu(&wq->rcu, wq_free_rcu);
279 kmem_cache_free(sock_inode_cachep, ei); 283 kmem_cache_free(sock_inode_cachep, ei);
280} 284}
281 285
@@ -524,7 +528,7 @@ void sock_release(struct socket *sock)
524 module_put(owner); 528 module_put(owner);
525 } 529 }
526 530
527 if (sock->wq->fasync_list) 531 if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
528 printk(KERN_ERR "sock_release: fasync list not empty!\n"); 532 printk(KERN_ERR "sock_release: fasync list not empty!\n");
529 533
530 percpu_sub(sockets_in_use, 1); 534 percpu_sub(sockets_in_use, 1);
@@ -1108,15 +1112,16 @@ static int sock_fasync(int fd, struct file *filp, int on)
1108{ 1112{
1109 struct socket *sock = filp->private_data; 1113 struct socket *sock = filp->private_data;
1110 struct sock *sk = sock->sk; 1114 struct sock *sk = sock->sk;
1115 struct socket_wq *wq;
1111 1116
1112 if (sk == NULL) 1117 if (sk == NULL)
1113 return -EINVAL; 1118 return -EINVAL;
1114 1119
1115 lock_sock(sk); 1120 lock_sock(sk);
1121 wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1122 fasync_helper(fd, filp, on, &wq->fasync_list);
1116 1123
1117 fasync_helper(fd, filp, on, &sock->wq->fasync_list); 1124 if (!wq->fasync_list)
1118
1119 if (!sock->wq->fasync_list)
1120 sock_reset_flag(sk, SOCK_FASYNC); 1125 sock_reset_flag(sk, SOCK_FASYNC);
1121 else 1126 else
1122 sock_set_flag(sk, SOCK_FASYNC); 1127 sock_set_flag(sk, SOCK_FASYNC);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index d802e941d365..b7d435c3f19e 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -420,6 +420,7 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
420static void svc_udp_data_ready(struct sock *sk, int count) 420static void svc_udp_data_ready(struct sock *sk, int count)
421{ 421{
422 struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; 422 struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
423 wait_queue_head_t *wq = sk_sleep(sk);
423 424
424 if (svsk) { 425 if (svsk) {
425 dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n", 426 dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
@@ -428,8 +429,8 @@ static void svc_udp_data_ready(struct sock *sk, int count)
428 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); 429 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
429 svc_xprt_enqueue(&svsk->sk_xprt); 430 svc_xprt_enqueue(&svsk->sk_xprt);
430 } 431 }
431 if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) 432 if (wq && waitqueue_active(wq))
432 wake_up_interruptible(sk_sleep(sk)); 433 wake_up_interruptible(wq);
433} 434}
434 435
435/* 436/*
@@ -438,6 +439,7 @@ static void svc_udp_data_ready(struct sock *sk, int count)
438static void svc_write_space(struct sock *sk) 439static void svc_write_space(struct sock *sk)
439{ 440{
440 struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data); 441 struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data);
442 wait_queue_head_t *wq = sk_sleep(sk);
441 443
442 if (svsk) { 444 if (svsk) {
443 dprintk("svc: socket %p(inet %p), write_space busy=%d\n", 445 dprintk("svc: socket %p(inet %p), write_space busy=%d\n",
@@ -445,10 +447,10 @@ static void svc_write_space(struct sock *sk)
445 svc_xprt_enqueue(&svsk->sk_xprt); 447 svc_xprt_enqueue(&svsk->sk_xprt);
446 } 448 }
447 449
448 if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) { 450 if (wq && waitqueue_active(wq)) {
449 dprintk("RPC svc_write_space: someone sleeping on %p\n", 451 dprintk("RPC svc_write_space: someone sleeping on %p\n",
450 svsk); 452 svsk);
451 wake_up_interruptible(sk_sleep(sk)); 453 wake_up_interruptible(wq);
452 } 454 }
453} 455}
454 456
@@ -739,6 +741,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
739static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused) 741static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
740{ 742{
741 struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; 743 struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
744 wait_queue_head_t *wq;
742 745
743 dprintk("svc: socket %p TCP (listen) state change %d\n", 746 dprintk("svc: socket %p TCP (listen) state change %d\n",
744 sk, sk->sk_state); 747 sk, sk->sk_state);
@@ -761,8 +764,9 @@ static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
761 printk("svc: socket %p: no user data\n", sk); 764 printk("svc: socket %p: no user data\n", sk);
762 } 765 }
763 766
764 if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) 767 wq = sk_sleep(sk);
765 wake_up_interruptible_all(sk_sleep(sk)); 768 if (wq && waitqueue_active(wq))
769 wake_up_interruptible_all(wq);
766} 770}
767 771
768/* 772/*
@@ -771,6 +775,7 @@ static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
771static void svc_tcp_state_change(struct sock *sk) 775static void svc_tcp_state_change(struct sock *sk)
772{ 776{
773 struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; 777 struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
778 wait_queue_head_t *wq = sk_sleep(sk);
774 779
775 dprintk("svc: socket %p TCP (connected) state change %d (svsk %p)\n", 780 dprintk("svc: socket %p TCP (connected) state change %d (svsk %p)\n",
776 sk, sk->sk_state, sk->sk_user_data); 781 sk, sk->sk_state, sk->sk_user_data);
@@ -781,13 +786,14 @@ static void svc_tcp_state_change(struct sock *sk)
781 set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); 786 set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
782 svc_xprt_enqueue(&svsk->sk_xprt); 787 svc_xprt_enqueue(&svsk->sk_xprt);
783 } 788 }
784 if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) 789 if (wq && waitqueue_active(wq))
785 wake_up_interruptible_all(sk_sleep(sk)); 790 wake_up_interruptible_all(wq);
786} 791}
787 792
788static void svc_tcp_data_ready(struct sock *sk, int count) 793static void svc_tcp_data_ready(struct sock *sk, int count)
789{ 794{
790 struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; 795 struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
796 wait_queue_head_t *wq = sk_sleep(sk);
791 797
792 dprintk("svc: socket %p TCP data ready (svsk %p)\n", 798 dprintk("svc: socket %p TCP data ready (svsk %p)\n",
793 sk, sk->sk_user_data); 799 sk, sk->sk_user_data);
@@ -795,8 +801,8 @@ static void svc_tcp_data_ready(struct sock *sk, int count)
795 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); 801 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
796 svc_xprt_enqueue(&svsk->sk_xprt); 802 svc_xprt_enqueue(&svsk->sk_xprt);
797 } 803 }
798 if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) 804 if (wq && waitqueue_active(wq))
799 wake_up_interruptible(sk_sleep(sk)); 805 wake_up_interruptible(wq);
800} 806}
801 807
802/* 808/*
@@ -1531,6 +1537,7 @@ static void svc_sock_detach(struct svc_xprt *xprt)
1531{ 1537{
1532 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); 1538 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
1533 struct sock *sk = svsk->sk_sk; 1539 struct sock *sk = svsk->sk_sk;
1540 wait_queue_head_t *wq;
1534 1541
1535 dprintk("svc: svc_sock_detach(%p)\n", svsk); 1542 dprintk("svc: svc_sock_detach(%p)\n", svsk);
1536 1543
@@ -1539,8 +1546,9 @@ static void svc_sock_detach(struct svc_xprt *xprt)
1539 sk->sk_data_ready = svsk->sk_odata; 1546 sk->sk_data_ready = svsk->sk_odata;
1540 sk->sk_write_space = svsk->sk_owspace; 1547 sk->sk_write_space = svsk->sk_owspace;
1541 1548
1542 if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) 1549 wq = sk_sleep(sk);
1543 wake_up_interruptible(sk_sleep(sk)); 1550 if (wq && waitqueue_active(wq))
1551 wake_up_interruptible(wq);
1544} 1552}
1545 1553
1546/* 1554/*
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d8d98d5b508c..217fb7f34d52 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1171,7 +1171,7 @@ restart:
1171 newsk->sk_type = sk->sk_type; 1171 newsk->sk_type = sk->sk_type;
1172 init_peercred(newsk); 1172 init_peercred(newsk);
1173 newu = unix_sk(newsk); 1173 newu = unix_sk(newsk);
1174 newsk->sk_wq = &newu->peer_wq; 1174 RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
1175 otheru = unix_sk(other); 1175 otheru = unix_sk(other);
1176 1176
1177 /* copy address information from listening to new sock*/ 1177 /* copy address information from listening to new sock*/