Print this page
14249 pseudo-terminal nomenclature should reflect POSIX
Change-Id: Ib4a3cef899ff4c71b09cb0dc6878863c5e8357bc

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/zcons.c
          +++ new/usr/src/uts/common/io/zcons.c
↓ open down ↓ 22 lines elided ↑ open up ↑
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  
  27   27  /*
  28   28   * Zone Console Driver.
  29   29   *
  30   30   * This driver, derived from the pts/ptm drivers, is the pseudo console driver
  31   31   * for system zones.  Its implementation is straightforward.  Each instance
  32   32   * of the driver represents a global-zone/local-zone pair (this maps in a
  33      - * straightforward way to the commonly used terminal notion of "master side"
  34      - * and "slave side", and we use that terminology throughout).
       33 + * straightforward way to the commonly used terminal notion of "manager side"
       34 + * and "subsidiary side", and we use that terminology throughout).
  35   35   *
  36   36   * Instances of zcons are onlined as children of /pseudo/zconsnex@1/
  37   37   * by zoneadmd in userland, using the devctl framework; thus the driver
  38   38   * does not need to maintain any sort of "admin" node.
  39   39   *
  40      - * The driver shuttles I/O from master side to slave side and back.  In a break
  41      - * from the pts/ptm semantics, if one side is not open, I/O directed towards
  42      - * it will simply be discarded.  This is so that if zoneadmd is not holding
  43      - * the master side console open (i.e. it has died somehow), processes in
  44      - * the zone do not experience any errors and I/O to the console does not
       40 + * The driver shuttles I/O from manager side to subsidiary side and back.  In a
       41 + * break from the pts/ptm semantics, if one side is not open, I/O directed
       42 + * towards it will simply be discarded.  This is so that if zoneadmd is not
       43 + * holding the manager side console open (i.e. it has died somehow), processes
       44 + * in the zone do not experience any errors and I/O to the console does not
  45   45   * hang.
  46   46   *
  47   47   * TODO: we may want to revisit the other direction; i.e. we may want
  48   48   * zoneadmd to be able to detect whether no zone processes are holding the
  49   49   * console open, an unusual situation.
  50   50   *
  51   51   *
  52   52   *
  53      - * MASTER SIDE IOCTLS
       53 + * MANAGER SIDE IOCTLS
  54   54   *
  55      - * The ZC_HOLDSLAVE and ZC_RELEASESLAVE ioctls instruct the master side of the
  56      - * console to hold and release a reference to the slave side's vnode.  They are
  57      - * meant to be issued by zoneadmd after the console device node is created and
  58      - * before it is destroyed so that the slave's STREAMS anchor, ptem, is
  59      - * preserved when ttymon starts popping STREAMS modules from within the
  60      - * associated zone.  This guarantees that the zone console will always have
       55 + * The ZC_HOLDSUBSID and ZC_RELEASESUBSID ioctls instruct the manager side of
       56 + * the console to hold and release a reference to the subsidiary side's vnode.
       57 + * They are meant to be issued by zoneadmd after the console device node is
       58 + * created and before it is destroyed so that the subsidiary's STREAMS anchor,
       59 + * ptem, is preserved when ttymon starts popping STREAMS modules from within
       60 + * the associated zone.  This guarantees that the zone console will always have
  61   61   * terminal semantics while the zone is running.
  62   62   *
  63   63   * Here is the issue: the ptem module is anchored in the zone console
  64      - * (slave side) so that processes within the associated non-global zone will
  65      - * fail to pop it off, thus ensuring that the slave will retain terminal
  66      - * semantics.  When a process attempts to pop the anchor off of a stream, the
  67      - * STREAMS subsystem checks whether the calling process' zone is the same as
  68      - * that of the process that pushed the anchor onto the stream and cancels the
  69      - * pop if they differ.  zoneadmd used to hold an open file descriptor for the
  70      - * slave while the associated non-global zone ran, thus ensuring that the
  71      - * slave's STREAMS anchor would never be popped from within the non-global zone
  72      - * (because zoneadmd runs in the global zone).  However, this file descriptor
  73      - * was removed to make zone console management more robust.  sad(7D) is now
  74      - * used to automatically set up the slave's STREAMS modules when the zone
  75      - * console is freshly opened within the associated non-global zone.  However,
  76      - * when a process within the non-global zone freshly opens the zone console, the
  77      - * anchor is pushed from within the non-global zone, making it possible for
  78      - * processes within the non-global zone (e.g., ttymon) to pop the anchor and
  79      - * destroy the zone console's terminal semantics.
       64 + * (subsidiary side) so that processes within the associated non-global zone
       65 + * will fail to pop it off, thus ensuring that the subsidiary will retain
       66 + * terminal semantics.  When a process attempts to pop the anchor off of a
       67 + * stream, the STREAMS subsystem checks whether the calling process' zone is
       68 + * the same as that of the process that pushed the anchor onto the stream and
       69 + * cancels the pop if they differ.  zoneadmd used to hold an open file
       70 + * descriptor for the subsidiary while the associated non-global zone ran, thus
       71 + * ensuring that the subsidiary's STREAMS anchor would never be popped from
       72 + * within the non-global zone (because zoneadmd runs in the global zone).
       73 + * However, this file descriptor was removed to make zone console management
       74 + * more robust.  sad(7D) is now used to automatically set up the subsidiary's
       75 + * STREAMS modules when the zone console is freshly opened within the
       76 + * associated non-global zone.  However, when a process within the non-global
       77 + * zone freshly opens the zone console, the anchor is pushed from within the
       78 + * non-global zone, making it possible for processes within the non-global zone
       79 + * (e.g., ttymon) to pop the anchor and destroy the zone console's terminal
       80 + * semantics.
  80   81   *
  81      - * One solution is to make the zcons device hold the slave open while the
       82 + * One solution is to make the zcons device hold the subsidiary open while the
  82   83   * associated non-global zone runs so that the STREAMS anchor will always be
  83      - * associated with the global zone.  Unfortunately, the slave cannot be opened
  84      - * from within the zcons driver because the driver is not reentrant: it has
  85      - * an outer STREAMS perimeter.  Therefore, the next best option is for zcons to
  86      - * provide an ioctl interface to zoneadmd to manage holding and releasing
  87      - * the slave side of the console.  It is sufficient to hold the slave side's
  88      - * vnode and bump the associated snode's reference count to preserve the slave's
  89      - * STREAMS configuration while the associated zone runs, so that's what the
  90      - * ioctls do.
       84 + * associated with the global zone.  Unfortunately, the subsidiary cannot be
       85 + * opened from within the zcons driver because the driver is not reentrant: it
       86 + * has an outer STREAMS perimeter.  Therefore, the next best option is for
       87 + * zcons to provide an ioctl interface to zoneadmd to manage holding and
       88 + * releasing the subsidiary side of the console.  It is sufficient to hold the
       89 + * subsidiary side's vnode and bump the associated snode's reference count to
       90 + * preserve the subsidiary's STREAMS configuration while the associated zone
       91 + * runs, so that's what the ioctls do.
  91   92   *
  92   93   *
  93      - * ZC_HOLDSLAVE
       94 + * ZC_HOLDSUBSID
  94   95   *
  95   96   * This ioctl takes a file descriptor as an argument.  It effectively gets a
  96      - * reference to the slave side's minor node's vnode and bumps the associated
  97      - * snode's reference count.  The vnode reference is stored in the zcons device
  98      - * node's soft state.  This ioctl succeeds if the given file descriptor refers
  99      - * to the slave side's minor node or if there is already a reference to the
 100      - * slave side's minor node's vnode in the device's soft state.
       97 + * reference to the subsidiary side's minor node's vnode and bumps the
       98 + * associated snode's reference count.  The vnode reference is stored in the
       99 + * zcons device node's soft state.  This ioctl succeeds if the given file
      100 + * descriptor refers to the subsidiary side's minor node or if there is already
      101 + * a reference to the subsidiary side's minor node's vnode in the device's soft
      102 + * state.
 101  103   *
 102  104   *
 103      - * ZC_RELEASESLAVE
      105 + * ZC_RELEASESUBSID
 104  106   *
 105  107   * This ioctl takes a file descriptor as an argument.  It effectively releases
 106  108   * the vnode reference stored in the zcons device node's soft state (which was
 107      - * previously acquired via ZC_HOLDSLAVE) and decrements the reference count of
      109 + * previously acquired via ZC_HOLDSUBSID) and decrements the reference count of
 108  110   * the snode associated with the vnode.  This ioctl succeeds if the given file
 109      - * descriptor refers to the slave side's minor node or if no reference to the
 110      - * slave side's minor node's vnode is stored in the device's soft state.
      111 + * descriptor refers to the subsidiary side's minor node or if no reference to
      112 + * the subsidiary side's minor node's vnode is stored in the device's soft
      113 + * state.
 111  114   *
 112  115   *
 113  116   * Note that the file descriptor arguments for both ioctls must be cast to
 114  117   * integers of pointer width.
 115  118   *
 116  119   * Here's how the dance between zcons and zoneadmd works:
 117  120   *
 118  121   *     Zone boot:
 119  122   *     1.  While booting the zone, zoneadmd creates an instance of zcons.
 120      - *     2.  zoneadmd opens the master and slave sides of the new zone console
 121      - *         and issues the ZC_HOLDSLAVE ioctl on the master side, passing its
 122      - *         file descriptor for the slave side as the ioctl argument.
 123      - *     3.  zcons holds the slave side's vnode, bumps the snode's reference
      123 + *     2.  zoneadmd opens the manager and subsidiary sides of the new zone
      124 + *         console and issues the ZC_HOLDSUBSID ioctl on the manager side,
      125 + *         passing its file descriptor for the subsidiary side as the ioctl
      126 + *         argument.
      127 + *     3.  zcons holds the subsidiary side's vnode, bumps the snode's reference
 124  128   *         count, and stores a pointer to the vnode in the device's soft
 125  129   *         state.
 126      - *     4.  zoneadmd closes the master and slave sides and continues to boot
 127      - *         the zone.
      130 + *     4.  zoneadmd closes the manager and subsidiary sides and continues to
      131 + *         boot the zone.
 128  132   *
 129  133   *     Zone halt:
 130      - *     1.  While halting the zone, zoneadmd opens the master and slave sides
 131      - *         of the zone's console and issues the ZC_RELEASESLAVE ioctl on the
 132      - *         master side, passing its file descriptor for the slave side as the
 133      - *         ioctl argument.
 134      - *     2.  zcons decrements the slave side's snode's reference count, releases
 135      - *         the slave's vnode, and eliminates its reference to the vnode in the
 136      - *         device's soft state.
 137      - *     3.  zoneadmd closes the master and slave sides.
      134 + *     1.  While halting the zone, zoneadmd opens the manager and subsidiary
      135 + *         sides of the zone's console and issues the ZC_RELEASESUBSID ioctl on
      136 + *         the manager side, passing its file descriptor for the subsidiary
      137 + *         side as the ioctl argument.
      138 + *     2.  zcons decrements the subsidiary side's snode's reference count,
      139 + *         releases the subsidiary's vnode, and eliminates its reference to the
      140 + *         vnode in the device's soft state.
      141 + *     3.  zoneadmd closes the manager and subsidiary sides.
 138  142   *     4.  zoneadmd destroys the zcons device and continues to halt the zone.
 139  143   *
 140      - * It is necessary for zoneadmd to hold the slave open while issuing
 141      - * ZC_RELEASESLAVE because zcons might otherwise release the last reference to
 142      - * the slave's vnode.  If it does, then specfs will panic because it will expect
 143      - * that the STREAMS configuration for the vnode was destroyed, which VN_RELE
 144      - * doesn't do.  Forcing zoneadmd to hold the slave open guarantees that zcons
 145      - * won't release the vnode's last reference.  zoneadmd will properly destroy the
 146      - * vnode and the snode when it closes the file descriptor.
      144 + * It is necessary for zoneadmd to hold the subsidiary open while issuing
      145 + * ZC_RELEASESUBSID because zcons might otherwise release the last reference to
      146 + * the subsidiary's vnode.  If it does, then specfs will panic because it will
      147 + * expect that the STREAMS configuration for the vnode was destroyed, which
      148 + * VN_RELE doesn't do.  Forcing zoneadmd to hold the subsidiary open guarantees
      149 + * that zcons won't release the vnode's last reference.  zoneadmd will properly
      150 + * destroy the vnode and the snode when it closes the file descriptor.
 147  151   *
 148      - * Technically, any process that can access the master side can issue these
      152 + * Technically, any process that can access the manager side can issue these
 149  153   * ioctls, but they should be treated as private interfaces for zoneadmd.
 150  154   */
 151  155  
 152  156  #include <sys/types.h>
 153  157  #include <sys/cmn_err.h>
 154  158  #include <sys/conf.h>
 155  159  #include <sys/cred.h>
 156  160  #include <sys/ddi.h>
 157  161  #include <sys/debug.h>
 158  162  #include <sys/devops.h>
