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,10 +20,11 @@
  */
 
 /*
  * 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,13 +550,25 @@
 
         /* 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)
+            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,20 +731,19 @@
         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 == ';');
+                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,10 +801,14 @@
                                          * 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,14 +854,15 @@
                 /*
                  * 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) {
+                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,11 +1172,12 @@
                     link_in_file.ll_linkid == DATALINK_INVALID_LINKID) {
                         linkattr_destroy(&link_in_file);
                         continue;
                 }
 
-                link_in_file.ll_zoneid = req->ls_zoneid;
+                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,10 +1272,11 @@
         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,10 +1291,15 @@
         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) {