aboutsummaryrefslogtreecommitdiffstats
path: root/fs/select.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/select.c')
-rw-r--r--fs/select.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/fs/select.c b/fs/select.c
index 0fe0e1469df3..d870237e42c7 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -168,7 +168,7 @@ static struct poll_table_entry *poll_get_entry(struct poll_wqueues *p)
168 return table->entry++; 168 return table->entry++;
169} 169}
170 170
171static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key) 171static int __pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
172{ 172{
173 struct poll_wqueues *pwq = wait->private; 173 struct poll_wqueues *pwq = wait->private;
174 DECLARE_WAITQUEUE(dummy_wait, pwq->polling_task); 174 DECLARE_WAITQUEUE(dummy_wait, pwq->polling_task);
@@ -194,6 +194,16 @@ static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
194 return default_wake_function(&dummy_wait, mode, sync, key); 194 return default_wake_function(&dummy_wait, mode, sync, key);
195} 195}
196 196
197static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
198{
199 struct poll_table_entry *entry;
200
201 entry = container_of(wait, struct poll_table_entry, wait);
202 if (key && !((unsigned long)key & entry->key))
203 return 0;
204 return __pollwake(wait, mode, sync, key);
205}
206
197/* Add a new entry */ 207/* Add a new entry */
198static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, 208static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
199 poll_table *p) 209 poll_table *p)
@@ -205,6 +215,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
205 get_file(filp); 215 get_file(filp);
206 entry->filp = filp; 216 entry->filp = filp;
207 entry->wait_address = wait_address; 217 entry->wait_address = wait_address;
218 entry->key = p->key;
208 init_waitqueue_func_entry(&entry->wait, pollwake); 219 init_waitqueue_func_entry(&entry->wait, pollwake);
209 entry->wait.private = pwq; 220 entry->wait.private = pwq;
210 add_wait_queue(wait_address, &entry->wait); 221 add_wait_queue(wait_address, &entry->wait);
@@ -362,6 +373,18 @@ get_max:
362#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR) 373#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
363#define POLLEX_SET (POLLPRI) 374#define POLLEX_SET (POLLPRI)
364 375
376static inline void wait_key_set(poll_table *wait, unsigned long in,
377 unsigned long out, unsigned long bit)
378{
379 if (wait) {
380 wait->key = POLLEX_SET;
381 if (in & bit)
382 wait->key |= POLLIN_SET;
383 if (out & bit)
384 wait->key |= POLLOUT_SET;
385 }
386}
387
365int do_select(int n, fd_set_bits *fds, struct timespec *end_time) 388int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
366{ 389{
367 ktime_t expire, *to = NULL; 390 ktime_t expire, *to = NULL;
@@ -418,20 +441,25 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
418 if (file) { 441 if (file) {
419 f_op = file->f_op; 442 f_op = file->f_op;
420 mask = DEFAULT_POLLMASK; 443 mask = DEFAULT_POLLMASK;
421 if (f_op && f_op->poll) 444 if (f_op && f_op->poll) {
422 mask = (*f_op->poll)(file, retval ? NULL : wait); 445 wait_key_set(wait, in, out, bit);
446 mask = (*f_op->poll)(file, wait);
447 }
423 fput_light(file, fput_needed); 448 fput_light(file, fput_needed);
424 if ((mask & POLLIN_SET) && (in & bit)) { 449 if ((mask & POLLIN_SET) && (in & bit)) {
425 res_in |= bit; 450 res_in |= bit;
426 retval++; 451 retval++;
452 wait = NULL;
427 } 453 }
428 if ((mask & POLLOUT_SET) && (out & bit)) { 454 if ((mask & POLLOUT_SET) && (out & bit)) {
429 res_out |= bit; 455 res_out |= bit;
430 retval++; 456 retval++;
457 wait = NULL;
431 } 458 }
432 if ((mask & POLLEX_SET) && (ex & bit)) { 459 if ((mask & POLLEX_SET) && (ex & bit)) {
433 res_ex |= bit; 460 res_ex |= bit;
434 retval++; 461 retval++;
462 wait = NULL;
435 } 463 }
436 } 464 }
437 } 465 }
@@ -685,8 +713,12 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait)
685 mask = POLLNVAL; 713 mask = POLLNVAL;
686 if (file != NULL) { 714 if (file != NULL) {
687 mask = DEFAULT_POLLMASK; 715 mask = DEFAULT_POLLMASK;
688 if (file->f_op && file->f_op->poll) 716 if (file->f_op && file->f_op->poll) {
717 if (pwait)
718 pwait->key = pollfd->events |
719 POLLERR | POLLHUP;
689 mask = file->f_op->poll(file, pwait); 720 mask = file->f_op->poll(file, pwait);
721 }
690 /* Mask out unneeded events. */ 722 /* Mask out unneeded events. */
691 mask &= pollfd->events | POLLERR | POLLHUP; 723 mask &= pollfd->events | POLLERR | POLLHUP;
692 fput_light(file, fput_needed); 724 fput_light(file, fput_needed);