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) {