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