Print this page
Merge cleanup from previous six commits
OS-2564 zone boot failed: could not start zoneadmd
OS-4166 zlogin to zfd needs TIOCSWINSZ support
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
OS-3075 zone long boot args aren't passed through

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/zoneadmd/zcons.c
          +++ new/usr/src/cmd/zoneadmd/zcons.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25      - * Copyright 2012 Joyent, Inc.  All rights reserved.
       25 + * Copyright 2015 Joyent, Inc.
  26   26   * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  27   27   */
  28   28  
  29   29  /*
  30   30   * Console support for zones requires a significant infrastructure.  The
  31   31   * core pieces are contained in this file, but other portions of note
  32   32   * are in the zlogin(1M) command, the zcons(7D) driver, and in the
  33   33   * devfsadm(1M) misc_link generator.
  34   34   *
  35   35   * Care is taken to make the console behave in an "intuitive" fashion for
↓ open down ↓ 75 lines elided ↑ open up ↑
 111  111  #include <syslog.h>
 112  112  #include <sys/modctl.h>
 113  113  
 114  114  #include "zoneadmd.h"
 115  115  
 116  116  #define ZCONSNEX_DEVTREEPATH    "/pseudo/zconsnex@1"
 117  117  #define ZCONSNEX_FILEPATH       "/devices/pseudo/zconsnex@1"
 118  118  
 119  119  #define CONSOLE_SOCKPATH        ZONES_TMPDIR "/%s.console_sock"
 120  120  
      121 +#define ZCONS_RETRY             10
      122 +
 121  123  static int      serverfd = -1;  /* console server unix domain socket fd */
 122  124  char boot_args[BOOTARGS_MAX];
 123      -char bad_boot_arg[BOOTARGS_MAX];
 124  125  
 125  126  /*
 126  127   * The eventstream is a simple one-directional flow of messages from the
 127  128   * door server to the console subsystem, implemented with a pipe.
 128  129   * It is used to wake up the console poller when it needs to take action,
 129  130   * message the user, die off, etc.
 130  131   */
 131  132  static int eventstream[2];
 132  133  
      134 +/* flag used to cope with race creating master zcons devlink */
      135 +static boolean_t master_zcons_failed = B_FALSE;
      136 +/* flag to track if we've seen a state change when there is no master zcons */
      137 +static boolean_t state_changed = B_FALSE;
 133  138  
 134      -
 135  139  int
 136  140  eventstream_init()
 137  141  {
 138  142          if (pipe(eventstream) == -1)
 139  143                  return (-1);
 140  144          return (0);
 141  145  }
 142  146  
 143  147  void
 144  148  eventstream_write(zone_evt_t evt)
