Print this page
OS-3752 Increase IOV_MAX to at least 1024
OS-2834 ship lx brand

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/streamio.c
          +++ new/usr/src/uts/common/os/streamio.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  22   22  /*        All Rights Reserved   */
  23   23  
  24   24  
  25   25  /*
  26   26   * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  27      - * Copyright (c) 2014, Joyent, Inc. All rights reserved.
       27 + * Copyright 2015, Joyent, Inc. All rights reserved.
  28   28   */
  29   29  
  30   30  #include <sys/types.h>
  31   31  #include <sys/sysmacros.h>
  32   32  #include <sys/param.h>
  33   33  #include <sys/errno.h>
  34   34  #include <sys/signal.h>
  35   35  #include <sys/stat.h>
  36   36  #include <sys/proc.h>
  37   37  #include <sys/cred.h>
↓ open down ↓ 32 lines elided ↑ open up ↑
  70   70  #include <sys/tty.h>
  71   71  #include <sys/ptyvar.h>
  72   72  #include <sys/vuid_event.h>
  73   73  #include <sys/modctl.h>
  74   74  #include <sys/sunddi.h>
  75   75  #include <sys/sunldi_impl.h>
  76   76  #include <sys/autoconf.h>
  77   77  #include <sys/policy.h>
  78   78  #include <sys/dld.h>
  79   79  #include <sys/zone.h>
       80 +#include <sys/limits.h>
  80   81  #include <c2/audit.h>
  81   82  
  82   83  /*
  83   84   * This define helps improve the readability of streams code while
  84   85   * still maintaining a very old streams performance enhancement.  The
  85   86   * performance enhancement basically involved having all callers
  86   87   * of straccess() perform the first check that straccess() will do
  87   88   * locally before actually calling straccess().  (There by reducing
  88   89   * the number of unnecessary calls to straccess().)
  89   90   */
↓ open down ↓ 888 lines elided ↑ open up ↑
 978  979          if (uiop != NULL && stp->sd_struiordq != NULL &&
 979  980              q->q_first == NULL &&
 980  981              (!first || (stp->sd_wakeq & RSLEEP))) {
 981  982                  /*
 982  983                   * Stream supports rwnext() for the read side.
 983  984                   * If this is the first time we're called by e.g. strread
 984  985                   * only do the downcall if there is a deferred wakeup
 985  986                   * (registered in sd_wakeq).
 986  987                   */
 987  988                  struiod_t uiod;
      989 +                struct iovec buf[IOV_MAX_STACK];
      990 +                int iovlen = 0;
 988  991  
 989  992                  if (first)
 990  993                          stp->sd_wakeq &= ~RSLEEP;
 991  994  
 992      -                (void) uiodup(uiop, &uiod.d_uio, uiod.d_iov,
 993      -                    sizeof (uiod.d_iov) / sizeof (*uiod.d_iov));
      995 +                if (uiop->uio_iovcnt > IOV_MAX_STACK) {
      996 +                        iovlen = uiop->uio_iovcnt * sizeof (iovec_t);
      997 +                        uiod.d_iov = kmem_alloc(iovlen, KM_SLEEP);
      998 +                } else {
      999 +                        uiod.d_iov = buf;
     1000 +                }
     1001 +
     1002 +                (void) uiodup(uiop, &uiod.d_uio, uiod.d_iov, uiop->uio_iovcnt);
 994 1003                  uiod.d_mp = 0;
 995 1004                  /*
 996 1005                   * Mark that a thread is in rwnext on the read side
 997 1006                   * to prevent strrput from nacking ioctls immediately.
 998 1007                   * When the last concurrent rwnext returns
 999 1008                   * the ioctls are nack'ed.
1000 1009                   */
1001 1010                  ASSERT(MUTEX_HELD(&stp->sd_lock));
1002 1011                  stp->sd_struiodnak++;
1003 1012                  /*
↓ open down ↓ 18 lines elided ↑ open up ↑
1022 1031                                  mutex_exit(&stp->sd_lock);
1023 1032                                  qreply(q, bp);
1024 1033                                  mutex_enter(&stp->sd_lock);
1025 1034                          }
1026 1035                  }
1027 1036                  ASSERT(MUTEX_HELD(&stp->sd_lock));
1028 1037                  if (error == 0 || error == EWOULDBLOCK) {
1029 1038                          if ((bp = uiod.d_mp) != NULL) {
1030 1039                                  *errorp = 0;
1031 1040                                  ASSERT(MUTEX_HELD(&stp->sd_lock));
     1041 +                                if (iovlen != 0)
     1042 +                                        kmem_free(uiod.d_iov, iovlen);
1032 1043                                  return (bp);
1033 1044                          }
1034 1045                          error = 0;
1035 1046                  } else if (error == EINVAL) {
1036 1047                          /*
1037 1048                           * The stream plumbing must have
1038 1049                           * changed while we were away, so
1039 1050                           * just turn off rwnext()s.
1040 1051                           */
1041 1052                          error = 0;
1042 1053                  } else if (error == EBUSY) {
1043 1054                          /*
1044 1055                           * The module might have data in transit using putnext
1045 1056                           * Fall back on waiting + getq.
1046 1057                           */
1047 1058                          error = 0;
1048 1059                  } else {
1049 1060                          *errorp = error;
1050 1061                          ASSERT(MUTEX_HELD(&stp->sd_lock));
     1062 +                        if (iovlen != 0)
     1063 +                                kmem_free(uiod.d_iov, iovlen);
1051 1064                          return (NULL);
1052 1065                  }
     1066 +
     1067 +                if (iovlen != 0)
     1068 +                        kmem_free(uiod.d_iov, iovlen);
     1069 +
