Print this page
post-merge correct dlmgmt_db.c
15167 Panic when halting a zone with self-created links
15407 zone_free asserts to its destruction when dlmgmtd has fallen
15408 dlmgmtd/zoneadmd interdependencies prevent dlmgmtd from starting
15409 dlmgmtd forking with write locks results in deadlock chaos
Portions contributed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Portions contributed by: Joshua M. Clulow <jmc@joyent.com>
Portions contributed by: Robert Mustacchi <rm@joyent.com>
Portions contributed by: Ryan Zezeski <rpz@joyent.com>
Change-ID: I17810387d2142c5c7e426e106e4c2dbb8f2496d4
Conflicts:
    usr/src/cmd/dlmgmtd/dlmgmt_db.c
    usr/src/cmd/dlmgmtd/dlmgmt_door.c
    usr/src/cmd/dlmgmtd/dlmgmt_impl.h
    usr/src/cmd/dlmgmtd/dlmgmt_main.c
    usr/src/cmd/dlmgmtd/dlmgmt_util.c
    usr/src/cmd/zoneadmd/vplat.c
    usr/src/lib/libdladm/common/libdladm.h
    usr/src/lib/libdladm/common/libdlmgmt.c
    usr/src/uts/common/io/dls/dls_mgmt.c

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/dlmgmtd/dlmgmt_db.c
          +++ new/usr/src/cmd/dlmgmtd/dlmgmt_db.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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright 2016 Joyent, Inc.
       25 + * Copyright 2023 Oxide Computer Company
  25   26   */
  26   27  
  27   28  #include <assert.h>
  28   29  #include <ctype.h>
  29   30  #include <errno.h>
  30   31  #include <fcntl.h>
  31   32  #include <stdio.h>
  32   33  #include <stdlib.h>
  33   34  #include <string.h>
  34   35  #include <strings.h>
↓ open down ↓ 509 lines elided ↑ open up ↑
 544  545  dlmgmt_db_update(dlmgmt_db_op_t op, const char *entryname, dlmgmt_link_t *linkp,
 545  546      uint32_t flags)
 546  547  {
 547  548          dlmgmt_db_req_t *req;
 548  549          int             err;
 549  550  
 550  551          /* It is either a persistent request or an active request, not both. */
 551  552          assert((flags == DLMGMT_PERSIST) || (flags == DLMGMT_ACTIVE));
 552  553  
 553  554          if ((req = dlmgmt_db_req_alloc(op, entryname, linkp->ll_linkid,
 554      -            linkp->ll_zoneid, flags, &err)) == NULL)
      555 +            linkp->ll_zoneid, flags, &err)) == NULL) {
 555  556                  return (err);
      557 +        }
 556  558  
      559 +        /*
      560 +         * If this is a transient link, then use the global zone cache file.
      561 +         * This is in order to allow recovery from a dlmgmtd failure that
      562 +         * leaves a zone in a 'down' state. In that state it is not possible
      563 +         * to read the zone's cache file (since it is always done from a sub
      564 +         * process running in the zone's context). As a result, datalinks would
      565 +         * otherwise remain stuck in the zone.
      566 +         */
      567 +        if (flags == DLMGMT_ACTIVE && linkp->ll_transient)
      568 +                req->ls_zoneid = GLOBAL_ZONEID;
      569 +
 557  570          /* If transient op and onloan, use the global zone cache file. */
 558  571          if (flags == DLMGMT_ACTIVE && linkp->ll_onloan)
 559  572                  req->ls_zoneid = GLOBAL_ZONEID;
 560  573  
 561  574          /*
 562  575           * If the return error is EINPROGRESS, this request is handled
 563  576           * asynchronously; return success.
 564  577           */
 565  578          err = dlmgmt_process_db_req(req);
 566  579          if (err != EINPROGRESS)