↓ open down ↓ 20 lines elided ↑ open up ↑
 179  183  static int zc_detach(dev_info_t *, ddi_detach_cmd_t);
 180  184  
 181  185  static int zc_open(queue_t *, dev_t *, int, int, cred_t *);
 182  186  static int zc_close(queue_t *, int, cred_t *);
 183  187  static int zc_wput(queue_t *, mblk_t *);
 184  188  static int zc_rsrv(queue_t *);
 185  189  static int zc_wsrv(queue_t *);
 186  190  
 187  191  /*
 188  192   * The instance number is encoded in the dev_t in the minor number; the lowest
 189      - * bit of the minor number is used to track the master vs. slave side of the
 190      - * virtual console.  The rest of the bits in the minor number are the instance.
      193 + * bit of the minor number is used to track the manager vs. subsidiary side of
      194 + * the virtual console.  The rest of the bits in the minor number are the
      195 + * instance.
 191  196   */
 192      -#define ZC_MASTER_MINOR         0
 193      -#define ZC_SLAVE_MINOR          1
      197 +#define ZC_MANAGER_MINOR        0
      198 +#define ZC_SUBSID_MINOR         1
 194  199  
 195  200  #define ZC_INSTANCE(x)          (getminor((x)) >> 1)
 196  201  #define ZC_NODE(x)              (getminor((x)) & 0x01)
 197  202  
 198  203  /*
 199      - * This macro converts a zc_state_t pointer to the associated slave minor node's
 200      - * dev_t.
      204 + * This macro converts a zc_state_t pointer to the associated subsidiary minor
      205 + * node's dev_t.
 201  206   */
 202      -#define ZC_STATE_TO_SLAVEDEV(x) (makedevice(ddi_driver_major((x)->zc_devinfo), \
 203      -        (minor_t)(ddi_get_instance((x)->zc_devinfo) << 1 | ZC_SLAVE_MINOR)))
      207 +#define ZC_STATE_TO_SUBDEV(x)   (makedevice(ddi_driver_major((x)->zc_devinfo), \
      208 +        (minor_t)(ddi_get_instance((x)->zc_devinfo) << 1 | ZC_SUBSID_MINOR)))
 204  209  
 205  210  int zcons_debug = 0;
 206  211  #define DBG(a)   if (zcons_debug) cmn_err(CE_NOTE, a)
 207  212  #define DBG1(a, b)   if (zcons_debug) cmn_err(CE_NOTE, a, b)
 208  213  
 209  214  
 210  215  /*
 211  216   * Zone Console Pseudo Terminal Module: stream data structure definitions
 212  217   */
 213  218  static struct module_info zc_info = {
↓ open down ↓ 51 lines elided ↑ open up ↑
 265  270  };
 266  271  
 267  272  static struct modlinkage modlinkage = {
 268  273          MODREV_1,
 269  274          &modldrv,
 270  275          NULL
 271  276  };
 272  277  
 273  278  typedef struct zc_state {
 274  279          dev_info_t *zc_devinfo;
 275      -        queue_t *zc_master_rdq;
 276      -        queue_t *zc_slave_rdq;
 277      -        vnode_t *zc_slave_vnode;
      280 +        queue_t *zc_manager_rdq;
      281 +        queue_t *zc_subsid_rdq;
      282 +        vnode_t *zc_subsid_vnode;
 278  283          int zc_state;
 279  284  } zc_state_t;
 280  285  
 281  286  #define ZC_STATE_MOPEN  0x01
 282  287  #define ZC_STATE_SOPEN  0x02
 283  288  
 284  289  static void *zc_soft_state;
 285  290  
 286  291  /*
 287      - * List of STREAMS modules that should be pushed onto every slave instance.
      292 + * List of STREAMS modules that should be pushed onto every subsidiary instance.
 288  293   */
 289  294  static char *zcons_mods[] = {
 290  295          "ptem",
 291  296          "ldterm",
 292  297          "ttcompat",
 293  298          NULL
 294  299  };
 295  300  
 296  301  int
 297  302  _init(void)
