aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/socket.c73
1 files changed, 11 insertions, 62 deletions
diff --git a/net/socket.c b/net/socket.c
index 35bc198bbf68..9822081eab38 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1067,78 +1067,27 @@ static int sock_close(struct inode *inode, struct file *filp)
1067 * 1. fasync_list is modified only under process context socket lock 1067 * 1. fasync_list is modified only under process context socket lock
1068 * i.e. under semaphore. 1068 * i.e. under semaphore.
1069 * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1069 * 2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1070 * or under socket lock. 1070 * 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 */ 1071 */
1076 1072
1077static int sock_fasync(int fd, struct file *filp, int on) 1073static int sock_fasync(int fd, struct file *filp, int on)
1078{ 1074{
1079 struct fasync_struct *fa, *fna = NULL, **prev; 1075 struct socket *sock = filp->private_data;
1080 struct socket *sock; 1076 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 1077
1091 sk = sock->sk; 1078 if (sk == NULL)
1092 if (sk == NULL) {
1093 kfree(fna);
1094 return -EINVAL; 1079 return -EINVAL;
1095 }
1096 1080
1097 lock_sock(sk); 1081 lock_sock(sk);
1098 1082
1099 spin_lock(&filp->f_lock); 1083 fasync_helper(fd, filp, on, &sock->fasync_list);
1100 if (on)
1101 filp->f_flags |= FASYNC;
1102 else
1103 filp->f_flags &= ~FASYNC;
1104 spin_unlock(&filp->f_lock);
1105
1106 prev = &(sock->fasync_list);
1107 1084
1108 for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev) 1085 if (!sock->fasync_list)
1109 if (fa->fa_file == filp) 1086 sock_reset_flag(sk, SOCK_FASYNC);
1110 break; 1087 else
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); 1088 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 1089
1140out: 1090 release_sock(sk);
1141 release_sock(sock->sk);
1142 return 0; 1091 return 0;
1143} 1092}
1144 1093
@@ -1159,10 +1108,10 @@ int sock_wake_async(struct socket *sock, int how, int band)
1159 /* fall through */ 1108 /* fall through */
1160 case SOCK_WAKE_IO: 1109 case SOCK_WAKE_IO:
1161call_kill: 1110call_kill:
1162 __kill_fasync(sock->fasync_list, SIGIO, band); 1111 kill_fasync(&sock->fasync_list, SIGIO, band);
1163 break; 1112 break;
1164 case SOCK_WAKE_URG: 1113 case SOCK_WAKE_URG:
1165 __kill_fasync(sock->fasync_list, SIGURG, band); 1114 kill_fasync(&sock->fasync_list, SIGURG, band);
1166 } 1115 }
1167 return 0; 1116 return 0;
1168} 1117}