↓ open down ↓ 256 lines elided ↑ open up ↑
 401  405                  (void) di_devlink_fini(&dl);
 402  406          } else {
 403  407                  zerror(zlogp, B_TRUE, "failed to create devlinks");
 404  408                  goto error;
 405  409          }
 406  410  
 407  411          /*
 408  412           * Open the master side of the console and issue the ZC_HOLDSLAVE ioctl,
 409  413           * which will cause the master to retain a reference to the slave.
 410  414           * This prevents ttymon from blowing through the slave's STREAMS anchor.
      415 +         *
      416 +         * In very rare cases the open returns ENOENT if devfs doesn't have
      417 +         * everything setup yet due to heavy zone startup load. Wait for
      418 +         * 1 sec. and retry a few times. Even if we can't setup the zone's
      419 +         * console, we still go ahead and boot the zone.
 411  420           */
 412  421          (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
 413  422              zone_name, ZCONS_MASTER_NAME);
 414  423          if ((masterfd = open(conspath, O_RDWR | O_NOCTTY)) == -1) {
 415  424                  zerror(zlogp, B_TRUE, "ERROR: could not open master side of "
 416  425                      "zone console for %s to acquire slave handle", zone_name);
 417      -                goto error;
      426 +                master_zcons_failed = B_TRUE;
 418  427          }
 419  428          (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
 420  429              zone_name, ZCONS_SLAVE_NAME);
 421      -        if ((slavefd = open(conspath, O_RDWR | O_NOCTTY)) == -1) {
      430 +        for (i = 0; i < ZCONS_RETRY; i++) {
      431 +                slavefd = open(conspath, O_RDWR | O_NOCTTY);
      432 +                if (slavefd >= 0 || errno != ENOENT)
      433 +                        break;
      434 +                (void) sleep(1);
      435 +        }
      436 +        if (slavefd == -1)
 422  437                  zerror(zlogp, B_TRUE, "ERROR: could not open slave side of zone"
 423  438                      " console for %s to acquire slave handle", zone_name);
 424      -                (void) close(masterfd);
 425      -                goto error;
 426      -        }
      439 +
 427  440          /*
 428  441           * This ioctl can occasionally return ENXIO if devfs doesn't have
 429  442           * everything plumbed up yet due to heavy zone startup load. Wait for
 430  443           * 1 sec. and retry a few times before we fail to boot the zone.
 431  444           */
 432      -        for (i = 0; i < 5; i++) {
 433      -                if (ioctl(masterfd, ZC_HOLDSLAVE, (caddr_t)(intptr_t)slavefd)
 434      -                    == 0) {
 435      -                        rv = 0;
 436      -                        break;
 437      -                } else if (errno != ENXIO) {
 438      -                        break;
      445 +        if (masterfd != -1 && slavefd != -1) {
      446 +                for (i = 0; i < ZCONS_RETRY; i++) {
      447 +                        if (ioctl(masterfd, ZC_HOLDSLAVE,
      448 +                            (caddr_t)(intptr_t)slavefd) == 0) {
      449 +                                rv = 0;
      450 +                                break;
      451 +                        } else if (errno != ENXIO) {
      452 +                                break;
      453 +                        }
      454 +                        (void) sleep(1);
 439  455                  }
 440      -                (void) sleep(1);
      456 +                if (rv != 0)
      457 +                        zerror(zlogp, B_TRUE, "ERROR: error while acquiring "
      458 +                            "slave handle of zone console for %s", zone_name);
 441  459          }
 442      -        if (rv != 0)
 443      -                zerror(zlogp, B_TRUE, "ERROR: error while acquiring slave "
 444      -                    "handle of zone console for %s", zone_name);
 445  460  
 446      -        (void) close(slavefd);
 447      -        (void) close(masterfd);
      461 +        if (slavefd != -1)
      462 +                (void) close(slavefd);
      463 +        if (masterfd != -1)
      464 +                (void) close(masterfd);
 448  465  
 449  466  error:
 450  467          if (ddef_hdl)
 451  468                  devctl_ddef_free(ddef_hdl);
 452  469          if (bus_hdl)
 453  470                  devctl_release(bus_hdl);
 454  471          if (dev_hdl)
 455  472                  devctl_release(dev_hdl);
 456  473          return (rv);
 457  474  }
↓ open down ↓ 52 lines elided ↑ open up ↑
 510  527   * the ident string from a client without saving it.
 511  528   */
 512  529  static int
 513  530  get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len,
 514  531      int *disconnect)
 515  532  {
 516  533          char buf[BUFSIZ], *bufp;
 517  534          size_t buflen = sizeof (buf);
 518  535          char c = '\0';
 519  536          int i = 0, r;
      537 +        ucred_t *cred = NULL;
 520  538  
 521  539          /* "eat up the ident string" case, for simplicity */
 522  540          if (pid == NULL) {
 523  541                  assert(locale == NULL && locale_len == 0);
 524  542                  while (read(clifd, &c, 1) == 1) {
 525  543                          if (c == '\n')
 526  544                                  return (0);
 527  545                  }
 528  546          }
 529  547  
↓ open down ↓ 13 lines elided ↑ open up ↑
 543  561           * We've filled the buffer, but still haven't seen \n.  Keep eating
 544  562           * until we find it; we don't expect this to happen, but this is
 545  563           * defensive.
 546  564           */
 547  565          if (c != '\n') {
 548  566                  while ((r = read(clifd, &c, sizeof (c))) > 0)
 549  567                          if (c == '\n')
 550  568                                  break;
 551  569          }
 552  570  
      571 +        if (getpeerucred(clifd, &cred) == 0) {
      572 +                *pid = ucred_getpid((const ucred_t *)cred);
      573 +                ucred_free(cred);
      574 +        } else {
      575 +                return (-1);
      576 +        }
      577 +
 553  578          /*
 554  579           * Parse buffer for message of the form:
 555      -         * IDENT <pid> <locale> <disconnect flag>
      580 +         * IDENT <locale> <disconnect flag>
 556  581           */
 557  582          bufp = buf;
 558  583          if (strncmp(bufp, "IDENT ", 6) != 0)
 559  584                  return (-1);
 560  585          bufp += 6;
 561  586          errno = 0;
 562      -        *pid = strtoll(bufp, &bufp, 10);
 563      -        if (errno != 0)
 564      -                return (-1);
 565  587  
 566  588          while (*bufp != '\0' && isspace(*bufp))
 567  589                  bufp++;
 568  590          buflen = strlen(bufp) - 1;
 569  591          *disconnect = atoi(&bufp[buflen]);
 570  592          bufp[buflen - 1] = '\0';
 571  593          (void) strlcpy(locale, bufp, locale_len);
 572  594  
 573  595          return (0);
 574  596  }
↓ open down ↓ 85 lines elided ↑ open up ↑
 660  682                  break;
 661  683          case Z_EVT_ZONE_UNINSTALLING:
 662  684                  str = "NOTICE: Zone is being uninstalled.  Disconnecting...";
 663  685                  break;
 664  686          case Z_EVT_ZONE_BOOTFAILED:
 665  687                  if (dflag)
 666  688                          str = "NOTICE: Zone boot failed.  Disconnecting...";
 667  689                  else
 668  690                          str = "NOTICE: Zone boot failed";
 669  691                  break;
 670      -        case Z_EVT_ZONE_BADARGS:
 671      -                /*LINTED*/
 672      -                (void) snprintf(lmsg, sizeof (lmsg),
 673      -                    localize_msg(clilocale,
 674      -                    "WARNING: Ignoring invalid boot arguments: %s"),
 675      -                    bad_boot_arg);
 676      -                lstr = lmsg;
 677      -                break;
 678  692          default:
 679  693                  return;
 680  694          }
 681  695  
 682  696          if (lstr == NULL)
 683  697                  lstr = localize_msg(clilocale, str);
 684  698          (void) snprintf(outbuf, sizeof (outbuf), "\r\n[%s]\r\n", lstr);
 685  699          (void) write(clifd, outbuf, strlen(outbuf));
 686  700  }
 687  701  