1053 1070                  /*
1054 1071                   * Try a getq in case a rwnext() generated mblk
1055 1072                   * has bubbled up via strrput().
1056 1073                   */
1057 1074          }
1058 1075          *errorp = 0;
1059 1076          ASSERT(MUTEX_HELD(&stp->sd_lock));
1060 1077  
1061 1078          /*
1062 1079           * If we have a valid uio, try and use this as a guide for how
↓ open down ↓ 1474 lines elided ↑ open up ↑
2537 2554   *
2538 2555   * If sd_maxblk is less than *iosize this routine might return without
2539 2556   * transferring all of *iosize. In all cases, on return *iosize will contain
2540 2557   * the amount of data that was transferred.
2541 2558   */
2542 2559  static int
2543 2560  strput(struct stdata *stp, mblk_t *mctl, struct uio *uiop, ssize_t *iosize,
2544 2561      int b_flag, int pri, int flags)
2545 2562  {
2546 2563          struiod_t uiod;
     2564 +        struct iovec buf[IOV_MAX_STACK];
     2565 +        int iovlen = 0;
2547 2566          mblk_t *mp;
2548 2567          queue_t *wqp = stp->sd_wrq;
2549 2568          int error = 0;
2550 2569          ssize_t count = *iosize;
2551 2570  
2552 2571          ASSERT(MUTEX_NOT_HELD(&stp->sd_lock));
2553 2572  
2554 2573          if (uiop != NULL && count >= 0)
2555 2574                  flags |= stp->sd_struiowrq ? STRUIO_POSTPONE : 0;
2556 2575  
↓ open down ↓ 71 lines elided ↑ open up ↑
2628 2647                  else if (mp != NULL)
2629 2648                          linkb(mctl, mp);
2630 2649                  mp = mctl;
2631 2650          } else if (mp == NULL) {
2632 2651                  return (0);
2633 2652          }
2634 2653  
2635 2654          mp->b_flag |= b_flag;
2636 2655          mp->b_band = (uchar_t)pri;
2637 2656  
2638      -        (void) uiodup(uiop, &uiod.d_uio, uiod.d_iov,
2639      -            sizeof (uiod.d_iov) / sizeof (*uiod.d_iov));
     2657 +        if (uiop->uio_iovcnt > IOV_MAX_STACK) {
     2658 +                iovlen = uiop->uio_iovcnt * sizeof (iovec_t);
     2659 +                uiod.d_iov = (struct iovec *)kmem_alloc(iovlen, KM_SLEEP);
     2660 +        } else {
     2661 +                uiod.d_iov = buf;
     2662 +        }
     2663 +
     2664 +        (void) uiodup(uiop, &uiod.d_uio, uiod.d_iov, uiop->uio_iovcnt);