↓ open down ↓ 146 lines elided ↑ open up ↑
 713  726  static int
 714  727  parse_linkprops(char *buf, dlmgmt_link_t *linkp)
 715  728  {
 716  729          boolean_t               found_type = B_FALSE;
 717  730          dladm_datatype_t        type = DLADM_TYPE_STR;
 718  731          int                     i, len;
 719  732          char                    *curr;
 720  733          char                    attr_name[MAXLINKATTRLEN];
 721  734          size_t                  attr_buf_len = 0;
 722  735          void                    *attr_buf = NULL;
 723      -        boolean_t               rename;
 724  736  
 725  737          curr = buf;
 726  738          len = strlen(buf);
 727  739          attr_name[0] = '\0';
 728  740          for (i = 0; i < len; i++) {
 729      -                rename = B_FALSE;
 730  741                  char            c = buf[i];
 731  742                  boolean_t       match = (c == '=' ||
 732  743                      (c == ',' && !found_type) || c == ';');
      744 +                boolean_t       rename = B_FALSE;
 733  745  
 734  746                  /*
 735  747                   * Move to the next character if there is no match and
 736  748                   * if we have not reached the last character.
 737  749                   */
 738  750                  if (!match && i != len - 1)
 739  751                          continue;
 740  752  
 741  753                  if (match) {
 742  754                          /*
↓ open down ↓ 41 lines elided ↑ open up ↑
 784  796                                          if (errno == EFAULT)
 785  797                                                  abort();
 786  798                                          /*
 787  799                                           * If we can't find the zone, assign the
 788  800                                           * link to the GZ and mark it for being
 789  801                                           * renamed.
 790  802                                           */
 791  803                                          linkp->ll_zoneid = 0;
 792  804                                          rename = B_TRUE;
 793  805                                  }
      806 +                        } else if (strcmp(attr_name, "transient") == 0) {
      807 +                                if (read_boolean(curr, &attr_buf) == 0)
      808 +                                        goto parse_fail;
      809 +                                linkp->ll_transient = *(boolean_t *)attr_buf;
 794  810                          } else {
 795  811                                  attr_buf_len = translators[type].read_func(curr,
 796  812                                      &attr_buf);
 797  813                                  if (attr_buf_len == 0)
 798  814                                          goto parse_fail;
 799  815  
 800  816                                  if (linkattr_set(&(linkp->ll_head), attr_name,
 801  817                                      attr_buf, attr_buf_len, type) != 0) {
 802  818                                          free(attr_buf);
 803  819                                          goto parse_fail;
↓ open down ↓ 29 lines elided ↑ open up ↑
 833  849                                  goto parse_fail;
 834  850  
 835  851                          (void) snprintf(attr_name, MAXLINKATTRLEN, "%s", curr);
 836  852                  }
 837  853  
 838  854                  /*
 839  855                   * The zone that this link belongs to has died, we are
 840  856                   * reparenting it to the GZ and renaming it to avoid name
 841  857                   * collisions.
 842  858                   */
 843      -                if (rename == B_TRUE) {
      859 +                if (rename) {
 844  860                          (void) snprintf(linkp->ll_link, MAXLINKNAMELEN,
 845  861                              "SUNWorphan%u", (uint16_t)(gethrtime() / 1000));
 846  862                  }
      863 +
 847  864                  curr = buf + i + 1;
 848  865          }
 849  866  
 850  867          /* Correct any erroneous IPTUN datalink class constant in the file */
 851  868          if (linkp->ll_class == 0x60) {
 852  869                  linkp->ll_class = DATALINK_CLASS_IPTUN;
 853  870                  rewrite_needed = B_TRUE;
 854  871          }
 855  872  
 856  873          return (0);
↓ open down ↓ 293 lines elided ↑ open up ↑
1150 1167                          linkattr_destroy(&link_in_file);
1151 1168                          continue;
1152 1169                  }
1153 1170  
1154 1171                  if ((req->ls_flags & DLMGMT_ACTIVE) &&
1155 1172                      link_in_file.ll_linkid == DATALINK_INVALID_LINKID) {
1156 1173                          linkattr_destroy(&link_in_file);
1157 1174                          continue;
1158 1175                  }
1159 1176  
1160      -                link_in_file.ll_zoneid = req->ls_zoneid;
     1177 +                assert(req->ls_zoneid == 0 ||
     1178 +                    link_in_file.ll_zoneid == req->ls_zoneid);
1161 1179                  link_in_db = link_by_name(link_in_file.ll_link,
1162 1180                      link_in_file.ll_zoneid);
1163 1181                  if (link_in_db != NULL) {
1164 1182                          /*
1165 1183                           * If the link in the database already has the flag
1166 1184                           * for this request set, then the entry is a
1167 1185                           * duplicate.  If it's not a duplicate, then simply
1168 1186                           * turn on the appropriate flag on the existing link.
1169 1187                           */
1170 1188                          if (link_in_db->ll_flags & req->ls_flags) {
↓ open down ↓ 78 lines elided ↑ open up ↑
1249 1267  {
1250 1268          char                    tmpbuf[MAXLINELEN];
1251 1269          char                    *ptr = tmpbuf;
1252 1270          char                    *lim = tmpbuf + MAXLINELEN;
1253 1271          dlmgmt_linkattr_t       *cur_p = NULL;
1254 1272          uint64_t                u64;
1255 1273  
1256 1274          ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", linkp->ll_link);
1257 1275          if (!persist) {
1258 1276                  char zname[ZONENAME_MAX];
     1277 +
1259 1278                  /*
1260 1279                   * We store the linkid and the zone name in the active database
1261 1280                   * so that dlmgmtd can recover in the event that it is
1262 1281                   * restarted.
1263 1282                   */
1264 1283                  u64 = linkp->ll_linkid;
1265 1284                  ptr += write_uint64(ptr, BUFLEN(lim, ptr), "linkid", &u64);
1266 1285  
1267 1286                  if (getzonenamebyid(linkp->ll_zoneid, zname,
1268 1287                      sizeof (zname)) != -1) {
1269 1288                          ptr += write_str(ptr, BUFLEN(lim, ptr), "zone", zname);
1270 1289                  }
1271 1290          }
1272 1291          u64 = linkp->ll_class;
1273 1292          ptr += write_uint64(ptr, BUFLEN(lim, ptr), "class", &u64);
1274 1293          u64 = linkp->ll_media;
1275 1294          ptr += write_uint64(ptr, BUFLEN(lim, ptr), "media", &u64);
1276 1295  
     1296 +        if (!persist && linkp->ll_transient) {
     1297 +                boolean_t b = B_TRUE;
     1298 +                ptr += write_boolean(ptr, BUFLEN(lim, ptr), "transient", &b);
     1299 +        }
     1300 +
1277 1301          /*
1278 1302           * The daemon does not keep any active link attribute. Only store the
1279 1303           * attributes if this request is for persistent configuration,
1280 1304           */
1281 1305          if (persist) {
1282 1306                  for (cur_p = linkp->ll_head; cur_p != NULL;
1283 1307                      cur_p = cur_p->lp_next) {
1284 1308                          ptr += translators[cur_p->lp_type].write_func(ptr,
1285 1309                              BUFLEN(lim, ptr), cur_p->lp_name, cur_p->lp_val);
1286 1310                  }
↓ open down ↓ 263 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX