Commit 252e5725cfb55a89e54888317856903fef9d5031

Authored by Oleg Nesterov
Committed by Linus Torvalds
1 parent 759d7c6c47

do_sys_poll: simplify playing with on-stack data

Cleanup. Lessens both the source and compiled code (100 bytes) and imho makes
the code much more understandable.

With this patch "struct poll_list *head" always points to on-stack stack_pps,
so we can remove all "is it on-stack" and "was it initialized" checks.

Also, move poll_initwait/poll_freewait and -EINTR detection closer to the
do_poll()'s callsite.

[akpm@linux-foundation.org: fix warning (size_t != uint)]
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Looks-good-to: Andi Kleen <ak@suse.de>
Cc: Davide Libenzi <davidel@xmailserver.org>
Cc: Vadim Lobanov <vlobanov@speakeasy.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 36 additions and 56 deletions Side-by-side Diff

... ... @@ -651,86 +651,66 @@
651 651 int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
652 652 {
653 653 struct poll_wqueues table;
654   - int fdcount, err;
655   - unsigned int i;
656   - struct poll_list *head;
657   - struct poll_list *walk;
  654 + int err = -EFAULT, fdcount, len, size;
658 655 /* Allocate small arguments on the stack to save memory and be
659 656 faster - use long to make sure the buffer is aligned properly
660 657 on 64 bit archs to avoid unaligned access */
661 658 long stack_pps[POLL_STACK_ALLOC/sizeof(long)];
662   - struct poll_list *stack_pp = NULL;
  659 + struct poll_list *const head = (struct poll_list *)stack_pps;
  660 + struct poll_list *walk = head;
  661 + unsigned long todo = nfds;
663 662  
664   - /* Do a sanity check on nfds ... */
665 663 if (nfds > current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
666 664 return -EINVAL;
667 665  
668   - poll_initwait(&table);
  666 + len = min_t(unsigned int, nfds, N_STACK_PPS);
  667 + for (;;) {
  668 + walk->next = NULL;
  669 + walk->len = len;
  670 + if (!len)
  671 + break;
669 672  
670   - head = NULL;
671   - walk = NULL;
672   - i = nfds;
673   - err = -ENOMEM;
674   - while(i!=0) {
675   - struct poll_list *pp;
676   - int num, size;
677   - if (stack_pp == NULL)
678   - num = N_STACK_PPS;
679   - else
680   - num = POLLFD_PER_PAGE;
681   - if (num > i)
682   - num = i;
683   - size = sizeof(struct poll_list) + sizeof(struct pollfd)*num;
684   - if (!stack_pp)
685   - stack_pp = pp = (struct poll_list *)stack_pps;
686   - else {
687   - pp = kmalloc(size, GFP_KERNEL);
688   - if (!pp)
689   - goto out_fds;
690   - }
691   - pp->next=NULL;
692   - pp->len = num;
693   - if (head == NULL)
694   - head = pp;
695   - else
696   - walk->next = pp;
  673 + if (copy_from_user(walk->entries, ufds + nfds-todo,
  674 + sizeof(struct pollfd) * walk->len))
  675 + goto out_fds;
697 676  
698   - walk = pp;
699   - if (copy_from_user(pp->entries, ufds + nfds-i,
700   - sizeof(struct pollfd)*num)) {
701   - err = -EFAULT;
  677 + todo -= walk->len;
  678 + if (!todo)
  679 + break;
  680 +
  681 + len = min(todo, POLLFD_PER_PAGE);
  682 + size = sizeof(struct poll_list) + sizeof(struct pollfd) * len;
  683 + walk = walk->next = kmalloc(size, GFP_KERNEL);
  684 + if (!walk) {
  685 + err = -ENOMEM;
702 686 goto out_fds;
703 687 }
704   - i -= pp->len;
705 688 }
706 689  
  690 + poll_initwait(&table);
707 691 fdcount = do_poll(nfds, head, &table, timeout);
  692 + if (!fdcount && signal_pending(current))
  693 + fdcount = -EINTR;
  694 + poll_freewait(&table);
708 695  
709   - /* OK, now copy the revents fields back to user space. */
710   - walk = head;
711   - err = -EFAULT;
712   - while(walk != NULL) {
  696 + for (walk = head; walk; walk = walk->next) {
713 697 struct pollfd *fds = walk->entries;
714 698 int j;
715 699  
716   - for (j=0; j < walk->len; j++, ufds++) {
717   - if(__put_user(fds[j].revents, &ufds->revents))
  700 + for (j = 0; j < walk->len; j++, ufds++)
  701 + if (__put_user(fds[j].revents, &ufds->revents))
718 702 goto out_fds;
719   - }
720   - walk = walk->next;
721 703 }
  704 +
722 705 err = fdcount;
723   - if (!fdcount && signal_pending(current))
724   - err = -EINTR;
725 706 out_fds:
726   - walk = head;
727   - while(walk!=NULL) {
728   - struct poll_list *pp = walk->next;
729   - if (walk != stack_pp)
730   - kfree(walk);
731   - walk = pp;
  707 + walk = head->next;
  708 + while (walk) {
  709 + struct poll_list *pos = walk;
  710 + walk = walk->next;
  711 + kfree(pos);
732 712 }
733   - poll_freewait(&table);
  713 +
734 714 return err;
735 715 }
736 716