summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2012-11-11 17:51:16 +0000
committerRobert Mustacchi <rm@joyent.com>2012-11-12 22:40:38 +0000
commit9406aa886183e374df80925823ad1041240587cd (patch)
tree399af3d9e4ad0956d1da3411fceeb17fde203a12 /usr/src
parentf127c3d314177b04bec20fd38a3a8742487ce02d (diff)
downloadillumos-joyent-9406aa886183e374df80925823ad1041240587cd.tar.gz
OS-577 race in netstack_unregister and zone creation
OS-1690 want zid2zone and zdid2zone OS-1691 want a dcmd for going from netstack id to nestack_t Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Bryan Cantrill <bryan@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/genunix.c7
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/netstack.c30
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/netstack.h3
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/zone.c51
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/zone.h4
-rw-r--r--usr/src/uts/common/os/netstack.c33
6 files changed, 119 insertions, 9 deletions
diff --git a/usr/src/cmd/mdb/common/modules/genunix/genunix.c b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
index d68260a8f8..48578a52f4 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/genunix.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
@@ -4059,6 +4059,9 @@ static const mdb_dcmd_t dcmds[] = {
/* from netstack.c */
{ "netstack", "", "show stack instances", netstack },
+ { "netstackid2netstack", ":",
+ "translate a netstack id to its netstack_t",
+ netstackid2netstack },
/* from nvpair.c */
{ NVPAIR_DCMD_NAME, NVPAIR_DCMD_USAGE, NVPAIR_DCMD_DESCR,
@@ -4149,6 +4152,10 @@ static const mdb_dcmd_t dcmds[] = {
pfiles_help },
/* from zone.c */
+ { "zid2zone", ":", "find the zone_t with the given zone id",
+ zid2zone },
+ { "zdid2zone", ":", "find the zone_t with the given zone debug id",
+ zdid2zone },
{ "zone", "?[-r [-v]]", "display kernel zone(s)", zoneprt },
{ "zsd", ":[-v] [zsd_key]", "display zone-specific-data entries for "
"selected zones", zsd },
diff --git a/usr/src/cmd/mdb/common/modules/genunix/netstack.c b/usr/src/cmd/mdb/common/modules/genunix/netstack.c
index 588bd6dbf3..d46bd85d1f 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/netstack.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/netstack.c
@@ -21,10 +21,9 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <mdb/mdb_modapi.h>
#include <mdb/mdb_ks.h>
#include <mdb/mdb_ctf.h>
@@ -121,3 +120,30 @@ netstack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_OK);
}
+
+static int
+netstackid_lookup_cb(uintptr_t addr, const netstack_t *ns, void *arg)
+{
+ netstackid_t nid = *(uintptr_t *)arg;
+ if (ns->netstack_stackid == nid)
+ mdb_printf("%p\n", addr);
+
+ return (WALK_NEXT);
+}
+
+/*ARGSUSED*/
+int
+netstackid2netstack(uintptr_t addr, uint_t flags, int argc,
+ const mdb_arg_t *argv)
+{
+ if (!(flags & DCMD_ADDRSPEC) || argc != 0)
+ return (DCMD_USAGE);
+
+ if (mdb_walk("netstack", (mdb_walk_cb_t)netstackid_lookup_cb, &addr) ==
+ -1) {
+ mdb_warn("failed to walk zone");
+ return (DCMD_ERR);
+ }
+
+ return (DCMD_OK);
+}
diff --git a/usr/src/cmd/mdb/common/modules/genunix/netstack.h b/usr/src/cmd/mdb/common/modules/genunix/netstack.h
index 392565caca..f5773c36c1 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/netstack.h
+++ b/usr/src/cmd/mdb/common/modules/genunix/netstack.h
@@ -26,8 +26,6 @@
#ifndef _NETSTACK_H
#define _NETSTACK_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <mdb/mdb_modapi.h>
#ifdef __cplusplus
@@ -38,6 +36,7 @@ int netstack_walk_init(mdb_walk_state_t *);
int netstack_walk_step(mdb_walk_state_t *);
int netstack(uintptr_t, uint_t, int, const mdb_arg_t *);
+int netstackid2netstack(uintptr_t, uint_t, int, const mdb_arg_t *);
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/mdb/common/modules/genunix/zone.c b/usr/src/cmd/mdb/common/modules/genunix/zone.c
index 96f6b598ec..fc243061cb 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/zone.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/zone.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#include <mdb/mdb_param.h>
@@ -54,6 +55,56 @@ char *zone_status_names[] = {
"dead" /* ZONE_IS_DEAD */
};
+static int
+zid_lookup_cb(uintptr_t addr, const zone_t *zone, void *arg)
+{
+ zoneid_t zid = *(uintptr_t *)arg;
+ if (zone->zone_id == zid)
+ mdb_printf("%p\n", addr);
+
+ return (WALK_NEXT);
+}
+
+/*ARGSUSED*/
+int
+zid2zone(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ if (!(flags & DCMD_ADDRSPEC) || argc != 0)
+ return (DCMD_USAGE);
+
+ if (mdb_walk("zone", (mdb_walk_cb_t)zid_lookup_cb, &addr) == -1) {
+ mdb_warn("failed to walk zone");
+ return (DCMD_ERR);
+ }
+
+ return (DCMD_OK);
+}
+
+static int
+zdid_lookup_cb(uintptr_t addr, const zone_t *zone, void *arg)
+{
+ zoneid_t zdid = *(uintptr_t *)arg;
+ if (zone->zone_did == zdid)
+ mdb_printf("%p\n", addr);
+
+ return (WALK_NEXT);
+}
+
+/*ARGSUSED*/
+int
+zdid2zone(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ if (!(flags & DCMD_ADDRSPEC) || argc != 0)
+ return (DCMD_USAGE);
+
+ if (mdb_walk("zone", (mdb_walk_cb_t)zdid_lookup_cb, &addr) == -1) {
+ mdb_warn("failed to walk zone");
+ return (DCMD_ERR);
+ }
+
+ return (DCMD_OK);
+}
+
int
zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
diff --git a/usr/src/cmd/mdb/common/modules/genunix/zone.h b/usr/src/cmd/mdb/common/modules/genunix/zone.h
index e0e5038527..94a383e41c 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/zone.h
+++ b/usr/src/cmd/mdb/common/modules/genunix/zone.h
@@ -27,14 +27,14 @@
#ifndef _ZONE_H
#define _ZONE_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <mdb/mdb_modapi.h>
#ifdef __cplusplus
extern "C" {
#endif
+extern int zid2zone(uintptr_t, uint_t, int argc, const mdb_arg_t *);
+extern int zdid2zone(uintptr_t, uint_t, int argc, const mdb_arg_t *);
extern int zoneprt(uintptr_t, uint_t, int argc, const mdb_arg_t *);
extern int zone_walk_init(mdb_walk_state_t *);
diff --git a/usr/src/uts/common/os/netstack.c b/usr/src/uts/common/os/netstack.c
index b8467fbe13..93fd1a387d 100644
--- a/usr/src/uts/common/os/netstack.c
+++ b/usr/src/uts/common/os/netstack.c
@@ -22,6 +22,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#include <sys/param.h>
@@ -205,6 +206,7 @@ void
netstack_unregister(int moduleid)
{
netstack_t *ns;
+ boolean_t created = B_FALSE;
ASSERT(moduleid >= 0 && moduleid < NS_MAX);
@@ -223,7 +225,33 @@ netstack_unregister(int moduleid)
nm_state_t *nms = &ns->netstack_m_state[moduleid];
mutex_enter(&ns->netstack_lock);
- if (ns_reg[moduleid].nr_shutdown != NULL &&
+
+ /*
+ * We need to be careful here. We could actually have a netstack
+ * being created as we speak waiting for us to let go of this
+ * lock to proceed. It may have set NSS_CREATE_NEEDED, but not
+ * have gotten to the point of completing it yet. If
+ * NSS_CREATE_NEEDED, we can safely just remove it here and
+ * never create the module. However, if NSS_CREATE_INPROGRESS is
+ * set, we need to still flag this module for shutdown and
+ * deletion, just as though it had reached NSS_CREATE_COMPLETED.
+ *
+ * It is safe to do that because of two different guarantees
+ * that exist in the system. The first is that before we do a
+ * create, shutdown, or destroy, we ensure that nothing else is
+ * in progress in the system for this netstack and wait for it
+ * to complete. Secondly, because the zone is being created, we
+ * know that the following call to apply_all_netstack will block
+ * on the zone finishing its initialization.
+ */
+ if (nms->nms_flags & NSS_CREATE_NEEDED)
+ nms->nms_flags &= ~NSS_CREATE_NEEDED;
+
+ if (nms->nms_flags & NSS_CREATE_INPROGRESS ||
+ nms->nms_flags & NSS_CREATE_COMPLETED)
+ created = B_TRUE;
+
+ if (ns_reg[moduleid].nr_shutdown != NULL && created &&
(nms->nms_flags & NSS_CREATE_COMPLETED) &&
(nms->nms_flags & NSS_SHUTDOWN_ALL) == 0) {
nms->nms_flags |= NSS_SHUTDOWN_NEEDED;
@@ -231,8 +259,7 @@ netstack_unregister(int moduleid)
netstack_t *, ns, int, moduleid);
}
if ((ns_reg[moduleid].nr_flags & NRF_REGISTERED) &&
- ns_reg[moduleid].nr_destroy != NULL &&
- (nms->nms_flags & NSS_CREATE_COMPLETED) &&
+ ns_reg[moduleid].nr_destroy != NULL && created &&
(nms->nms_flags & NSS_DESTROY_ALL) == 0) {
nms->nms_flags |= NSS_DESTROY_NEEDED;
DTRACE_PROBE2(netstack__destroy__needed,