diff options
author | Robert Mustacchi <rm@joyent.com> | 2012-11-11 17:51:16 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2012-11-12 22:40:38 +0000 |
commit | 9406aa886183e374df80925823ad1041240587cd (patch) | |
tree | 399af3d9e4ad0956d1da3411fceeb17fde203a12 /usr/src | |
parent | f127c3d314177b04bec20fd38a3a8742487ce02d (diff) | |
download | illumos-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.c | 7 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/netstack.c | 30 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/netstack.h | 3 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/zone.c | 51 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/zone.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/os/netstack.c | 33 |
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, |