Print this page
Merge cleanup from previous six commits
OS-200 need a better mechanism for storing persistent zone_did
OS-2564 zone boot failed: could not start zoneadmd
OS-1763 mount of /etc/svc/volatile failed: Device busy
OS-511 make zonecfg device resource extensible, like the net resource
OS-224 add more zonecfg net properties

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/zoneadmd/zoneadmd.c
          +++ new/usr/src/cmd/zoneadmd/zoneadmd.c
↓ open down ↓ 137 lines elided ↑ open up ↑
 138  138  
 139  139  boolean_t in_death_throes = B_FALSE;    /* daemon is dying */
 140  140  boolean_t bringup_failure_recovery = B_FALSE; /* ignore certain failures */
 141  141  
 142  142  #if !defined(TEXT_DOMAIN)               /* should be defined by cc -D */
 143  143  #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it wasn't */
 144  144  #endif
 145  145  
 146  146  #define DEFAULT_LOCALE  "C"
 147  147  
      148 +#define RSRC_NET        "net"
      149 +#define RSRC_DEV        "device"
      150 +
 148  151  static const char *
 149  152  z_cmd_name(zone_cmd_t zcmd)
 150  153  {
 151  154          /* This list needs to match the enum in sys/zone.h */
 152  155          static const char *zcmdstr[] = {
 153  156                  "ready", "boot", "forceboot", "reboot", "halt",
 154  157                  "note_uninstalling", "mount", "forcemount", "unmount",
 155  158                  "shutdown"
 156  159          };
 157  160  
↓ open down ↓ 516 lines elided ↑ open up ↑
 674  677          if ((child = fork()) == -1) {
 675  678                  (void) ct_tmpl_clear(tmpl_fd);
 676  679                  (void) close(tmpl_fd);
 677  680                  zerror(zlogp, B_TRUE, "failed to fork");
 678  681                  return (-1);
 679  682  
 680  683          } else if (child == 0) {        /* child */
 681  684                  char opt_buf[MAX_MNTOPT_STR];
 682  685                  int optlen = 0;
 683  686                  int mflag = MS_DATA;
      687 +                int i;
      688 +                int ret;
 684  689  
 685  690                  (void) ct_tmpl_clear(tmpl_fd);
 686  691                  /*
 687  692                   * Even though there are no procs running in the zone, we
 688  693                   * do this for paranoia's sake.
 689  694                   */
 690  695                  (void) closefrom(0);
 691  696  
 692  697                  if (zone_enter(zoneid) == -1) {
 693  698                          _exit(errno);
↓ open down ↓ 7 lines elided ↑ open up ↑
 701  706                           * also fail if the new option string it wants to
 702  707                           * write is bigger than the one we passed in, so
 703  708                           * you must pass in a buffer of the maximum possible
 704  709                           * option string length.  sigh.
 705  710                           */
 706  711                          (void) strlcpy(opt_buf, opt, sizeof (opt_buf));
 707  712                          opt = opt_buf;
 708  713                          optlen = MAX_MNTOPT_STR;
 709  714                          mflag = MS_OPTIONSTR;
 710  715                  }
 711      -                if (mount(spec, dir, mflag, fstype, NULL, 0, opt, optlen) != 0)
 712      -                        _exit(errno);
 713      -                _exit(0);
      716 +
      717 +                /*
      718 +                 * There is an obscure race condition which can cause mount
      719 +                 * to return EBUSY. This happens for example on the mount
      720 +                 * of the zone's /etc/svc/volatile file system if there is
      721 +                 * a GZ process running svcs -Z, which will touch the
      722 +                 * mountpoint, just as we're trying to do the mount. To cope
      723 +                 * with this, we retry up to 3 times to let this transient
      724 +                 * process get out of the way.
      725 +                 */
      726 +                for (i = 0; i < 3; i++) {
      727 +                        ret = 0;
      728 +                        if (mount(spec, dir, mflag, fstype, NULL, 0, opt,
      729 +                            optlen) != 0)
      730 +                                ret = errno;
      731 +                        if (ret != EBUSY)
      732 +                                break;
      733 +                        (void) sleep(1);
      734 +                }
      735 +                _exit(ret);
 714  736          }
 715  737  
 716  738          /* parent */
 717  739          if (contract_latest(&ct) == -1)
 718  740                  ct = -1;
 719  741          (void) ct_tmpl_clear(tmpl_fd);
 720  742          (void) close(tmpl_fd);
 721  743          if (waitpid(child, &child_status, 0) != child) {
 722  744                  /* unexpected: we must have been signalled */
 723  745                  (void) contract_abandon_id(ct);
↓ open down ↓ 3 lines elided ↑ open up ↑
 727  749          if (WEXITSTATUS(child_status) != 0) {
 728  750                  errno = WEXITSTATUS(child_status);
 729  751                  zerror(zlogp, B_TRUE, "mount of %s failed", dir);
 730  752                  return (-1);
 731  753          }
 732  754  
 733  755          return (0);
 734  756  }
 735  757  
 736  758  /*
      759 + * env variable name format
      760 + *      _ZONECFG;{resource name};{identifying attr. name};{property name}
      761 + */
      762 +static void
      763 +set_zonecfg_env(char *rsrc, char *attr, char *name, char *val)
      764 +{
      765 +        char *p;
      766 +        /* Enough for maximal name, rsrc + attr, & slop for ZONECFG & _'s */
      767 +        char nm[2 * MAXNAMELEN + 32];
      768 +
      769 +        if (attr == NULL)
      770 +                (void) snprintf(nm, sizeof (nm), "_ZONECFG_%s_%s", rsrc,
      771 +                    name);
      772 +        else
      773 +                (void) snprintf(nm, sizeof (nm), "_ZONECFG_%s_%s_%s", rsrc,
      774 +                    attr, name);
      775 +
      776 +        p = nm;
      777 +        while ((p = strchr(p, '-')) != NULL)
      778 +                *p++ = '_';
      779 +
      780 +        (void) setenv(nm, val, 1);
      781 +}
      782 +
      783 +/*
      784 + * Export zonecfg network and device properties into environment for the boot
      785 + * and state change hooks.
      786 + * If debug is true, export the brand hook debug env. variable as well.
      787 + *
      788 + * We could export more of the config in the future, as necessary.
      789 + */
      790 +static int
      791 +setup_subproc_env()
      792 +{
      793 +        int res;
      794 +        zone_dochandle_t handle;
      795 +        struct zone_nwiftab ntab;
      796 +        struct zone_devtab dtab;
      797 +        char net_resources[MAXNAMELEN * 2];
      798 +        char dev_resources[MAXNAMELEN * 2];
      799 +
      800 +        if ((handle = zonecfg_init_handle()) == NULL)
      801 +                exit(Z_NOMEM);
      802 +
      803 +        if ((res = zonecfg_get_handle(zone_name, handle)) != Z_OK)
      804 +                goto done;
      805 +
      806 +        if ((res = zonecfg_setnwifent(handle)) != Z_OK)
      807 +                goto done;
      808 +
      809 +        while (zonecfg_getnwifent(handle, &ntab) == Z_OK) {
      810 +                struct zone_res_attrtab *rap;
      811 +                char *phys;
      812 +
      813 +                phys = ntab.zone_nwif_physical;
      814 +
      815 +                (void) strlcat(net_resources, phys, sizeof (net_resources));
      816 +                (void) strlcat(net_resources, " ", sizeof (net_resources));
      817 +
      818 +                set_zonecfg_env(RSRC_NET, phys, "physical", phys);
      819 +
      820 +                set_zonecfg_env(RSRC_NET, phys, "address",
      821 +                    ntab.zone_nwif_address);
      822 +                set_zonecfg_env(RSRC_NET, phys, "allowed-address",
      823 +                    ntab.zone_nwif_allowed_address);
      824 +                set_zonecfg_env(RSRC_NET, phys, "defrouter",
      825 +                    ntab.zone_nwif_defrouter);
      826 +                set_zonecfg_env(RSRC_NET, phys, "global-nic",
      827 +                    ntab.zone_nwif_gnic);
      828 +                set_zonecfg_env(RSRC_NET, phys, "mac-addr", ntab.zone_nwif_mac);
      829 +                set_zonecfg_env(RSRC_NET, phys, "vlan-id",
      830 +                    ntab.zone_nwif_vlan_id);
      831 +
      832 +                for (rap = ntab.zone_nwif_attrp; rap != NULL;
      833 +                    rap = rap->zone_res_attr_next)
      834 +                        set_zonecfg_env(RSRC_NET, phys, rap->zone_res_attr_name,
      835 +                            rap->zone_res_attr_value);
      836 +        }
      837 +
      838 +        (void) zonecfg_endnwifent(handle);
      839 +
      840 +        if ((res = zonecfg_setdevent(handle)) != Z_OK)
      841 +                goto done;
      842 +
      843 +        while (zonecfg_getdevent(handle, &dtab) == Z_OK) {
      844 +                struct zone_res_attrtab *rap;
      845 +                char *match;
      846 +
      847 +                match = dtab.zone_dev_match;
      848 +
      849 +                (void) strlcat(dev_resources, match, sizeof (dev_resources));
      850 +                (void) strlcat(dev_resources, " ", sizeof (dev_resources));
      851 +
      852 +                for (rap = dtab.zone_dev_attrp; rap != NULL;
      853 +                    rap = rap->zone_res_attr_next)
      854 +                        set_zonecfg_env(RSRC_DEV, match,
      855 +                            rap->zone_res_attr_name, rap->zone_res_attr_value);
      856 +        }
      857 +
      858 +        (void) zonecfg_enddevent(handle);
      859 +
      860 +        res = Z_OK;
      861 +
      862 +done:
      863 +        zonecfg_fini_handle(handle);
      864 +        return (res);
      865 +}
      866 +
      867 +/*
 737  868   * If retstr is not NULL, the output of the subproc is returned in the str,
 738  869   * otherwise it is output using zerror().  Any memory allocated for retstr
 739  870   * should be freed by the caller.
 740  871   */
 741  872  int
 742  873  do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr)
 743  874  {
 744  875          char buf[1024];         /* arbitrary large amount */
 745  876          char *inbuf;
 746  877          FILE *file;
↓ open down ↓ 4 lines elided ↑ open up ↑
 751  882                  if ((*retstr = malloc(1024)) == NULL) {
 752  883                          zerror(zlogp, B_FALSE, "out of memory");
 753  884                          return (-1);
 754  885                  }
 755  886                  inbuf = *retstr;
 756  887                  rd_cnt = 0;
 757  888          } else {
 758  889                  inbuf = buf;
 759  890          }
 760  891  
      892 +        if (setup_subproc_env() != Z_OK) {
      893 +                zerror(zlogp, B_FALSE, "failed to setup environment");
      894 +                return (-1);
      895 +        }
      896 +
 761  897          file = popen(cmdbuf, "r");
 762  898          if (file == NULL) {
 763  899                  zerror(zlogp, B_TRUE, "could not launch: %s", cmdbuf);
 764  900                  return (-1);
 765  901          }
 766  902  
 767  903          while (fgets(inbuf, 1024, file) != NULL) {
 768  904                  if (retstr == NULL) {
 769  905                          if (zlogp != &logsys)
 770  906                                  zerror(zlogp, B_FALSE, "%s", inbuf);
↓ open down ↓ 685 lines elided ↑ open up ↑
1456 1592                      "%s operation is invalid for zones in state '%s'",
1457 1593                      z_cmd_name(cmd), zone_state_str(zstate));
1458 1594                  break;
1459 1595  
1460 1596          case ZONE_STATE_INSTALLED:
1461 1597                  switch (cmd) {
1462 1598                  case Z_READY:
1463 1599                          rval = zone_ready(zlogp, Z_MNT_BOOT, zstate);
1464 1600                          if (rval == 0)
1465 1601                                  eventstream_write(Z_EVT_ZONE_READIED);
     1602 +                        zcons_statechanged();
1466 1603                          break;
1467 1604                  case Z_BOOT:
1468 1605                  case Z_FORCEBOOT:
1469 1606                          eventstream_write(Z_EVT_ZONE_BOOTING);
1470 1607                          if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate))
1471 1608                              == 0) {
1472 1609                                  rval = zone_bootup(zlogp, zargp->bootbuf,
1473 1610                                      zstate);
1474 1611                          }
1475 1612                          audit_put_record(zlogp, uc, rval, "boot");
     1613 +                        zcons_statechanged();
