aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c23
1 files changed, 14 insertions, 9 deletions
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);