aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-28 12:43:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-28 13:40:47 -0400
commita11e1d432b51f63ba698d044441284a661f01144 (patch)
tree9f3c5a10bf0d7f9a342d5fb39c0c35ea14170124 /net/socket.c
parentf57494321cbf5b1e7769b6135407d2995a369e28 (diff)
Revert changes to convert to ->poll_mask() and aio IOCB_CMD_POLL
The poll() changes were not well thought out, and completely unexplained. They also caused a huge performance regression, because "->poll()" was no longer a trivial file operation that just called down to the underlying file operations, but instead did at least two indirect calls. Indirect calls are sadly slow now with the Spectre mitigation, but the performance problem could at least be largely mitigated by changing the "->get_poll_head()" operation to just have a per-file-descriptor pointer to the poll head instead. That gets rid of one of the new indirections. But that doesn't fix the new complexity that is completely unwarranted for the regular case. The (undocumented) reason for the poll() changes was some alleged AIO poll race fixing, but we don't make the common case slower and more complex for some uncommon special case, so this all really needs way more explanations and most likely a fundamental redesign. [ This revert is a revert of about 30 different commits, not reverted individually because that would just be unnecessarily messy - Linus ] Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c48
1 files changed, 5 insertions, 43 deletions
diff --git a/net/socket.c b/net/socket.c
index 8a109012608a..a564c6ed19d5 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -117,10 +117,8 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
117static int sock_mmap(struct file *file, struct vm_area_struct *vma); 117static int sock_mmap(struct file *file, struct vm_area_struct *vma);
118 118
119static int sock_close(struct inode *inode, struct file *file); 119static int sock_close(struct inode *inode, struct file *file);
120static struct wait_queue_head *sock_get_poll_head(struct file *file, 120static __poll_t sock_poll(struct file *file,
121 __poll_t events); 121 struct poll_table_struct *wait);
122static __poll_t sock_poll_mask(struct file *file, __poll_t);
123static __poll_t sock_poll(struct file *file, struct poll_table_struct *wait);
124static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 122static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
125#ifdef CONFIG_COMPAT 123#ifdef CONFIG_COMPAT
126static long compat_sock_ioctl(struct file *file, 124static long compat_sock_ioctl(struct file *file,
@@ -143,8 +141,6 @@ static const struct file_operations socket_file_ops = {
143 .llseek = no_llseek, 141 .llseek = no_llseek,
144 .read_iter = sock_read_iter, 142 .read_iter = sock_read_iter,
145 .write_iter = sock_write_iter, 143 .write_iter = sock_write_iter,
146 .get_poll_head = sock_get_poll_head,
147 .poll_mask = sock_poll_mask,
148 .poll = sock_poll, 144 .poll = sock_poll,
149 .unlocked_ioctl = sock_ioctl, 145 .unlocked_ioctl = sock_ioctl,
150#ifdef CONFIG_COMPAT 146#ifdef CONFIG_COMPAT
@@ -1130,48 +1126,14 @@ out_release:
1130} 1126}
1131EXPORT_SYMBOL(sock_create_lite); 1127EXPORT_SYMBOL(sock_create_lite);
1132 1128
1133static struct wait_queue_head *sock_get_poll_head(struct file *file,
1134 __poll_t events)
1135{
1136 struct socket *sock = file->private_data;
1137
1138 if (!sock->ops->poll_mask)
1139 return NULL;
1140 sock_poll_busy_loop(sock, events);
1141 return sk_sleep(sock->sk);
1142}
1143
1144static __poll_t sock_poll_mask(struct file *file, __poll_t events)
1145{
1146 struct socket *sock = file->private_data;
1147
1148 /*
1149 * We need to be sure we are in sync with the socket flags modification.
1150 *
1151 * This memory barrier is paired in the wq_has_sleeper.
1152 */
1153 smp_mb();
1154
1155 /* this socket can poll_ll so tell the system call */
1156 return sock->ops->poll_mask(sock, events) |
1157 (sk_can_busy_loop(sock->sk) ? POLL_BUSY_LOOP : 0);
1158}
1159
1160/* No kernel lock held - perfect */ 1129/* No kernel lock held - perfect */
1161static __poll_t sock_poll(struct file *file, poll_table *wait) 1130static __poll_t sock_poll(struct file *file, poll_table *wait)
1162{ 1131{
1163 struct socket *sock = file->private_data; 1132 struct socket *sock = file->private_data;
1164 __poll_t events = poll_requested_events(wait), mask = 0; 1133 __poll_t events = poll_requested_events(wait);
1165
1166 if (sock->ops->poll) {
1167 sock_poll_busy_loop(sock, events);
1168 mask = sock->ops->poll(file, sock, wait);
1169 } else if (sock->ops->poll_mask) {
1170 sock_poll_wait(file, sock_get_poll_head(file, events), wait);
1171 mask = sock->ops->poll_mask(sock, events);
1172 }
1173 1134
1174 return mask | sock_poll_busy_flag(sock); 1135 sock_poll_busy_loop(sock, events);
1136 return sock->ops->poll(file, sock, wait) | sock_poll_busy_flag(sock);
1175} 1137}
1176 1138
1177static int sock_mmap(struct file *file, struct vm_area_struct *vma) 1139static int sock_mmap(struct file *file, struct vm_area_struct *vma)