1476 1614                          if (rval != 0) {
1477 1615                                  bringup_failure_recovery = B_TRUE;
1478 1616                                  (void) zone_halt(zlogp, B_FALSE, B_FALSE,
1479 1617                                      zstate);
1480 1618                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1481 1619                          }
1482 1620                          break;
1483 1621                  case Z_SHUTDOWN:
1484 1622                  case Z_HALT:
1485 1623                          if (kernelcall) /* Invalid; can't happen */
↓ open down ↓ 102 lines elided ↑ open up ↑
1588 1726                           */
1589 1727                          zerror(zlogp, B_FALSE, "zone is already ready");
1590 1728                          rval = 0;
1591 1729                          break;
1592 1730                  case Z_BOOT:
1593 1731                          (void) strlcpy(boot_args, zargp->bootbuf,
1594 1732                              sizeof (boot_args));
1595 1733                          eventstream_write(Z_EVT_ZONE_BOOTING);
1596 1734                          rval = zone_bootup(zlogp, zargp->bootbuf, zstate);
1597 1735                          audit_put_record(zlogp, uc, rval, "boot");
     1736 +                        zcons_statechanged();
1598 1737                          if (rval != 0) {
1599 1738                                  bringup_failure_recovery = B_TRUE;
1600 1739                                  (void) zone_halt(zlogp, B_FALSE, B_TRUE,
1601 1740                                      zstate);
1602 1741                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1603 1742                          }
1604 1743                          boot_args[0] = '\0';
1605 1744                          break;
1606 1745                  case Z_HALT:
1607 1746                          if (kernelcall) /* Invalid; can't happen */
1608 1747                                  abort();
1609 1748                          if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate))
1610 1749                              != 0)
1611 1750                                  break;
     1751 +                        zcons_statechanged();