↓ open down ↓ 38 lines elided ↑ open up ↑
 336  341          int instance;
 337  342  
 338  343          if (cmd != DDI_ATTACH)
 339  344                  return (DDI_FAILURE);
 340  345  
 341  346          instance = ddi_get_instance(dip);
 342  347          if (ddi_soft_state_zalloc(zc_soft_state, instance) != DDI_SUCCESS)
 343  348                  return (DDI_FAILURE);
 344  349  
 345  350          /*
 346      -         * Create the master and slave minor nodes.
      351 +         * Create the manager and subsidiary minor nodes.
 347  352           */
 348      -        if ((ddi_create_minor_node(dip, ZCONS_SLAVE_NAME, S_IFCHR,
 349      -            instance << 1 | ZC_SLAVE_MINOR, DDI_PSEUDO, 0) == DDI_FAILURE) ||
 350      -            (ddi_create_minor_node(dip, ZCONS_MASTER_NAME, S_IFCHR,
 351      -            instance << 1 | ZC_MASTER_MINOR, DDI_PSEUDO, 0) == DDI_FAILURE)) {
      353 +        if ((ddi_create_minor_node(dip, ZCONS_SUBSIDIARY_NAME, S_IFCHR,
      354 +            instance << 1 | ZC_SUBSID_MINOR, DDI_PSEUDO, 0) == DDI_FAILURE) ||
      355 +            (ddi_create_minor_node(dip, ZCONS_MANAGER_NAME, S_IFCHR,
      356 +            instance << 1 | ZC_MANAGER_MINOR, DDI_PSEUDO, 0) == DDI_FAILURE)) {
 352  357                  ddi_remove_minor_node(dip, NULL);
 353  358                  ddi_soft_state_free(zc_soft_state, instance);
 354  359                  return (DDI_FAILURE);
 355  360          }
 356  361  
 357  362          VERIFY((zcs = ddi_get_soft_state(zc_soft_state, instance)) != NULL);
 358  363          zcs->zc_devinfo = dip;
 359  364          return (DDI_SUCCESS);
 360  365  }
 361  366  
