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