↓ open down ↓ 183 lines elided ↑ open up ↑
 871  885                  (void) close(clifd);
 872  886          }
 873  887  }
 874  888  
 875  889  int
 876  890  init_console(zlog_t *zlogp)
 877  891  {
 878  892          if (init_console_dev(zlogp) == -1) {
 879  893                  zerror(zlogp, B_FALSE,
 880  894                      "console setup: device initialization failed");
 881      -                return (-1);
 882  895          }
 883  896  
 884  897          if ((serverfd = init_console_sock(zlogp)) == -1) {
 885  898                  zerror(zlogp, B_FALSE,
 886  899                      "console setup: socket initialization failed");
 887  900                  return (-1);
 888  901          }
 889  902          return (0);
 890  903  }
 891  904  
 892  905  /*
      906 + * Maintain a simple flag that tracks if we have seen at least one state
      907 + * change. This is currently only used to handle the special case where we are
      908 + * running without a console device, which is what normally drives shutdown.
      909 + */
      910 +void
      911 +zcons_statechanged()
      912 +{
      913 +        state_changed = B_TRUE;
      914 +}
      915 +
      916 +/*
 893  917   * serve_console() is the master loop for driving console I/O.  It is also the
 894  918   * routine which is ultimately responsible for "pulling the plug" on zoneadmd
 895  919   * when it realizes that the daemon should shut down.
 896  920   *
 897  921   * The rules for shutdown are: there must be no console client, and the zone
 898  922   * state must be < ready.  However, we need to give things a chance to actually
 899  923   * get going when the daemon starts up-- otherwise the daemon would immediately
 900  924   * exit on startup if the zone was in the installed state, so we first drop
 901  925   * into the do_console_io() loop in order to give *something* a chance to
 902  926   * happen.
 903  927   */
 904  928  void
 905  929  serve_console(zlog_t *zlogp)
 906  930  {
 907  931          int masterfd;
 908  932          zone_state_t zstate;
 909  933          char conspath[MAXPATHLEN];
      934 +        static boolean_t cons_warned = B_FALSE;
 910  935  
 911  936          (void) snprintf(conspath, sizeof (conspath),
 912  937              "/dev/zcons/%s/%s", zone_name, ZCONS_MASTER_NAME);
 913  938  
 914  939          for (;;) {
 915  940                  masterfd = open(conspath, O_RDWR|O_NONBLOCK|O_NOCTTY);
 916  941                  if (masterfd == -1) {
      942 +                        if (master_zcons_failed) {
      943 +                                /*
      944 +                                 * If we don't have a console and the zone is
      945 +                                 * not shutting down, there may have been a
      946 +                                 * race/failure with devfs while creating the
      947 +                                 * console. In this case we want to leave the
      948 +                                 * zone up, even without a console, so
      949 +                                 * periodically recheck.
      950 +                                 */
      951 +                                int i;
      952 +
      953 +                                /*
      954 +                                 * In the normal flow of this loop, we use
      955 +                                 * do_console_io to give things a chance to get
      956 +                                 * going first. However, in this case we can't
      957 +                                 * use that, so we have to wait for at least
      958 +                                 * one state change before checking the state.
      959 +                                 */
      960 +                                for (i = 0; i < 60; i++) {
      961 +                                        if (state_changed)
      962 +                                                break;
      963 +                                        (void) sleep(1);
      964 +                                }
      965 +
      966 +                                if (i < 60 && zone_get_state(zone_name,
      967 +                                    &zstate) == Z_OK &&
      968 +                                    (zstate == ZONE_STATE_READY ||
      969 +                                    zstate == ZONE_STATE_RUNNING)) {
      970 +                                        if (!cons_warned) {
      971 +                                                zerror(zlogp, B_FALSE,
      972 +                                                    "WARNING: missing zone "
      973 +                                                    "console for %s",
      974 +                                                    zone_name);
      975 +                                                cons_warned = B_TRUE;
      976 +                                        }
      977 +                                        (void) sleep(ZCONS_RETRY);
      978 +                                        continue;
      979 +                                }
      980 +                        }
      981 +
 917  982                          zerror(zlogp, B_TRUE, "failed to open console master");
 918  983                          (void) mutex_lock(&lock);
 919  984                          goto death;
 920  985                  }
 921  986  
 922  987                  /*
 923  988                   * Setting RPROTDIS on the stream means that the control
 924  989                   * portion of messages received (which we don't care about)
 925  990                   * will be discarded by the stream head.  If we allowed such
 926  991                   * messages, we wouldn't be able to use read(2), as it fails
↓ open down ↓ 51 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX