diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /fs/select.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'fs/select.c')
-rw-r--r-- | fs/select.c | 91 |
1 files changed, 52 insertions, 39 deletions
diff --git a/fs/select.c b/fs/select.c index 2ef72d96503..d33418fdc85 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/syscalls.h> | 19 | #include <linux/syscalls.h> |
20 | #include <linux/export.h> | 20 | #include <linux/module.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/poll.h> | 22 | #include <linux/poll.h> |
23 | #include <linux/personality.h> /* for STICKY_TIMEOUTS */ | 23 | #include <linux/personality.h> /* for STICKY_TIMEOUTS */ |
@@ -220,9 +220,10 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, | |||
220 | struct poll_table_entry *entry = poll_get_entry(pwq); | 220 | struct poll_table_entry *entry = poll_get_entry(pwq); |
221 | if (!entry) | 221 | if (!entry) |
222 | return; | 222 | return; |
223 | entry->filp = get_file(filp); | 223 | get_file(filp); |
224 | entry->filp = filp; | ||
224 | entry->wait_address = wait_address; | 225 | entry->wait_address = wait_address; |
225 | entry->key = p->_key; | 226 | entry->key = p->key; |
226 | init_waitqueue_func_entry(&entry->wait, pollwake); | 227 | init_waitqueue_func_entry(&entry->wait, pollwake); |
227 | entry->wait.private = pwq; | 228 | entry->wait.private = pwq; |
228 | add_wait_queue(wait_address, &entry->wait); | 229 | add_wait_queue(wait_address, &entry->wait); |
@@ -344,10 +345,10 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds) | |||
344 | struct fdtable *fdt; | 345 | struct fdtable *fdt; |
345 | 346 | ||
346 | /* handle last in-complete long-word first */ | 347 | /* handle last in-complete long-word first */ |
347 | set = ~(~0UL << (n & (BITS_PER_LONG-1))); | 348 | set = ~(~0UL << (n & (__NFDBITS-1))); |
348 | n /= BITS_PER_LONG; | 349 | n /= __NFDBITS; |
349 | fdt = files_fdtable(current->files); | 350 | fdt = files_fdtable(current->files); |
350 | open_fds = fdt->open_fds + n; | 351 | open_fds = fdt->open_fds->fds_bits+n; |
351 | max = 0; | 352 | max = 0; |
352 | if (set) { | 353 | if (set) { |
353 | set &= BITS(fds, n); | 354 | set &= BITS(fds, n); |
@@ -372,7 +373,7 @@ get_max: | |||
372 | max++; | 373 | max++; |
373 | set >>= 1; | 374 | set >>= 1; |
374 | } while (set); | 375 | } while (set); |
375 | max += n * BITS_PER_LONG; | 376 | max += n * __NFDBITS; |
376 | } | 377 | } |
377 | 378 | ||
378 | return max; | 379 | return max; |
@@ -385,11 +386,13 @@ get_max: | |||
385 | static inline void wait_key_set(poll_table *wait, unsigned long in, | 386 | static inline void wait_key_set(poll_table *wait, unsigned long in, |
386 | unsigned long out, unsigned long bit) | 387 | unsigned long out, unsigned long bit) |
387 | { | 388 | { |
388 | wait->_key = POLLEX_SET; | 389 | if (wait) { |
389 | if (in & bit) | 390 | wait->key = POLLEX_SET; |
390 | wait->_key |= POLLIN_SET; | 391 | if (in & bit) |
391 | if (out & bit) | 392 | wait->key |= POLLIN_SET; |
392 | wait->_key |= POLLOUT_SET; | 393 | if (out & bit) |
394 | wait->key |= POLLOUT_SET; | ||
395 | } | ||
393 | } | 396 | } |
394 | 397 | ||
395 | int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | 398 | int do_select(int n, fd_set_bits *fds, struct timespec *end_time) |
@@ -411,7 +414,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
411 | poll_initwait(&table); | 414 | poll_initwait(&table); |
412 | wait = &table.pt; | 415 | wait = &table.pt; |
413 | if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { | 416 | if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { |
414 | wait->_qproc = NULL; | 417 | wait = NULL; |
415 | timed_out = 1; | 418 | timed_out = 1; |
416 | } | 419 | } |
417 | 420 | ||
@@ -428,44 +431,45 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
428 | for (i = 0; i < n; ++rinp, ++routp, ++rexp) { | 431 | for (i = 0; i < n; ++rinp, ++routp, ++rexp) { |
429 | unsigned long in, out, ex, all_bits, bit = 1, mask, j; | 432 | unsigned long in, out, ex, all_bits, bit = 1, mask, j; |
430 | unsigned long res_in = 0, res_out = 0, res_ex = 0; | 433 | unsigned long res_in = 0, res_out = 0, res_ex = 0; |
434 | const struct file_operations *f_op = NULL; | ||
435 | struct file *file = NULL; | ||
431 | 436 | ||
432 | in = *inp++; out = *outp++; ex = *exp++; | 437 | in = *inp++; out = *outp++; ex = *exp++; |
433 | all_bits = in | out | ex; | 438 | all_bits = in | out | ex; |
434 | if (all_bits == 0) { | 439 | if (all_bits == 0) { |
435 | i += BITS_PER_LONG; | 440 | i += __NFDBITS; |
436 | continue; | 441 | continue; |
437 | } | 442 | } |
438 | 443 | ||
439 | for (j = 0; j < BITS_PER_LONG; ++j, ++i, bit <<= 1) { | 444 | for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) { |
440 | struct fd f; | 445 | int fput_needed; |
441 | if (i >= n) | 446 | if (i >= n) |
442 | break; | 447 | break; |
443 | if (!(bit & all_bits)) | 448 | if (!(bit & all_bits)) |
444 | continue; | 449 | continue; |
445 | f = fdget(i); | 450 | file = fget_light(i, &fput_needed); |
446 | if (f.file) { | 451 | if (file) { |
447 | const struct file_operations *f_op; | 452 | f_op = file->f_op; |
448 | f_op = f.file->f_op; | ||
449 | mask = DEFAULT_POLLMASK; | 453 | mask = DEFAULT_POLLMASK; |
450 | if (f_op && f_op->poll) { | 454 | if (f_op && f_op->poll) { |
451 | wait_key_set(wait, in, out, bit); | 455 | wait_key_set(wait, in, out, bit); |
452 | mask = (*f_op->poll)(f.file, wait); | 456 | mask = (*f_op->poll)(file, wait); |
453 | } | 457 | } |
454 | fdput(f); | 458 | fput_light(file, fput_needed); |
455 | if ((mask & POLLIN_SET) && (in & bit)) { | 459 | if ((mask & POLLIN_SET) && (in & bit)) { |
456 | res_in |= bit; | 460 | res_in |= bit; |
457 | retval++; | 461 | retval++; |
458 | wait->_qproc = NULL; | 462 | wait = NULL; |
459 | } | 463 | } |
460 | if ((mask & POLLOUT_SET) && (out & bit)) { | 464 | if ((mask & POLLOUT_SET) && (out & bit)) { |
461 | res_out |= bit; | 465 | res_out |= bit; |
462 | retval++; | 466 | retval++; |
463 | wait->_qproc = NULL; | 467 | wait = NULL; |
464 | } | 468 | } |
465 | if ((mask & POLLEX_SET) && (ex & bit)) { | 469 | if ((mask & POLLEX_SET) && (ex & bit)) { |
466 | res_ex |= bit; | 470 | res_ex |= bit; |
467 | retval++; | 471 | retval++; |
468 | wait->_qproc = NULL; | 472 | wait = NULL; |
469 | } | 473 | } |
470 | } | 474 | } |
471 | } | 475 | } |
@@ -477,7 +481,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
477 | *rexp = res_ex; | 481 | *rexp = res_ex; |
478 | cond_resched(); | 482 | cond_resched(); |
479 | } | 483 | } |
480 | wait->_qproc = NULL; | 484 | wait = NULL; |
481 | if (retval || timed_out || signal_pending(current)) | 485 | if (retval || timed_out || signal_pending(current)) |
482 | break; | 486 | break; |
483 | if (table.error) { | 487 | if (table.error) { |
@@ -612,6 +616,7 @@ SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp, | |||
612 | return ret; | 616 | return ret; |
613 | } | 617 | } |
614 | 618 | ||
619 | #ifdef HAVE_SET_RESTORE_SIGMASK | ||
615 | static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp, | 620 | static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp, |
616 | fd_set __user *exp, struct timespec __user *tsp, | 621 | fd_set __user *exp, struct timespec __user *tsp, |
617 | const sigset_t __user *sigmask, size_t sigsetsize) | 622 | const sigset_t __user *sigmask, size_t sigsetsize) |
@@ -683,6 +688,7 @@ SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp, | |||
683 | 688 | ||
684 | return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize); | 689 | return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize); |
685 | } | 690 | } |
691 | #endif /* HAVE_SET_RESTORE_SIGMASK */ | ||
686 | 692 | ||
687 | #ifdef __ARCH_WANT_SYS_OLD_SELECT | 693 | #ifdef __ARCH_WANT_SYS_OLD_SELECT |
688 | struct sel_arg_struct { | 694 | struct sel_arg_struct { |
@@ -714,7 +720,7 @@ struct poll_list { | |||
714 | * interested in events matching the pollfd->events mask, and the result | 720 | * interested in events matching the pollfd->events mask, and the result |
715 | * matching that mask is both recorded in pollfd->revents and returned. The | 721 | * matching that mask is both recorded in pollfd->revents and returned. The |
716 | * pwait poll_table will be used by the fd-provided poll handler for waiting, | 722 | * pwait poll_table will be used by the fd-provided poll handler for waiting, |
717 | * if pwait->_qproc is non-NULL. | 723 | * if non-NULL. |
718 | */ | 724 | */ |
719 | static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) | 725 | static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) |
720 | { | 726 | { |
@@ -724,17 +730,22 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) | |||
724 | mask = 0; | 730 | mask = 0; |
725 | fd = pollfd->fd; | 731 | fd = pollfd->fd; |
726 | if (fd >= 0) { | 732 | if (fd >= 0) { |
727 | struct fd f = fdget(fd); | 733 | int fput_needed; |
734 | struct file * file; | ||
735 | |||
736 | file = fget_light(fd, &fput_needed); | ||
728 | mask = POLLNVAL; | 737 | mask = POLLNVAL; |
729 | if (f.file) { | 738 | if (file != NULL) { |
730 | mask = DEFAULT_POLLMASK; | 739 | mask = DEFAULT_POLLMASK; |
731 | if (f.file->f_op && f.file->f_op->poll) { | 740 | if (file->f_op && file->f_op->poll) { |
732 | pwait->_key = pollfd->events|POLLERR|POLLHUP; | 741 | if (pwait) |
733 | mask = f.file->f_op->poll(f.file, pwait); | 742 | pwait->key = pollfd->events | |
743 | POLLERR | POLLHUP; | ||
744 | mask = file->f_op->poll(file, pwait); | ||
734 | } | 745 | } |
735 | /* Mask out unneeded events. */ | 746 | /* Mask out unneeded events. */ |
736 | mask &= pollfd->events | POLLERR | POLLHUP; | 747 | mask &= pollfd->events | POLLERR | POLLHUP; |
737 | fdput(f); | 748 | fput_light(file, fput_needed); |
738 | } | 749 | } |
739 | } | 750 | } |
740 | pollfd->revents = mask; | 751 | pollfd->revents = mask; |
@@ -752,7 +763,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
752 | 763 | ||
753 | /* Optimise the no-wait case */ | 764 | /* Optimise the no-wait case */ |
754 | if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { | 765 | if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { |
755 | pt->_qproc = NULL; | 766 | pt = NULL; |
756 | timed_out = 1; | 767 | timed_out = 1; |
757 | } | 768 | } |
758 | 769 | ||
@@ -770,22 +781,22 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
770 | for (; pfd != pfd_end; pfd++) { | 781 | for (; pfd != pfd_end; pfd++) { |
771 | /* | 782 | /* |
772 | * Fish for events. If we found one, record it | 783 | * Fish for events. If we found one, record it |
773 | * and kill poll_table->_qproc, so we don't | 784 | * and kill the poll_table, so we don't |
774 | * needlessly register any other waiters after | 785 | * needlessly register any other waiters after |
775 | * this. They'll get immediately deregistered | 786 | * this. They'll get immediately deregistered |
776 | * when we break out and return. | 787 | * when we break out and return. |
777 | */ | 788 | */ |
778 | if (do_pollfd(pfd, pt)) { | 789 | if (do_pollfd(pfd, pt)) { |
779 | count++; | 790 | count++; |
780 | pt->_qproc = NULL; | 791 | pt = NULL; |
781 | } | 792 | } |
782 | } | 793 | } |
783 | } | 794 | } |
784 | /* | 795 | /* |
785 | * All waiters have already been registered, so don't provide | 796 | * All waiters have already been registered, so don't provide |
786 | * a poll_table->_qproc to them on the next loop iteration. | 797 | * a poll_table to them on the next loop iteration. |
787 | */ | 798 | */ |
788 | pt->_qproc = NULL; | 799 | pt = NULL; |
789 | if (!count) { | 800 | if (!count) { |
790 | count = wait->error; | 801 | count = wait->error; |
791 | if (signal_pending(current)) | 802 | if (signal_pending(current)) |
@@ -901,7 +912,7 @@ static long do_restart_poll(struct restart_block *restart_block) | |||
901 | } | 912 | } |
902 | 913 | ||
903 | SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds, | 914 | SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds, |
904 | int, timeout_msecs) | 915 | long, timeout_msecs) |
905 | { | 916 | { |
906 | struct timespec end_time, *to = NULL; | 917 | struct timespec end_time, *to = NULL; |
907 | int ret; | 918 | int ret; |
@@ -934,6 +945,7 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds, | |||
934 | return ret; | 945 | return ret; |
935 | } | 946 | } |
936 | 947 | ||
948 | #ifdef HAVE_SET_RESTORE_SIGMASK | ||
937 | SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, | 949 | SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, |
938 | struct timespec __user *, tsp, const sigset_t __user *, sigmask, | 950 | struct timespec __user *, tsp, const sigset_t __user *, sigmask, |
939 | size_t, sigsetsize) | 951 | size_t, sigsetsize) |
@@ -984,3 +996,4 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, | |||
984 | 996 | ||
985 | return ret; | 997 | return ret; |
986 | } | 998 | } |
999 | #endif /* HAVE_SET_RESTORE_SIGMASK */ | ||