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
        
*** 20,29 ****
--- 20,30 ----
   */
  
  /*
   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   * Copyright 2016 Joyent, Inc.
+  * Copyright 2023 Oxide Computer Company
   */
  
  #include <assert.h>
  #include <ctype.h>
  #include <errno.h>
*** 549,561 ****
  
          /* It is either a persistent request or an active request, not both. */
          assert((flags == DLMGMT_PERSIST) || (flags == DLMGMT_ACTIVE));
  
          if ((req = dlmgmt_db_req_alloc(op, entryname, linkp->ll_linkid,
!             linkp->ll_zoneid, flags, &err)) == NULL)
                  return (err);
  
          /* If transient op and onloan, use the global zone cache file. */
          if (flags == DLMGMT_ACTIVE && linkp->ll_onloan)
                  req->ls_zoneid = GLOBAL_ZONEID;
  
          /*
--- 550,574 ----
  
          /* It is either a persistent request or an active request, not both. */
          assert((flags == DLMGMT_PERSIST) || (flags == DLMGMT_ACTIVE));
  
          if ((req = dlmgmt_db_req_alloc(op, entryname, linkp->ll_linkid,
!             linkp->ll_zoneid, flags, &err)) == NULL) {
                  return (err);
+         }
  
+         /*
+          * If this is a transient link, then use the global zone cache file.
+          * This is in order to allow recovery from a dlmgmtd failure that
+          * leaves a zone in a 'down' state. In that state it is not possible
+          * to read the zone's cache file (since it is always done from a sub
+          * process running in the zone's context). As a result, datalinks would
+          * otherwise remain stuck in the zone.
+          */
+         if (flags == DLMGMT_ACTIVE && linkp->ll_transient)
+                 req->ls_zoneid = GLOBAL_ZONEID;
+ 
          /* If transient op and onloan, use the global zone cache file. */
          if (flags == DLMGMT_ACTIVE && linkp->ll_onloan)
                  req->ls_zoneid = GLOBAL_ZONEID;
  
          /*
*** 718,737 ****
          int                     i, len;
          char                    *curr;
          char                    attr_name[MAXLINKATTRLEN];
          size_t                  attr_buf_len = 0;
          void                    *attr_buf = NULL;
-         boolean_t               rename;
  
          curr = buf;
          len = strlen(buf);
          attr_name[0] = '\0';
          for (i = 0; i < len; i++) {
-                 rename = B_FALSE;
                  char            c = buf[i];
                  boolean_t       match = (c == '=' ||
                      (c == ',' && !found_type) || c == ';');
  
                  /*
                   * Move to the next character if there is no match and
                   * if we have not reached the last character.
                   */
--- 731,749 ----
          int                     i, len;
          char                    *curr;
          char                    attr_name[MAXLINKATTRLEN];
          size_t                  attr_buf_len = 0;
          void                    *attr_buf = NULL;
  
          curr = buf;
          len = strlen(buf);
          attr_name[0] = '\0';
          for (i = 0; i < len; i++) {
                  char            c = buf[i];
                  boolean_t       match = (c == '=' ||
                      (c == ',' && !found_type) || c == ';');
+                 boolean_t       rename = B_FALSE;
  
                  /*
                   * Move to the next character if there is no match and
                   * if we have not reached the last character.
                   */
*** 789,798 ****
--- 801,814 ----
                                           * renamed.
                                           */
                                          linkp->ll_zoneid = 0;
                                          rename = B_TRUE;
                                  }
+                         } else if (strcmp(attr_name, "transient") == 0) {
+                                 if (read_boolean(curr, &attr_buf) == 0)
+                                         goto parse_fail;
+                                 linkp->ll_transient = *(boolean_t *)attr_buf;
                          } else {
                                  attr_buf_len = translators[type].read_func(curr,
                                      &attr_buf);
                                  if (attr_buf_len == 0)
                                          goto parse_fail;
*** 838,851 ****
                  /*
                   * The zone that this link belongs to has died, we are
                   * reparenting it to the GZ and renaming it to avoid name
                   * collisions.
                   */
!                 if (rename == B_TRUE) {
                          (void) snprintf(linkp->ll_link, MAXLINKNAMELEN,
                              "SUNWorphan%u", (uint16_t)(gethrtime() / 1000));
                  }
                  curr = buf + i + 1;
          }
  
          /* Correct any erroneous IPTUN datalink class constant in the file */
          if (linkp->ll_class == 0x60) {
--- 854,868 ----
                  /*
                   * The zone that this link belongs to has died, we are
                   * reparenting it to the GZ and renaming it to avoid name
                   * collisions.
                   */
!                 if (rename) {
                          (void) snprintf(linkp->ll_link, MAXLINKNAMELEN,
                              "SUNWorphan%u", (uint16_t)(gethrtime() / 1000));
                  }
+ 
                  curr = buf + i + 1;
          }
  
          /* Correct any erroneous IPTUN datalink class constant in the file */
          if (linkp->ll_class == 0x60) {
*** 1155,1165 ****
                      link_in_file.ll_linkid == DATALINK_INVALID_LINKID) {
                          linkattr_destroy(&link_in_file);
                          continue;
                  }
  
!                 link_in_file.ll_zoneid = req->ls_zoneid;
                  link_in_db = link_by_name(link_in_file.ll_link,
                      link_in_file.ll_zoneid);
                  if (link_in_db != NULL) {
                          /*
                           * If the link in the database already has the flag
--- 1172,1183 ----
                      link_in_file.ll_linkid == DATALINK_INVALID_LINKID) {
                          linkattr_destroy(&link_in_file);
                          continue;
                  }
  
!                 assert(req->ls_zoneid == 0 ||
!                     link_in_file.ll_zoneid == req->ls_zoneid);
                  link_in_db = link_by_name(link_in_file.ll_link,
                      link_in_file.ll_zoneid);
                  if (link_in_db != NULL) {
                          /*
                           * If the link in the database already has the flag
*** 1254,1263 ****
--- 1272,1282 ----
          uint64_t                u64;
  
          ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", linkp->ll_link);
          if (!persist) {
                  char zname[ZONENAME_MAX];
+ 
                  /*
                   * We store the linkid and the zone name in the active database
                   * so that dlmgmtd can recover in the event that it is
                   * restarted.
                   */
*** 1272,1281 ****
--- 1291,1305 ----
          u64 = linkp->ll_class;
          ptr += write_uint64(ptr, BUFLEN(lim, ptr), "class", &u64);
          u64 = linkp->ll_media;
          ptr += write_uint64(ptr, BUFLEN(lim, ptr), "media", &u64);
  
+         if (!persist && linkp->ll_transient) {
+                 boolean_t b = B_TRUE;
+                 ptr += write_boolean(ptr, BUFLEN(lim, ptr), "transient", &b);
+         }
+ 
          /*
           * The daemon does not keep any active link attribute. Only store the
           * attributes if this request is for persistent configuration,
           */
          if (persist) {