1612 1752                          eventstream_write(Z_EVT_ZONE_HALTED);
1613 1753                          break;
1614 1754                  case Z_SHUTDOWN:
1615 1755                  case Z_REBOOT:
1616 1756                  case Z_NOTE_UNINSTALLING:
1617 1757                  case Z_MOUNT:
1618 1758                  case Z_UNMOUNT:
1619 1759                          if (kernelcall) /* Invalid; can't happen */
1620 1760                                  abort();
1621 1761                          zerror(zlogp, B_FALSE, "%s operation is invalid "
↓ open down ↓ 27 lines elided ↑ open up ↑
1649 1789                  break;
1650 1790  
1651 1791          case ZONE_STATE_RUNNING:
1652 1792          case ZONE_STATE_SHUTTING_DOWN:
1653 1793          case ZONE_STATE_DOWN:
1654 1794                  switch (cmd) {
1655 1795                  case Z_READY:
1656 1796                          if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate))
1657 1797                              != 0)
1658 1798                                  break;
     1799 +                        zcons_statechanged();
1659 1800                          if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) == 0)
1660 1801                                  eventstream_write(Z_EVT_ZONE_READIED);
1661 1802                          else
1662 1803                                  eventstream_write(Z_EVT_ZONE_HALTED);
1663 1804                          break;
1664 1805                  case Z_BOOT:
1665 1806                          /*
1666 1807                           * We could have two clients racing to boot this
1667 1808                           * zone; the second client loses, but his request
1668 1809                           * doesn't fail, since the zone is now in the desired
↓ open down ↓ 5 lines elided ↑ open up ↑
1674 1815                  case Z_HALT:
1675 1816                          if (kernelcall) {
1676 1817                                  log_init_exit(init_status);
1677 1818                          } else {
1678 1819                                  log_init_exit(-1);
1679 1820                          }
1680 1821                          if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate))
1681 1822                              != 0)
1682 1823                                  break;
1683 1824                          eventstream_write(Z_EVT_ZONE_HALTED);
     1825 +                        zcons_statechanged();
1684 1826                          break;
1685 1827                  case Z_REBOOT:
1686 1828                          (void) strlcpy(boot_args, zargp->bootbuf,
1687 1829                              sizeof (boot_args));
1688 1830                          eventstream_write(Z_EVT_ZONE_REBOOTING);
1689 1831                          if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate))
1690 1832                              != 0) {
1691 1833                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1692 1834                                  boot_args[0] = '\0';
1693 1835                                  break;
1694 1836                          }
1695      -                        if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate))
1696      -                            != 0) {
     1837 +                        zcons_statechanged();
     1838 +                        if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) !=
     1839 +                            0) {
1697 1840                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1698 1841                                  boot_args[0] = '\0';
1699 1842                                  break;
1700 1843                          }
1701 1844                          rval = zone_bootup(zlogp, zargp->bootbuf, zstate);
1702 1845                          audit_put_record(zlogp, uc, rval, "reboot");
1703 1846                          if (rval != 0) {
1704 1847                                  (void) zone_halt(zlogp, B_FALSE, B_TRUE,
1705 1848                                      zstate);
1706 1849                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
↓ open down ↓ 737 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX