Print this page
OS-3342+co
OS-722
OS-478 -- lint
OS-375-1
OS-328 dlmgmtd/mac_link_flow_add() deadlock
OS-249
@@ -19,10 +19,11 @@
* CDDL HEADER END
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
*/
/*
* Main door handler functions used by dlmgmtd to process the different door
* call requests. Door call requests can come from the user-land applications,
@@ -56,10 +57,14 @@
#include <sys/sysevent/eventdefs.h>
#include <zone.h>
#include <libsysevent.h>
#include <libdlmgmt.h>
#include <librcm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
#include "dlmgmt_impl.h"
typedef void dlmgmt_door_handler_t(void *, void *, size_t *, zoneid_t,
ucred_t *);
@@ -377,10 +382,15 @@
}
if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0)
goto done;
+ if (linkp->ll_tomb == B_TRUE) {
+ err = EINPROGRESS;
+ goto done;
+ }
+
if (((linkp->ll_flags & flags) & DLMGMT_ACTIVE) != 0) {
if ((err = dlmgmt_delete_db_entry(linkp, DLMGMT_ACTIVE)) != 0)
goto done;
dflags |= DLMGMT_ACTIVE;
}
@@ -437,10 +447,14 @@
dlmgmt_door_getlinkid_t *getlinkid = argp;
dlmgmt_getlinkid_retval_t *retvalp = retp;
dlmgmt_link_t *linkp;
int err = 0;
+ /* Enable the global zone to lookup links it has given away. */
+ if (zoneid == GLOBAL_ZONEID && getlinkid->ld_zoneid != -1)
+ zoneid = getlinkid->ld_zoneid;
+
/*
* Hold the reader lock to access the link
*/
dlmgmt_table_lock(B_FALSE);
@@ -646,10 +660,16 @@
}
if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0)
goto done;
+ if (linkp->ll_tomb == B_TRUE) {
+ err = EBUSY;
+ goto done;
+ }
+
+
if (link_by_name(remapid->ld_link, linkp->ll_zoneid) != NULL) {
err = EEXIST;
goto done;
}
@@ -707,10 +727,15 @@
}
if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0)
goto done;
+ if (linkp->ll_tomb == B_TRUE) {
+ err = EBUSY;
+ goto done;
+ }
+
if (linkp->ll_flags & DLMGMT_ACTIVE) {
err = EINVAL;
goto done;
}
@@ -1214,10 +1239,15 @@
}
if ((err = dlmgmt_checkprivs(linkp->ll_class, cred)) != 0)
goto done;
+ if (linkp->ll_tomb == B_TRUE) {
+ err = EBUSY;
+ goto done;
+ }
+
/* We can only assign an active link to a zone. */
if (!(linkp->ll_flags & DLMGMT_ACTIVE)) {
err = EINVAL;
goto done;
}
@@ -1243,11 +1273,23 @@
err = errno;
dlmgmt_log(LOG_WARNING, "unable to remove link %d from "
"zone %d: %s", linkid, oldzoneid, strerror(err));
goto done;
}
- avl_remove(&dlmgmt_loan_avl, linkp);
+
+ if (newzoneid == GLOBAL_ZONEID && linkp->ll_onloan) {
+ /*
+ * We can only reassign a loaned VNIC back to the
+ * global zone when the zone is shutting down, since
+ * otherwise the VNIC is in use by the zone and will be
+ * busy. Leave the VNIC assigned to the zone so we can
+ * still see it and delete it when dlmgmt_zonehalt()
+ * runs.
+ */
+ goto done;
+ }
+
linkp->ll_onloan = B_FALSE;
}
if (newzoneid != GLOBAL_ZONEID) {
if (zone_add_datalink(newzoneid, linkid) != 0) {
err = errno;
@@ -1254,11 +1296,10 @@
dlmgmt_log(LOG_WARNING, "unable to add link %d to zone "
"%d: %s", linkid, newzoneid, strerror(err));
(void) zone_add_datalink(oldzoneid, linkid);
goto done;
}
- avl_add(&dlmgmt_loan_avl, linkp);
linkp->ll_onloan = B_TRUE;
}
avl_remove(&dlmgmt_name_avl, linkp);
linkp->ll_zoneid = newzoneid;
@@ -1307,20 +1348,41 @@
ucred_t *cred)
{
int err = 0;
dlmgmt_door_zonehalt_t *zonehalt = argp;
dlmgmt_zonehalt_retval_t *retvalp = retp;
+ static char my_pid[10];
+ if (my_pid[0] == NULL)
+ (void) snprintf(my_pid, sizeof (my_pid), "%d\n", getpid());
+
if ((err = dlmgmt_checkprivs(0, cred)) == 0) {
if (zoneid != GLOBAL_ZONEID) {
err = EACCES;
} else if (zonehalt->ld_zoneid == GLOBAL_ZONEID) {
err = EINVAL;
} else {
+ /*
+ * dls and mac don't honor the locking rules defined in
+ * mac. In order to try and make that case less likely
+ * to happen, we try to serialize some of the zone
+ * activity here between dlmgmtd and the brands on
+ * /etc/dladm/zone.lck
+ */
+ int fd;
+
+ while ((fd = open(ZONE_LOCK, O_WRONLY |
+ O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) < 0)
+ (void) sleep(1);
+ (void) write(fd, my_pid, sizeof (my_pid));
+ (void) close(fd);
+
dlmgmt_table_lock(B_TRUE);
dlmgmt_db_fini(zonehalt->ld_zoneid);
dlmgmt_table_unlock();
+
+ (void) unlink(ZONE_LOCK);
}
}
retvalp->lr_err = err;
}