↓ open down ↓ 19 lines elided ↑ open up ↑
 381  386          ddi_remove_minor_node(dip, NULL);
 382  387          ddi_soft_state_free(zc_soft_state, instance);
 383  388  
 384  389          return (DDI_SUCCESS);
 385  390  }
 386  391  
 387  392  /*
 388  393   * zc_getinfo()
 389  394   *      getinfo(9e) entrypoint.
 390  395   */
 391      -/*ARGSUSED*/
 392  396  static int
 393  397  zc_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
 394  398  {
 395  399          zc_state_t *zcs;
 396  400          int instance = ZC_INSTANCE((dev_t)arg);
 397  401  
 398  402          switch (infocmd) {
 399  403          case DDI_INFO_DEVT2DEVINFO:
 400  404                  if ((zcs = ddi_get_soft_state(zc_soft_state, instance)) == NULL)
 401  405                          return (DDI_FAILURE);
↓ open down ↓ 1 lines elided ↑ open up ↑
 403  407                  return (DDI_SUCCESS);
 404  408          case DDI_INFO_DEVT2INSTANCE:
 405  409                  *result = (void *)(uintptr_t)instance;
 406  410                  return (DDI_SUCCESS);
 407  411          }
 408  412          return (DDI_FAILURE);
 409  413  }
 410  414  
 411  415  /*
 412  416   * Return the equivalent queue from the other side of the relationship.
 413      - * e.g.: given the slave's write queue, return the master's write queue.
      417 + * e.g.: given the subsidiary's write queue, return the manager's write queue.
 414  418   */
 415  419  static queue_t *
 416  420  zc_switch(queue_t *qp)
 417  421  {
 418  422          zc_state_t *zcs = qp->q_ptr;
 419  423          ASSERT(zcs != NULL);
 420  424  
 421      -        if (qp == zcs->zc_master_rdq)
 422      -                return (zcs->zc_slave_rdq);
 423      -        else if (OTHERQ(qp) == zcs->zc_master_rdq && zcs->zc_slave_rdq != NULL)
 424      -                return (OTHERQ(zcs->zc_slave_rdq));
 425      -        else if (qp == zcs->zc_slave_rdq)
 426      -                return (zcs->zc_master_rdq);
 427      -        else if (OTHERQ(qp) == zcs->zc_slave_rdq && zcs->zc_master_rdq != NULL)
 428      -                return (OTHERQ(zcs->zc_master_rdq));
 429      -        else
      425 +        if (qp == zcs->zc_manager_rdq) {
      426 +                return (zcs->zc_subsid_rdq);
      427 +        } else if (OTHERQ(qp) == zcs->zc_manager_rdq &&
      428 +            zcs->zc_subsid_rdq != NULL) {
      429 +                return (OTHERQ(zcs->zc_subsid_rdq));
      430 +        } else if (qp == zcs->zc_subsid_rdq) {
      431 +                return (zcs->zc_manager_rdq);
      432 +        } else if (OTHERQ(qp) == zcs->zc_subsid_rdq &&
      433 +            zcs->zc_manager_rdq != NULL) {
      434 +                return (OTHERQ(zcs->zc_manager_rdq));
      435 +        } else {
 430  436                  return (NULL);
      437 +        }
 431  438  }
 432  439  
 433  440  /*
 434  441   * For debugging and outputting messages.  Returns the name of the side of
 435  442   * the relationship associated with this queue.
 436  443   */
 437  444  static const char *
 438  445  zc_side(queue_t *qp)
 439  446  {
 440  447          zc_state_t *zcs = qp->q_ptr;
 441  448          ASSERT(zcs != NULL);
 442  449  
 443      -        if (qp == zcs->zc_master_rdq ||
 444      -            OTHERQ(qp) == zcs->zc_master_rdq) {
 445      -                return ("master");
      450 +        if (qp == zcs->zc_manager_rdq ||
      451 +            OTHERQ(qp) == zcs->zc_manager_rdq) {
      452 +                return ("manager");
 446  453          }
 447      -        ASSERT(qp == zcs->zc_slave_rdq || OTHERQ(qp) == zcs->zc_slave_rdq);
 448      -        return ("slave");
      454 +        ASSERT(qp == zcs->zc_subsid_rdq || OTHERQ(qp) == zcs->zc_subsid_rdq);
      455 +        return ("subsidiary");
 449  456  }
 450  457  
 451      -/*ARGSUSED*/
 452  458  static int
 453      -zc_master_open(zc_state_t *zcs,
      459 +zc_manager_open(zc_state_t *zcs,
 454  460      queue_t     *rqp,   /* pointer to the read side queue */
 455  461      dev_t       *devp,  /* pointer to stream tail's dev */
 456  462      int         oflag,  /* the user open(2) supplied flags */
 457  463      int         sflag,  /* open state flag */
 458  464      cred_t      *credp) /* credentials */
 459  465  {
 460  466          mblk_t *mop;
 461  467          struct stroptions *sop;
 462  468  
 463  469          /*
 464      -         * Enforce exclusivity on the master side; the only consumer should
      470 +         * Enforce exclusivity on the manager side; the only consumer should
 465  471           * be the zoneadmd for the zone.
 466  472           */
 467  473          if ((zcs->zc_state & ZC_STATE_MOPEN) != 0)
 468  474                  return (EBUSY);
 469  475  
 470  476          if ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) {
 471      -                DBG("zc_master_open(): mop allocation failed\n");
      477 +                DBG("zc_manager_open(): mop allocation failed\n");
 472  478                  return (ENOMEM);
 473  479          }
 474  480  
 475  481          zcs->zc_state |= ZC_STATE_MOPEN;
 476  482  
 477  483          /*
 478  484           * q_ptr stores driver private data; stash the soft state data on both
 479  485           * read and write sides of the queue.
 480  486           */
 481  487          WR(rqp)->q_ptr = rqp->q_ptr = zcs;
 482  488          qprocson(rqp);
 483  489  
 484  490          /*
 485      -         * Following qprocson(), the master side is fully plumbed into the
 486      -         * STREAM and may send/receive messages.  Setting zcs->zc_master_rdq
 487      -         * will allow the slave to send messages to us (the master).
 488      -         * This cannot occur before qprocson() because the master is not
      491 +         * Following qprocson(), the manager side is fully plumbed into the
      492 +         * STREAM and may send/receive messages.  Setting zcs->zc_manager_rdq
      493 +         * will allow the subsidiary to send messages to us (the manager).
      494 +         * This cannot occur before qprocson() because the manager is not
 489  495           * ready to process them until that point.
 490  496           */
 491      -        zcs->zc_master_rdq = rqp;
      497 +        zcs->zc_manager_rdq = rqp;
 492  498  
 493  499          /*
 494  500           * set up hi/lo water marks on stream head read queue and add
 495  501           * controlling tty as needed.
 496  502           */
 497  503          mop->b_datap->db_type = M_SETOPTS;
 498  504          mop->b_wptr += sizeof (struct stroptions);
 499  505          sop = (struct stroptions *)(void *)mop->b_rptr;
 500  506          if (oflag & FNOCTTY)
 501  507                  sop->so_flags = SO_HIWAT | SO_LOWAT;
 502  508          else
 503  509                  sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
 504  510          sop->so_hiwat = _TTY_BUFSIZ;
 505  511          sop->so_lowat = 256;
 506  512          putnext(rqp, mop);
 507  513  
 508  514          return (0);
 509  515  }
 510  516  
 511      -/*ARGSUSED*/
 512  517  static int
 513      -zc_slave_open(zc_state_t *zcs,
      518 +zc_subsidiary_open(zc_state_t *zcs,
 514  519      queue_t     *rqp,   /* pointer to the read side queue */
 515  520      dev_t       *devp,  /* pointer to stream tail's dev */
 516  521      int         oflag,  /* the user open(2) supplied flags */
 517  522      int         sflag,  /* open state flag */
 518  523      cred_t      *credp) /* credentials */
 519  524  {
 520  525          mblk_t *mop;
 521  526          struct stroptions *sop;
 522  527          major_t major;
 523  528          minor_t minor;
 524  529          minor_t lastminor;
 525  530          uint_t anchorindex;
 526  531  
 527  532          /*
 528      -         * The slave side can be opened as many times as needed.
      533 +         * The subsidiary side can be opened as many times as needed.
 529  534           */
 530  535          if ((zcs->zc_state & ZC_STATE_SOPEN) != 0) {
 531  536                  ASSERT((rqp != NULL) && (WR(rqp)->q_ptr == zcs));
 532  537                  return (0);
 533  538          }
 534  539  
 535  540          /*
 536  541           * Set up sad(7D) so that the necessary STREAMS modules will be in
 537  542           * place.  A wrinkle is that 'ptem' must be anchored
 538  543           * in place (see streamio(7i)) because we always want the console to
 539  544           * have terminal semantics.
 540  545           */
 541      -        minor = ddi_get_instance(zcs->zc_devinfo) << 1 | ZC_SLAVE_MINOR;
      546 +        minor = ddi_get_instance(zcs->zc_devinfo) << 1 | ZC_SUBSID_MINOR;
 542  547          major = ddi_driver_major(zcs->zc_devinfo);
 543  548          lastminor = 0;
 544  549          anchorindex = 1;
 545  550          if (kstr_autopush(SET_AUTOPUSH, &major, &minor, &lastminor,
 546  551              &anchorindex, zcons_mods) != 0) {
 547      -                DBG("zc_slave_open(): kstr_autopush() failed\n");
      552 +                DBG("zc_subsidiary_open(): kstr_autopush() failed\n");
 548  553                  return (EIO);
 549  554          }
 550  555  
 551  556          if ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) {
 552      -                DBG("zc_slave_open(): mop allocation failed\n");
      557 +                DBG("zc_subsidiary_open(): mop allocation failed\n");
 553  558                  return (ENOMEM);
 554  559          }
 555  560  
 556  561          zcs->zc_state |= ZC_STATE_SOPEN;
 557  562  
 558  563          /*
 559  564           * q_ptr stores driver private data; stash the soft state data on both
 560  565           * read and write sides of the queue.
 561  566           */
 562  567          WR(rqp)->q_ptr = rqp->q_ptr = zcs;
 563  568  
 564  569          qprocson(rqp);
 565  570  
 566  571          /*
 567  572           * Must follow qprocson(), since we aren't ready to process until then.
 568  573           */
 569      -        zcs->zc_slave_rdq = rqp;
      574 +        zcs->zc_subsid_rdq = rqp;
 570  575  
 571  576          /*
 572  577           * set up hi/lo water marks on stream head read queue and add
 573  578           * controlling tty as needed.
 574  579           */
 575  580          mop->b_datap->db_type = M_SETOPTS;
 576  581          mop->b_wptr += sizeof (struct stroptions);
 577  582          sop = (struct stroptions *)(void *)mop->b_rptr;
 578  583          sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
 579  584          sop->so_hiwat = _TTY_BUFSIZ;
↓ open down ↓ 17 lines elided ↑ open up ↑
 597  602          int ret;
 598  603          zc_state_t *zcs;
 599  604  
 600  605          if (sflag != 0)
 601  606                  return (EINVAL);
 602  607  
 603  608          if ((zcs = ddi_get_soft_state(zc_soft_state, instance)) == NULL)
 604  609                  return (ENXIO);
 605  610  
 606  611          switch (ZC_NODE(*devp)) {
 607      -        case ZC_MASTER_MINOR:
 608      -                ret = zc_master_open(zcs, rqp, devp, oflag, sflag, credp);
      612 +        case ZC_MANAGER_MINOR:
      613 +                ret = zc_manager_open(zcs, rqp, devp, oflag, sflag, credp);
 609  614                  break;
 610      -        case ZC_SLAVE_MINOR:
 611      -                ret = zc_slave_open(zcs, rqp, devp, oflag, sflag, credp);
      615 +        case ZC_SUBSID_MINOR:
      616 +                ret = zc_subsidiary_open(zcs, rqp, devp, oflag, sflag, credp);
 612  617                  break;
 613  618          default:
 614  619                  ret = ENXIO;
 615  620                  break;
 616  621          }
 617  622  
 618  623          return (ret);
 619  624  }
 620  625  
 621  626  /*
 622  627   * close(9e) entrypoint.
 623  628   */
 624      -/*ARGSUSED1*/
 625  629  static int
 626  630  zc_close(queue_t *rqp, int flag, cred_t *credp)
 627  631  {
 628  632          queue_t *wqp;
 629  633          mblk_t  *bp;
 630  634          zc_state_t *zcs;
 631  635          major_t major;
 632  636          minor_t minor;
 633  637  
 634  638          zcs = (zc_state_t *)rqp->q_ptr;
 635  639  
 636      -        if (rqp == zcs->zc_master_rdq) {
 637      -                DBG("Closing master side");
      640 +        if (rqp == zcs->zc_manager_rdq) {
      641 +                DBG("Closing manager side");
 638  642  
 639      -                zcs->zc_master_rdq = NULL;
      643 +                zcs->zc_manager_rdq = NULL;
 640  644                  zcs->zc_state &= ~ZC_STATE_MOPEN;
 641  645  
 642  646                  /*
 643      -                 * qenable slave side write queue so that it can flush
 644      -                 * its messages as master's read queue is going away
      647 +                 * qenable subsidiary side write queue so that it can flush
      648 +                 * its messages as manager's read queue is going away
 645  649                   */
 646      -                if (zcs->zc_slave_rdq != NULL) {
 647      -                        qenable(WR(zcs->zc_slave_rdq));
      650 +                if (zcs->zc_subsid_rdq != NULL) {
      651 +                        qenable(WR(zcs->zc_subsid_rdq));
 648  652                  }
 649  653  
 650  654                  qprocsoff(rqp);
 651  655                  WR(rqp)->q_ptr = rqp->q_ptr = NULL;
 652  656  
 653      -        } else if (rqp == zcs->zc_slave_rdq) {
      657 +        } else if (rqp == zcs->zc_subsid_rdq) {
 654  658  
 655      -                DBG("Closing slave side");
      659 +                DBG("Closing subsidiary side");
 656  660                  zcs->zc_state &= ~ZC_STATE_SOPEN;
 657      -                zcs->zc_slave_rdq = NULL;
      661 +                zcs->zc_subsid_rdq = NULL;
 658  662  
 659  663                  wqp = WR(rqp);
 660  664                  while ((bp = getq(wqp)) != NULL) {
 661      -                        if (zcs->zc_master_rdq != NULL)
 662      -                                putnext(zcs->zc_master_rdq, bp);
      665 +                        if (zcs->zc_manager_rdq != NULL)
      666 +                                putnext(zcs->zc_manager_rdq, bp);
 663  667                          else if (bp->b_datap->db_type == M_IOCTL)
 664  668                                  miocnak(wqp, bp, 0, 0);
 665  669                          else
 666  670                                  freemsg(bp);
 667  671                  }
 668  672  
 669  673                  /*
 670      -                 * Qenable master side write queue so that it can flush its
 671      -                 * messages as slaves's read queue is going away.
      674 +                 * Qenable manager side write queue so that it can flush its
      675 +                 * messages as subsidiarys's read queue is going away.
 672  676                   */
 673      -                if (zcs->zc_master_rdq != NULL)
 674      -                        qenable(WR(zcs->zc_master_rdq));
      677 +                if (zcs->zc_manager_rdq != NULL)
      678 +                        qenable(WR(zcs->zc_manager_rdq));
 675  679  
 676  680                  qprocsoff(rqp);
 677  681                  WR(rqp)->q_ptr = rqp->q_ptr = NULL;
 678  682  
 679  683                  /*
 680  684                   * Clear the sad configuration so that reopening doesn't fail
 681  685                   * to set up sad configuration.
 682  686                   */
 683  687                  major = ddi_driver_major(zcs->zc_devinfo);
 684      -                minor = ddi_get_instance(zcs->zc_devinfo) << 1 | ZC_SLAVE_MINOR;
      688 +                minor = ddi_get_instance(zcs->zc_devinfo) << 1 |
      689 +                    ZC_SUBSID_MINOR;
 685  690                  (void) kstr_autopush(CLR_AUTOPUSH, &major, &minor, NULL, NULL,
 686  691                      NULL);
 687  692          }
 688  693  
 689  694          return (0);
 690  695  }
 691  696  
 692  697  static void
 693  698  handle_mflush(queue_t *qp, mblk_t *mp)
 694  699  {
↓ open down ↓ 27 lines elided ↑ open up ↑
 722  727  
 723  728          if (*mp->b_rptr & FLUSHR) {
 724  729                  DBG("qreply(qp) turning FLUSHR around\n");
 725  730                  qreply(qp, mp);
 726  731                  return;
 727  732          }
 728  733          freemsg(mp);
 729  734  }
 730  735  
 731  736  /*
 732      - * wput(9E) is symmetric for master and slave sides, so this handles both
      737 + * wput(9E) is symmetric for manager and subsidiary sides, so this handles both
 733  738   * without splitting the codepath.  (The only exception to this is the
 734      - * processing of zcons ioctls, which is restricted to the master side.)
      739 + * processing of zcons ioctls, which is restricted to the manager side.)
 735  740   *
 736  741   * zc_wput() looks at the other side; if there is no process holding that
 737  742   * side open, it frees the message.  This prevents processes from hanging
 738  743   * if no one is holding open the console.  Otherwise, it putnext's high
 739  744   * priority messages, putnext's normal messages if possible, and otherwise
 740  745   * enqueues the messages; in the case that something is enqueued, wsrv(9E)
 741  746   * will take care of eventually shuttling I/O to the other side.
 742  747   */
 743  748  static int
 744  749  zc_wput(queue_t *qp, mblk_t *mp)
 745  750  {
 746  751          unsigned char type = mp->b_datap->db_type;
 747  752          zc_state_t *zcs;
 748  753          struct iocblk *iocbp;
 749      -        file_t *slave_filep;
 750      -        struct snode *slave_snodep;
 751      -        int slave_fd;
      754 +        file_t *subsidiary_filep;
      755 +        struct snode *subsidiary_snodep;
      756 +        int subsidiary_fd;
 752  757  
 753  758          ASSERT(qp->q_ptr);
 754  759  
 755  760          DBG1("entering zc_wput, %s side", zc_side(qp));
 756  761  
 757  762          /*
 758      -         * Process zcons ioctl messages if qp is the master console's write
      763 +         * Process zcons ioctl messages if qp is the manager console's write
 759  764           * queue.
 760  765           */
 761  766          zcs = (zc_state_t *)qp->q_ptr;
 762      -        if (zcs->zc_master_rdq != NULL && qp == WR(zcs->zc_master_rdq) &&
      767 +        if (zcs->zc_manager_rdq != NULL && qp == WR(zcs->zc_manager_rdq) &&
 763  768              type == M_IOCTL) {
 764  769                  iocbp = (struct iocblk *)(void *)mp->b_rptr;
 765  770                  switch (iocbp->ioc_cmd) {
 766      -                case ZC_HOLDSLAVE:
      771 +                case ZC_HOLDSUBSID:
 767  772                          /*
 768      -                         * Hold the slave's vnode and increment the refcount
 769      -                         * of the snode.  If the vnode is already held, then
 770      -                         * indicate success.
      773 +                         * Hold the subsidiary's vnode and increment the
      774 +                         * refcount of the snode.  If the vnode is already
      775 +                         * held, then indicate success.
 771  776                           */
 772  777                          if (iocbp->ioc_count != TRANSPARENT) {
 773  778                                  miocack(qp, mp, 0, EINVAL);
 774  779                                  return (0);
 775  780                          }
 776      -                        if (zcs->zc_slave_vnode != NULL) {
      781 +                        if (zcs->zc_subsid_vnode != NULL) {
 777  782                                  miocack(qp, mp, 0, 0);
 778  783                                  return (0);
 779  784                          }
 780  785  
 781  786                          /*
 782  787                           * The process that passed the ioctl must be running in
 783  788                           * the global zone.
 784  789                           */
 785  790                          if (curzone != global_zone) {
 786  791                                  miocack(qp, mp, 0, EINVAL);
 787  792                                  return (0);
 788  793                          }
 789  794  
 790  795                          /*
 791  796                           * The calling process must pass a file descriptor for
 792      -                         * the slave device.
      797 +                         * the subsidiary device.
 793  798                           */
 794      -                        slave_fd =
      799 +                        subsidiary_fd =
 795  800                              (int)(intptr_t)*(caddr_t *)(void *)mp->b_cont->
 796  801                              b_rptr;
 797      -                        slave_filep = getf(slave_fd);
 798      -                        if (slave_filep == NULL) {
      802 +                        subsidiary_filep = getf(subsidiary_fd);
      803 +                        if (subsidiary_filep == NULL) {
 799  804                                  miocack(qp, mp, 0, EINVAL);
 800  805                                  return (0);
 801  806                          }
 802      -                        if (ZC_STATE_TO_SLAVEDEV(zcs) !=
 803      -                            slave_filep->f_vnode->v_rdev) {
 804      -                                releasef(slave_fd);
      807 +                        if (ZC_STATE_TO_SUBDEV(zcs) !=
      808 +                            subsidiary_filep->f_vnode->v_rdev) {
      809 +                                releasef(subsidiary_fd);
 805  810                                  miocack(qp, mp, 0, EINVAL);
 806  811                                  return (0);
 807  812                          }
 808  813  
 809  814                          /*
 810      -                         * Get a reference to the slave's vnode.  Also bump the
 811      -                         * reference count on the associated snode.
      815 +                         * Get a reference to the subsidiary's vnode.  Also
      816 +                         * bump the reference count on the associated snode.
 812  817                           */
 813      -                        ASSERT(vn_matchops(slave_filep->f_vnode,
      818 +                        ASSERT(vn_matchops(subsidiary_filep->f_vnode,
 814  819                              spec_getvnodeops()));
 815      -                        zcs->zc_slave_vnode = slave_filep->f_vnode;
 816      -                        VN_HOLD(zcs->zc_slave_vnode);
 817      -                        slave_snodep = VTOCS(zcs->zc_slave_vnode);
 818      -                        mutex_enter(&slave_snodep->s_lock);
 819      -                        ++slave_snodep->s_count;
 820      -                        mutex_exit(&slave_snodep->s_lock);
 821      -                        releasef(slave_fd);
      820 +                        zcs->zc_subsid_vnode = subsidiary_filep->f_vnode;
      821 +                        VN_HOLD(zcs->zc_subsid_vnode);
      822 +                        subsidiary_snodep = VTOCS(zcs->zc_subsid_vnode);
      823 +                        mutex_enter(&subsidiary_snodep->s_lock);
      824 +                        ++subsidiary_snodep->s_count;
      825 +                        mutex_exit(&subsidiary_snodep->s_lock);
      826 +                        releasef(subsidiary_fd);
 822  827                          miocack(qp, mp, 0, 0);
 823  828                          return (0);
 824      -                case ZC_RELEASESLAVE:
      829 +                case ZC_RELEASESUBSID:
 825  830                          /*
 826      -                         * Release the master's handle on the slave's vnode.
 827      -                         * If there isn't a handle for the vnode, then indicate
 828      -                         * success.
      831 +                         * Release the manager's handle on the subsidiary's
      832 +                         * vnode.  If there isn't a handle for the vnode, then
      833 +                         * indicate success.
 829  834                           */
 830  835                          if (iocbp->ioc_count != TRANSPARENT) {
 831  836                                  miocack(qp, mp, 0, EINVAL);
 832  837                                  return (0);
 833  838                          }
 834      -                        if (zcs->zc_slave_vnode == NULL) {
      839 +                        if (zcs->zc_subsid_vnode == NULL) {
 835  840                                  miocack(qp, mp, 0, 0);
 836  841                                  return (0);
 837  842                          }
 838  843  
 839  844                          /*
 840  845                           * The process that passed the ioctl must be running in
 841  846                           * the global zone.
 842  847                           */
 843  848                          if (curzone != global_zone) {
 844  849                                  miocack(qp, mp, 0, EINVAL);
 845  850                                  return (0);
 846  851                          }
 847  852  
 848  853                          /*
 849  854                           * The process that passed the ioctl must have provided
 850      -                         * a file descriptor for the slave device.  Make sure
 851      -                         * this is correct.
      855 +                         * a file descriptor for the subsidiary device.  Make
      856 +                         * sure this is correct.
 852  857                           */
 853      -                        slave_fd =
      858 +                        subsidiary_fd =
 854  859                              (int)(intptr_t)*(caddr_t *)(void *)mp->b_cont->
 855  860                              b_rptr;
 856      -                        slave_filep = getf(slave_fd);
 857      -                        if (slave_filep == NULL) {
      861 +                        subsidiary_filep = getf(subsidiary_fd);
      862 +                        if (subsidiary_filep == NULL) {
 858  863                                  miocack(qp, mp, 0, EINVAL);
 859  864                                  return (0);
 860  865                          }
 861      -                        if (zcs->zc_slave_vnode->v_rdev !=
 862      -                            slave_filep->f_vnode->v_rdev) {
 863      -                                releasef(slave_fd);
      866 +                        if (zcs->zc_subsid_vnode->v_rdev !=
      867 +                            subsidiary_filep->f_vnode->v_rdev) {
      868 +                                releasef(subsidiary_fd);
 864  869                                  miocack(qp, mp, 0, EINVAL);
 865  870                                  return (0);
 866  871                          }
 867  872  
 868  873                          /*
 869  874                           * Decrement the snode's reference count and release the
 870  875                           * vnode.
 871  876                           */
 872      -                        ASSERT(vn_matchops(slave_filep->f_vnode,
      877 +                        ASSERT(vn_matchops(subsidiary_filep->f_vnode,
 873  878                              spec_getvnodeops()));
 874      -                        slave_snodep = VTOCS(zcs->zc_slave_vnode);
 875      -                        mutex_enter(&slave_snodep->s_lock);
 876      -                        --slave_snodep->s_count;
 877      -                        mutex_exit(&slave_snodep->s_lock);
 878      -                        VN_RELE(zcs->zc_slave_vnode);
 879      -                        zcs->zc_slave_vnode = NULL;
 880      -                        releasef(slave_fd);
      879 +                        subsidiary_snodep = VTOCS(zcs->zc_subsid_vnode);
      880 +                        mutex_enter(&subsidiary_snodep->s_lock);
      881 +                        --subsidiary_snodep->s_count;
      882 +                        mutex_exit(&subsidiary_snodep->s_lock);
      883 +                        VN_RELE(zcs->zc_subsid_vnode);
      884 +                        zcs->zc_subsid_vnode = NULL;
      885 +                        releasef(subsidiary_fd);
 881  886                          miocack(qp, mp, 0, 0);
 882  887                          return (0);
 883  888                  default:
 884  889                          break;
 885  890                  }
 886  891          }
 887  892  
 888  893          if (zc_switch(RD(qp)) == NULL) {
 889  894                  DBG1("wput to %s side (no one listening)", zc_side(qp));
 890  895                  switch (type) {
↓ open down ↓ 41 lines elided ↑ open up ↑
 932  937                  putnext(RD(zc_switch(qp)), mp);
 933  938          } else {
 934  939                  DBG("wput: putting msg onto queue\n");
 935  940                  (void) putq(qp, mp);
 936  941          }
 937  942          DBG1("done wput, %s side", zc_side(qp));
 938  943          return (0);
 939  944  }
 940  945  
 941  946  /*
 942      - * rsrv(9E) is symmetric for master and slave, so zc_rsrv() handles both
      947 + * rsrv(9E) is symmetric for manager and subsidiary, so zc_rsrv() handles both
 943  948   * without splitting up the codepath.
 944  949   *
 945  950   * Enable the write side of the partner.  This triggers the partner to send
 946  951   * messages queued on its write side to this queue's read side.
 947  952   */
 948  953  static int
 949  954  zc_rsrv(queue_t *qp)
 950  955  {
 951  956          zc_state_t *zcs;
 952  957          zcs = (zc_state_t *)qp->q_ptr;
 953  958  
 954  959          /*
 955      -         * Care must be taken here, as either of the master or slave side
      960 +         * Care must be taken here, as either of the manager or subsidiary side
 956  961           * qptr could be NULL.
 957  962           */
 958      -        ASSERT(qp == zcs->zc_master_rdq || qp == zcs->zc_slave_rdq);
      963 +        ASSERT(qp == zcs->zc_manager_rdq || qp == zcs->zc_subsid_rdq);
 959  964          if (zc_switch(qp) == NULL) {
 960  965                  DBG("zc_rsrv: other side isn't listening\n");
 961  966                  return (0);
 962  967          }
 963  968          qenable(WR(zc_switch(qp)));
 964  969          return (0);
 965  970  }
 966  971  
 967  972  /*
 968      - * This routine is symmetric for master and slave, so it handles both without
 969      - * splitting up the codepath.
      973 + * This routine is symmetric for manager and subsidiary, so it handles both
      974 + * without splitting up the codepath.
 970  975   *
 971  976   * If there are messages on this queue that can be sent to the other, send
 972  977   * them via putnext(). Else, if queued messages cannot be sent, leave them
 973  978   * on this queue.
 974  979   */
 975  980  static int
 976  981  zc_wsrv(queue_t *qp)
 977  982  {
 978  983          mblk_t *mp;
 979  984  
 980      -        DBG1("zc_wsrv master (%s) side", zc_side(qp));
      985 +        DBG1("zc_wsrv manager (%s) side", zc_side(qp));
 981  986  
 982  987          /*
 983  988           * Partner has no read queue, so take the data, and throw it away.
 984  989           */
 985  990          if (zc_switch(RD(qp)) == NULL) {
 986  991                  DBG("zc_wsrv: other side isn't listening");
 987  992                  while ((mp = getq(qp)) != NULL) {
 988  993                          if (mp->b_datap->db_type == M_IOCTL)
 989  994                                  miocnak(qp, mp, 0, 0);
 990  995                          else
↓ open down ↓ 27 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX