aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c126
1 files changed, 52 insertions, 74 deletions
diff --git a/net/socket.c b/net/socket.c
index 769c386bd428..dae8c6b84a09 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -87,6 +87,7 @@
87#include <linux/wireless.h> 87#include <linux/wireless.h>
88#include <linux/nsproxy.h> 88#include <linux/nsproxy.h>
89#include <linux/magic.h> 89#include <linux/magic.h>
90#include <linux/slab.h>
90 91
91#include <asm/uaccess.h> 92#include <asm/uaccess.h>
92#include <asm/unistd.h> 93#include <asm/unistd.h>
@@ -251,9 +252,14 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
251 ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); 252 ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
252 if (!ei) 253 if (!ei)
253 return NULL; 254 return NULL;
254 init_waitqueue_head(&ei->socket.wait); 255 ei->socket.wq = kmalloc(sizeof(struct socket_wq), GFP_KERNEL);
256 if (!ei->socket.wq) {
257 kmem_cache_free(sock_inode_cachep, ei);
258 return NULL;
259 }
260 init_waitqueue_head(&ei->socket.wq->wait);
261 ei->socket.wq->fasync_list = NULL;
255 262
256 ei->socket.fasync_list = NULL;
257 ei->socket.state = SS_UNCONNECTED; 263 ei->socket.state = SS_UNCONNECTED;
258 ei->socket.flags = 0; 264 ei->socket.flags = 0;
259 ei->socket.ops = NULL; 265 ei->socket.ops = NULL;
@@ -263,10 +269,21 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
263 return &ei->vfs_inode; 269 return &ei->vfs_inode;
264} 270}
265 271
272
273static void wq_free_rcu(struct rcu_head *head)
274{
275 struct socket_wq *wq = container_of(head, struct socket_wq, rcu);
276
277 kfree(wq);
278}
279
266static void sock_destroy_inode(struct inode *inode) 280static void sock_destroy_inode(struct inode *inode)
267{ 281{
268 kmem_cache_free(sock_inode_cachep, 282 struct socket_alloc *ei;
269 container_of(inode, struct socket_alloc, vfs_inode)); 283
284 ei = container_of(inode, struct socket_alloc, vfs_inode);
285 call_rcu(&ei->socket.wq->rcu, wq_free_rcu);
286 kmem_cache_free(sock_inode_cachep, ei);
270} 287}
271 288
272static void init_once(void *foo) 289static void init_once(void *foo)
@@ -512,7 +529,7 @@ void sock_release(struct socket *sock)
512 module_put(owner); 529 module_put(owner);
513 } 530 }
514 531
515 if (sock->fasync_list) 532 if (sock->wq->fasync_list)
516 printk(KERN_ERR "sock_release: fasync list not empty!\n"); 533 printk(KERN_ERR "sock_release: fasync list not empty!\n");
517 534
518 percpu_sub(sockets_in_use, 1); 535 percpu_sub(sockets_in_use, 1);
@@ -619,10 +636,9 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
619 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, 636 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
620 sizeof(tv), &tv); 637 sizeof(tv), &tv);
621 } else { 638 } else {
622 struct timespec ts; 639 skb_get_timestampns(skb, &ts[0]);
623 skb_get_timestampns(skb, &ts);
624 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, 640 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
625 sizeof(ts), &ts); 641 sizeof(ts[0]), &ts[0]);
626 } 642 }
627 } 643 }
628 644
@@ -655,13 +671,13 @@ inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, struct sk_buff
655 sizeof(__u32), &skb->dropcount); 671 sizeof(__u32), &skb->dropcount);
656} 672}
657 673
658void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 674void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
659 struct sk_buff *skb) 675 struct sk_buff *skb)
660{ 676{
661 sock_recv_timestamp(msg, sk, skb); 677 sock_recv_timestamp(msg, sk, skb);
662 sock_recv_drops(msg, sk, skb); 678 sock_recv_drops(msg, sk, skb);
663} 679}
664EXPORT_SYMBOL_GPL(sock_recv_ts_and_drops); 680EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
665 681
666static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, 682static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
667 struct msghdr *msg, size_t size, int flags) 683 struct msghdr *msg, size_t size, int flags)
@@ -1067,87 +1083,44 @@ static int sock_close(struct inode *inode, struct file *filp)
1067 * 1. fasync_list is modified only under process context socket lock 1083 * 1. fasync_list is modified only under process context socket lock
1068 * i.e. under semaphore. 1084 * i.e. under semaphore.
1069 * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1085 * 2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1070 * or under socket lock. 1086 * or under socket lock
1071 * 3. fasync_list can be used from softirq context, so that
1072 * modification under socket lock have to be enhanced with
1073 * write_lock_bh(&sk->sk_callback_lock).
1074 * --ANK (990710)
1075 */ 1087 */
1076 1088
1077static int sock_fasync(int fd, struct file *filp, int on) 1089static int sock_fasync(int fd, struct file *filp, int on)
1078{ 1090{
1079 struct fasync_struct *fa, *fna = NULL, **prev; 1091 struct socket *sock = filp->private_data;
1080 struct socket *sock; 1092 struct sock *sk = sock->sk;
1081 struct sock *sk;
1082
1083 if (on) {
1084 fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
1085 if (fna == NULL)
1086 return -ENOMEM;
1087 }
1088
1089 sock = filp->private_data;
1090 1093
1091 sk = sock->sk; 1094 if (sk == NULL)
1092 if (sk == NULL) {
1093 kfree(fna);
1094 return -EINVAL; 1095 return -EINVAL;
1095 }
1096 1096
1097 lock_sock(sk); 1097 lock_sock(sk);
1098 1098
1099 spin_lock(&filp->f_lock); 1099 fasync_helper(fd, filp, on, &sock->wq->fasync_list);
1100 if (on)
1101 filp->f_flags |= FASYNC;
1102 else
1103 filp->f_flags &= ~FASYNC;
1104 spin_unlock(&filp->f_lock);
1105 1100
1106 prev = &(sock->fasync_list); 1101 if (!sock->wq->fasync_list)
1107 1102 sock_reset_flag(sk, SOCK_FASYNC);
1108 for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev) 1103 else
1109 if (fa->fa_file == filp)
1110 break;
1111
1112 if (on) {
1113 if (fa != NULL) {
1114 write_lock_bh(&sk->sk_callback_lock);
1115 fa->fa_fd = fd;
1116 write_unlock_bh(&sk->sk_callback_lock);
1117
1118 kfree(fna);
1119 goto out;
1120 }
1121 fna->fa_file = filp;
1122 fna->fa_fd = fd;
1123 fna->magic = FASYNC_MAGIC;
1124 fna->fa_next = sock->fasync_list;
1125 write_lock_bh(&sk->sk_callback_lock);
1126 sock->fasync_list = fna;
1127 sock_set_flag(sk, SOCK_FASYNC); 1104 sock_set_flag(sk, SOCK_FASYNC);
1128 write_unlock_bh(&sk->sk_callback_lock);
1129 } else {
1130 if (fa != NULL) {
1131 write_lock_bh(&sk->sk_callback_lock);
1132 *prev = fa->fa_next;
1133 if (!sock->fasync_list)
1134 sock_reset_flag(sk, SOCK_FASYNC);
1135 write_unlock_bh(&sk->sk_callback_lock);
1136 kfree(fa);
1137 }
1138 }
1139 1105
1140out: 1106 release_sock(sk);
1141 release_sock(sock->sk);
1142 return 0; 1107 return 0;
1143} 1108}
1144 1109
1145/* This function may be called only under socket lock or callback_lock */ 1110/* This function may be called only under socket lock or callback_lock or rcu_lock */
1146 1111
1147int sock_wake_async(struct socket *sock, int how, int band) 1112int sock_wake_async(struct socket *sock, int how, int band)
1148{ 1113{
1149 if (!sock || !sock->fasync_list) 1114 struct socket_wq *wq;
1115
1116 if (!sock)
1150 return -1; 1117 return -1;
1118 rcu_read_lock();
1119 wq = rcu_dereference(sock->wq);
1120 if (!wq || !wq->fasync_list) {
1121 rcu_read_unlock();
1122 return -1;
1123 }
1151 switch (how) { 1124 switch (how) {
1152 case SOCK_WAKE_WAITD: 1125 case SOCK_WAKE_WAITD:
1153 if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) 1126 if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
@@ -1159,11 +1132,12 @@ int sock_wake_async(struct socket *sock, int how, int band)
1159 /* fall through */ 1132 /* fall through */
1160 case SOCK_WAKE_IO: 1133 case SOCK_WAKE_IO:
1161call_kill: 1134call_kill:
1162 __kill_fasync(sock->fasync_list, SIGIO, band); 1135 kill_fasync(&wq->fasync_list, SIGIO, band);
1163 break; 1136 break;
1164 case SOCK_WAKE_URG: 1137 case SOCK_WAKE_URG:
1165 __kill_fasync(sock->fasync_list, SIGURG, band); 1138 kill_fasync(&wq->fasync_list, SIGURG, band);
1166 } 1139 }
1140 rcu_read_unlock();
1167 return 0; 1141 return 0;
1168} 1142}
1169 1143
@@ -2135,6 +2109,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2135 break; 2109 break;
2136 ++datagrams; 2110 ++datagrams;
2137 2111
2112 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
2113 if (flags & MSG_WAITFORONE)
2114 flags |= MSG_DONTWAIT;
2115
2138 if (timeout) { 2116 if (timeout) {
2139 ktime_get_ts(timeout); 2117 ktime_get_ts(timeout);
2140 *timeout = timespec_sub(end_time, *timeout); 2118 *timeout = timespec_sub(end_time, *timeout);