Skip to content

Commit 1525242

Browse files
author
Christoph Hellwig
committed
net: add support for ->poll_mask in proto_ops
The socket file operations still implement ->poll until all protocols are switched over. Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 3cafb37 commit 1525242

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

include/linux/net.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ struct proto_ops {
147147
int (*getname) (struct socket *sock,
148148
struct sockaddr *addr,
149149
int peer);
150+
__poll_t (*poll_mask) (struct socket *sock, __poll_t events);
150151
__poll_t (*poll) (struct file *file, struct socket *sock,
151152
struct poll_table_struct *wait);
152153
int (*ioctl) (struct socket *sock, unsigned int cmd,

net/socket.c

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,10 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
117117
static int sock_mmap(struct file *file, struct vm_area_struct *vma);
118118

119119
static int sock_close(struct inode *inode, struct file *file);
120-
static __poll_t sock_poll(struct file *file,
121-
struct poll_table_struct *wait);
120+
static struct wait_queue_head *sock_get_poll_head(struct file *file,
121+
__poll_t events);
122+
static __poll_t sock_poll_mask(struct file *file, __poll_t);
123+
static __poll_t sock_poll(struct file *file, struct poll_table_struct *wait);
122124
static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
123125
#ifdef CONFIG_COMPAT
124126
static long compat_sock_ioctl(struct file *file,
@@ -141,6 +143,8 @@ static const struct file_operations socket_file_ops = {
141143
.llseek = no_llseek,
142144
.read_iter = sock_read_iter,
143145
.write_iter = sock_write_iter,
146+
.get_poll_head = sock_get_poll_head,
147+
.poll_mask = sock_poll_mask,
144148
.poll = sock_poll,
145149
.unlocked_ioctl = sock_ioctl,
146150
#ifdef CONFIG_COMPAT
@@ -1114,14 +1118,48 @@ int sock_create_lite(int family, int type, int protocol, struct socket **res)
11141118
}
11151119
EXPORT_SYMBOL(sock_create_lite);
11161120

1121+
static struct wait_queue_head *sock_get_poll_head(struct file *file,
1122+
__poll_t events)
1123+
{
1124+
struct socket *sock = file->private_data;
1125+
1126+
if (!sock->ops->poll_mask)
1127+
return NULL;
1128+
sock_poll_busy_loop(sock, events);
1129+
return sk_sleep(sock->sk);
1130+
}
1131+
1132+
static __poll_t sock_poll_mask(struct file *file, __poll_t events)
1133+
{
1134+
struct socket *sock = file->private_data;
1135+
1136+
/*
1137+
* We need to be sure we are in sync with the socket flags modification.
1138+
*
1139+
* This memory barrier is paired in the wq_has_sleeper.
1140+
*/
1141+
smp_mb();
1142+
1143+
/* this socket can poll_ll so tell the system call */
1144+
return sock->ops->poll_mask(sock, events) |
1145+
(sk_can_busy_loop(sock->sk) ? POLL_BUSY_LOOP : 0);
1146+
}
1147+
11171148
/* No kernel lock held - perfect */
11181149
static __poll_t sock_poll(struct file *file, poll_table *wait)
11191150
{
11201151
struct socket *sock = file->private_data;
1121-
__poll_t events = poll_requested_events(wait);
1152+
__poll_t events = poll_requested_events(wait), mask = 0;
11221153

1123-
sock_poll_busy_loop(sock, events);
1124-
return sock->ops->poll(file, sock, wait) | sock_poll_busy_flag(sock);
1154+
if (sock->ops->poll) {
1155+
sock_poll_busy_loop(sock, events);
1156+
mask = sock->ops->poll(file, sock, wait);
1157+
} else if (sock->ops->poll_mask) {
1158+
sock_poll_wait(file, sock_get_poll_head(file, events), wait);
1159+
mask = sock->ops->poll_mask(sock, events);
1160+
}
1161+
1162+
return mask | sock_poll_busy_flag(sock);
11251163
}
11261164

11271165
static int sock_mmap(struct file *file, struct vm_area_struct *vma)

0 commit comments

Comments
 (0)