diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2017-07-03 20:14:56 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-11-27 16:19:54 -0500 |
commit | 3ad6f93e98d6df25d0667d847d3ab9cbdccb3eae (patch) | |
tree | 8b52d66806f02c815198e962758ac4199d9ee6e0 | |
parent | e6c8adca20ba459dd88057ca74232bf9f1045075 (diff) |
annotate poll-related wait keys
__poll_t is also used as wait key in some waitqueues.
Verify that wait_..._poll() gets __poll_t as key and
provide a helper for wakeup functions to get back to
that __poll_t value.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | drivers/vfio/virqfd.c | 2 | ||||
-rw-r--r-- | drivers/vhost/vhost.c | 4 | ||||
-rw-r--r-- | fs/eventpoll.c | 9 | ||||
-rw-r--r-- | fs/select.c | 2 | ||||
-rw-r--r-- | include/linux/wait.h | 10 | ||||
-rw-r--r-- | mm/memcontrol.c | 2 | ||||
-rw-r--r-- | net/core/datagram.c | 4 | ||||
-rw-r--r-- | net/unix/af_unix.c | 2 | ||||
-rw-r--r-- | virt/kvm/eventfd.c | 2 |
9 files changed, 19 insertions, 18 deletions
diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c index d18b10ff119e..8cc4b48ff127 100644 --- a/drivers/vfio/virqfd.c +++ b/drivers/vfio/virqfd.c | |||
@@ -46,7 +46,7 @@ static void virqfd_deactivate(struct virqfd *virqfd) | |||
46 | static int virqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key) | 46 | static int virqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key) |
47 | { | 47 | { |
48 | struct virqfd *virqfd = container_of(wait, struct virqfd, wait); | 48 | struct virqfd *virqfd = container_of(wait, struct virqfd, wait); |
49 | unsigned long flags = (unsigned long)key; | 49 | __poll_t flags = key_to_poll(key); |
50 | 50 | ||
51 | if (flags & POLLIN) { | 51 | if (flags & POLLIN) { |
52 | /* An event has been signaled, call function */ | 52 | /* An event has been signaled, call function */ |
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index c18e70bd0466..7aad77be0b46 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
@@ -170,7 +170,7 @@ static int vhost_poll_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, | |||
170 | { | 170 | { |
171 | struct vhost_poll *poll = container_of(wait, struct vhost_poll, wait); | 171 | struct vhost_poll *poll = container_of(wait, struct vhost_poll, wait); |
172 | 172 | ||
173 | if (!((unsigned long)key & poll->mask)) | 173 | if (!(key_to_poll(key) & poll->mask)) |
174 | return 0; | 174 | return 0; |
175 | 175 | ||
176 | vhost_poll_queue(poll); | 176 | vhost_poll_queue(poll); |
@@ -211,7 +211,7 @@ int vhost_poll_start(struct vhost_poll *poll, struct file *file) | |||
211 | 211 | ||
212 | mask = file->f_op->poll(file, &poll->table); | 212 | mask = file->f_op->poll(file, &poll->table); |
213 | if (mask) | 213 | if (mask) |
214 | vhost_poll_wakeup(&poll->wait, 0, 0, (void *)(uintptr_t)mask); | 214 | vhost_poll_wakeup(&poll->wait, 0, 0, poll_to_key(mask)); |
215 | if (mask & POLLERR) { | 215 | if (mask & POLLERR) { |
216 | if (poll->wqh) | 216 | if (poll->wqh) |
217 | remove_wait_queue(poll->wqh, &poll->wait); | 217 | remove_wait_queue(poll->wqh, &poll->wait); |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index afd548ebc328..21e6fee00e8b 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -1117,6 +1117,7 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v | |||
1117 | unsigned long flags; | 1117 | unsigned long flags; |
1118 | struct epitem *epi = ep_item_from_wait(wait); | 1118 | struct epitem *epi = ep_item_from_wait(wait); |
1119 | struct eventpoll *ep = epi->ep; | 1119 | struct eventpoll *ep = epi->ep; |
1120 | __poll_t pollflags = key_to_poll(key); | ||
1120 | int ewake = 0; | 1121 | int ewake = 0; |
1121 | 1122 | ||
1122 | spin_lock_irqsave(&ep->lock, flags); | 1123 | spin_lock_irqsave(&ep->lock, flags); |
@@ -1138,7 +1139,7 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v | |||
1138 | * callback. We need to be able to handle both cases here, hence the | 1139 | * callback. We need to be able to handle both cases here, hence the |
1139 | * test for "key" != NULL before the event match test. | 1140 | * test for "key" != NULL before the event match test. |
1140 | */ | 1141 | */ |
1141 | if (key && !((unsigned long) key & epi->event.events)) | 1142 | if (pollflags && !(pollflags & epi->event.events)) |
1142 | goto out_unlock; | 1143 | goto out_unlock; |
1143 | 1144 | ||
1144 | /* | 1145 | /* |
@@ -1175,8 +1176,8 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v | |||
1175 | */ | 1176 | */ |
1176 | if (waitqueue_active(&ep->wq)) { | 1177 | if (waitqueue_active(&ep->wq)) { |
1177 | if ((epi->event.events & EPOLLEXCLUSIVE) && | 1178 | if ((epi->event.events & EPOLLEXCLUSIVE) && |
1178 | !((unsigned long)key & POLLFREE)) { | 1179 | !(pollflags & POLLFREE)) { |
1179 | switch ((unsigned long)key & EPOLLINOUT_BITS) { | 1180 | switch (pollflags & EPOLLINOUT_BITS) { |
1180 | case POLLIN: | 1181 | case POLLIN: |
1181 | if (epi->event.events & POLLIN) | 1182 | if (epi->event.events & POLLIN) |
1182 | ewake = 1; | 1183 | ewake = 1; |
@@ -1205,7 +1206,7 @@ out_unlock: | |||
1205 | if (!(epi->event.events & EPOLLEXCLUSIVE)) | 1206 | if (!(epi->event.events & EPOLLEXCLUSIVE)) |
1206 | ewake = 1; | 1207 | ewake = 1; |
1207 | 1208 | ||
1208 | if ((unsigned long)key & POLLFREE) { | 1209 | if (pollflags & POLLFREE) { |
1209 | /* | 1210 | /* |
1210 | * If we race with ep_remove_wait_queue() it can miss | 1211 | * If we race with ep_remove_wait_queue() it can miss |
1211 | * ->whead = NULL and do another remove_wait_queue() after | 1212 | * ->whead = NULL and do another remove_wait_queue() after |
diff --git a/fs/select.c b/fs/select.c index b2bf84be5056..ffc16fd3673e 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -212,7 +212,7 @@ static int pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key | |||
212 | struct poll_table_entry *entry; | 212 | struct poll_table_entry *entry; |
213 | 213 | ||
214 | entry = container_of(wait, struct poll_table_entry, wait); | 214 | entry = container_of(wait, struct poll_table_entry, wait); |
215 | if (key && !((unsigned long)key & entry->key)) | 215 | if (key && !(key_to_poll(key) & entry->key)) |
216 | return 0; | 216 | return 0; |
217 | return __pollwake(wait, mode, sync, key); | 217 | return __pollwake(wait, mode, sync, key); |
218 | } | 218 | } |
diff --git a/include/linux/wait.h b/include/linux/wait.h index 158715445ffb..55a611486bac 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h | |||
@@ -206,14 +206,16 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode, int nr); | |||
206 | /* | 206 | /* |
207 | * Wakeup macros to be used to report events to the targets. | 207 | * Wakeup macros to be used to report events to the targets. |
208 | */ | 208 | */ |
209 | #define poll_to_key(m) ((void *)(__force uintptr_t)(__poll_t)(m)) | ||
210 | #define key_to_poll(m) ((__force __poll_t)(uintptr_t)(void *)(m)) | ||
209 | #define wake_up_poll(x, m) \ | 211 | #define wake_up_poll(x, m) \ |
210 | __wake_up(x, TASK_NORMAL, 1, (void *) (m)) | 212 | __wake_up(x, TASK_NORMAL, 1, poll_to_key(m)) |
211 | #define wake_up_locked_poll(x, m) \ | 213 | #define wake_up_locked_poll(x, m) \ |
212 | __wake_up_locked_key((x), TASK_NORMAL, (void *) (m)) | 214 | __wake_up_locked_key((x), TASK_NORMAL, poll_to_key(m)) |
213 | #define wake_up_interruptible_poll(x, m) \ | 215 | #define wake_up_interruptible_poll(x, m) \ |
214 | __wake_up(x, TASK_INTERRUPTIBLE, 1, (void *) (m)) | 216 | __wake_up(x, TASK_INTERRUPTIBLE, 1, poll_to_key(m)) |
215 | #define wake_up_interruptible_sync_poll(x, m) \ | 217 | #define wake_up_interruptible_sync_poll(x, m) \ |
216 | __wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, (void *) (m)) | 218 | __wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, poll_to_key(m)) |
217 | 219 | ||
218 | #define ___wait_cond_timeout(condition) \ | 220 | #define ___wait_cond_timeout(condition) \ |
219 | ({ \ | 221 | ({ \ |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 50e6906314f8..006aa27f4fb4 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -3777,7 +3777,7 @@ static int memcg_event_wake(wait_queue_entry_t *wait, unsigned mode, | |||
3777 | struct mem_cgroup_event *event = | 3777 | struct mem_cgroup_event *event = |
3778 | container_of(wait, struct mem_cgroup_event, wait); | 3778 | container_of(wait, struct mem_cgroup_event, wait); |
3779 | struct mem_cgroup *memcg = event->memcg; | 3779 | struct mem_cgroup *memcg = event->memcg; |
3780 | unsigned long flags = (unsigned long)key; | 3780 | __poll_t flags = key_to_poll(key); |
3781 | 3781 | ||
3782 | if (flags & POLLHUP) { | 3782 | if (flags & POLLHUP) { |
3783 | /* | 3783 | /* |
diff --git a/net/core/datagram.c b/net/core/datagram.c index 522873ed120b..000da13c01f2 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -72,12 +72,10 @@ static inline int connection_based(struct sock *sk) | |||
72 | static int receiver_wake_function(wait_queue_entry_t *wait, unsigned int mode, int sync, | 72 | static int receiver_wake_function(wait_queue_entry_t *wait, unsigned int mode, int sync, |
73 | void *key) | 73 | void *key) |
74 | { | 74 | { |
75 | unsigned long bits = (unsigned long)key; | ||
76 | |||
77 | /* | 75 | /* |
78 | * Avoid a wakeup if event not interesting for us | 76 | * Avoid a wakeup if event not interesting for us |
79 | */ | 77 | */ |
80 | if (bits && !(bits & (POLLIN | POLLERR))) | 78 | if (key && !(key_to_poll(key) & (POLLIN | POLLERR))) |
81 | return 0; | 79 | return 0; |
82 | return autoremove_wake_function(wait, mode, sync, key); | 80 | return autoremove_wake_function(wait, mode, sync, key); |
83 | } | 81 | } |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index a9ee634f3c42..72957961ac22 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -367,7 +367,7 @@ static int unix_dgram_peer_wake_relay(wait_queue_entry_t *q, unsigned mode, int | |||
367 | /* relaying can only happen while the wq still exists */ | 367 | /* relaying can only happen while the wq still exists */ |
368 | u_sleep = sk_sleep(&u->sk); | 368 | u_sleep = sk_sleep(&u->sk); |
369 | if (u_sleep) | 369 | if (u_sleep) |
370 | wake_up_interruptible_poll(u_sleep, key); | 370 | wake_up_interruptible_poll(u_sleep, key_to_poll(key)); |
371 | 371 | ||
372 | return 0; | 372 | return 0; |
373 | } | 373 | } |
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index a1f68ed999d8..a334399fafec 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c | |||
@@ -188,7 +188,7 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key) | |||
188 | { | 188 | { |
189 | struct kvm_kernel_irqfd *irqfd = | 189 | struct kvm_kernel_irqfd *irqfd = |
190 | container_of(wait, struct kvm_kernel_irqfd, wait); | 190 | container_of(wait, struct kvm_kernel_irqfd, wait); |
191 | unsigned long flags = (unsigned long)key; | 191 | __poll_t flags = key_to_poll(key); |
192 | struct kvm_kernel_irq_routing_entry irq; | 192 | struct kvm_kernel_irq_routing_entry irq; |
193 | struct kvm *kvm = irqfd->kvm; | 193 | struct kvm *kvm = irqfd->kvm; |
194 | unsigned seq; | 194 | unsigned seq; |