2640 2665          uiod.d_uio.uio_offset = 0;
2641 2666          uiod.d_mp = mp;
2642 2667          error = rwnext(wqp, &uiod);
2643 2668          if (! uiod.d_mp) {
2644 2669                  uioskip(uiop, *iosize);
     2670 +                if (iovlen != 0)
     2671 +                        kmem_free(uiod.d_iov, iovlen);
2645 2672                  return (error);
2646 2673          }
2647 2674          ASSERT(mp == uiod.d_mp);
2648 2675          if (error == EINVAL) {
2649 2676                  /*
2650 2677                   * The stream plumbing must have changed while
2651 2678                   * we were away, so just turn off rwnext()s.
2652 2679                   */
2653 2680                  error = 0;
2654 2681          } else if (error == EBUSY || error == EWOULDBLOCK) {
2655 2682                  /*
2656 2683                   * Couldn't enter a perimeter or took a page fault,
2657 2684                   * so fall-back to putnext().
2658 2685                   */
2659 2686                  error = 0;
2660 2687          } else {
2661 2688                  freemsg(mp);
     2689 +                if (iovlen != 0)
     2690 +                        kmem_free(uiod.d_iov, iovlen);
2662 2691                  return (error);
2663 2692          }
2664 2693          /* Have to check canput before consuming data from the uio */
2665 2694          if (pri == 0) {
2666 2695                  if (!canputnext(wqp) && !(flags & MSG_IGNFLOW)) {
2667 2696                          freemsg(mp);
     2697 +                        if (iovlen != 0)
     2698 +                                kmem_free(uiod.d_iov, iovlen);
2668 2699                          return (EWOULDBLOCK);
2669 2700                  }
2670 2701          } else {
2671 2702                  if (!bcanputnext(wqp, pri) && !(flags & MSG_IGNFLOW)) {
2672 2703                          freemsg(mp);
     2704 +                        if (iovlen != 0)
     2705 +                                kmem_free(uiod.d_iov, iovlen);
2673 2706                          return (EWOULDBLOCK);
2674 2707                  }
2675 2708          }
2676 2709          ASSERT(mp == uiod.d_mp);
2677 2710          /* Copyin data from the uio */
2678 2711          if ((error = struioget(wqp, mp, &uiod, 0)) != 0) {
2679 2712                  freemsg(mp);
     2713 +                if (iovlen != 0)
     2714 +                        kmem_free(uiod.d_iov, iovlen);
2680 2715                  return (error);
2681 2716          }
2682 2717          uioskip(uiop, *iosize);
2683 2718          if (flags & MSG_IGNFLOW) {
2684 2719                  /*
2685 2720                   * XXX Hack: Don't get stuck running service procedures.
2686 2721                   * This is needed for sockfs when sending the unbind message
2687 2722                   * out of the rput procedure - we don't want a put procedure
2688 2723                   * to run service procedures.
2689 2724                   */
2690 2725                  putnext(wqp, mp);
2691 2726          } else {
2692 2727                  stream_willservice(stp);
2693 2728                  putnext(wqp, mp);
2694 2729                  stream_runservice(stp);
2695 2730          }
     2731 +        if (iovlen != 0)
     2732 +                kmem_free(uiod.d_iov, iovlen);
2696 2733          return (0);
2697 2734  }
2698 2735  
2699 2736  /*
2700 2737   * Write attempts to break the write request into messages conforming
2701 2738   * with the minimum and maximum packet sizes set downstream.
2702 2739   *
2703 2740   * Write will not block if downstream queue is full and
2704 2741   * O_NDELAY is set, otherwise it will block waiting for the queue to get room.
2705 2742   *
↓ open down ↓ 465 lines elided ↑ open up ↑
3171 3208          case FIONBIO:
3172 3209          case FIOASYNC:
3173 3210          case FIOSETOWN:
3174 3211          case JBOOT:     /* Obsolete */
3175 3212          case JTERM:     /* Obsolete */
3176 3213          case JTIMOM:    /* Obsolete */
3177 3214          case JZOMBOOT:  /* Obsolete */
3178 3215          case JAGENT:    /* Obsolete */
3179 3216          case JTRUN:     /* Obsolete */
3180 3217          case JXTPROTO:  /* Obsolete */
     3218 +        case TIOCSETLD:
3181 3219                  return (JCSETP);
3182 3220          }
3183 3221  
3184 3222          return (JCGETP);
3185 3223  }
3186 3224  
3187 3225  /*
3188 3226   * ioctl for streams
3189 3227   */
3190 3228  int
↓ open down ↓ 5447 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX