usr/src/uts/common/os/zone.c
author dp
Thu, 22 Jun 2006 14:42:46 -0700
changeset 2267 c5d9a656170f
parent 2110 31cba59b38be
child 2677 212d61b14a8b
permissions -rw-r--r--
PSARC/2006/269 Zone Boot Arguments II 4943812 init improperly respawning stuff during reboot 4994285 RFE: zones should support boot arguments 6315349 halt.c contains an uninitialized variable 6395642 missing global zone checks for menu updates in uadmin(2) 6415633 krtld calls printf(), goes boom 6421372 libc's lintlib doesn't include <sys/uadmin.h> 6433526 zoneadm should use statvfs64
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
     5
 * Common Development and Distribution License (the "License").
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
     6
 * You may not use this file except in compliance with the License.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 */
390
ff89f8283e6c 6272865 race condition between SIGKILL and /proc PCAGENT
raf
parents: 0
diff changeset
    21
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
1409
c25d6f2622c9 6366674 zones service common name could be more descriptive
dp
parents: 1166
diff changeset
    23
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
 * Zones
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
 *   A zone is a named collection of processes, namespace constraints,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
 *   and other system resources which comprise a secure and manageable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
 *   application containment facility.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
 *   Zones (represented by the reference counted zone_t) are tracked in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
 *   the kernel in the zonehash.  Elsewhere in the kernel, Zone IDs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
 *   (zoneid_t) are used to track zone association.  Zone IDs are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
 *   dynamically generated when the zone is created; if a persistent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
 *   identifier is needed (core files, accounting logs, audit trail,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
 *   etc.), the zone name should be used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 *   Global Zone:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
 *   The global zone (zoneid 0) is automatically associated with all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
 *   system resources that have not been bound to a user-created zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
 *   This means that even systems where zones are not in active use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
 *   have a global zone, and all processes, mounts, etc. are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
 *   associated with that zone.  The global zone is generally
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
 *   unconstrained in terms of privileges and access, though the usual
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
 *   credential and privilege based restrictions apply.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
 *   Zone States:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
 *   The states in which a zone may be in and the transitions are as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
 *   follows:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
 *   ZONE_IS_UNINITIALIZED: primordial state for a zone. The partially
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
 *   initialized zone is added to the list of active zones on the system but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
 *   isn't accessible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
 *   ZONE_IS_READY: zsched (the kernel dummy process for a zone) is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
 *   ready.  The zone is made visible after the ZSD constructor callbacks are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
 *   executed.  A zone remains in this state until it transitions into
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
 *   the ZONE_IS_BOOTING state as a result of a call to zone_boot().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
 *   ZONE_IS_BOOTING: in this shortlived-state, zsched attempts to start
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
 *   init.  Should that fail, the zone proceeds to the ZONE_IS_SHUTTING_DOWN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
 *   state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
 *   ZONE_IS_RUNNING: The zone is open for business: zsched has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
 *   successfully started init.   A zone remains in this state until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
 *   zone_shutdown() is called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
 *   ZONE_IS_SHUTTING_DOWN: zone_shutdown() has been called, the system is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
 *   killing all processes running in the zone. The zone remains
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
 *   in this state until there are no more user processes running in the zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
 *   zone_create(), zone_enter(), and zone_destroy() on this zone will fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
 *   Since zone_shutdown() is restartable, it may be called successfully
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
 *   multiple times for the same zone_t.  Setting of the zone's state to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
 *   ZONE_IS_SHUTTING_DOWN is synchronized with mounts, so VOP_MOUNT() may check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
 *   the zone's status without worrying about it being a moving target.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
 *   ZONE_IS_EMPTY: zone_shutdown() has been called, and there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
 *   are no more user processes in the zone.  The zone remains in this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
 *   state until there are no more kernel threads associated with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
 *   zone.  zone_create(), zone_enter(), and zone_destroy() on this zone will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
 *   fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
 *   ZONE_IS_DOWN: All kernel threads doing work on behalf of the zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
 *   have exited.  zone_shutdown() returns.  Henceforth it is not possible to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
 *   join the zone or create kernel threads therein.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
 *   ZONE_IS_DYING: zone_destroy() has been called on the zone; zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
 *   remains in this state until zsched exits.  Calls to zone_find_by_*()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
 *   return NULL from now on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
 *   ZONE_IS_DEAD: zsched has exited (zone_ntasks == 0).  There are no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
 *   processes or threads doing work on behalf of the zone.  The zone is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
 *   removed from the list of active zones.  zone_destroy() returns, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
 *   the zone can be recreated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
 *   ZONE_IS_FREE (internal state): zone_ref goes to 0, ZSD destructor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
 *   callbacks are executed, and all memory associated with the zone is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
 *   freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
 *   Threads can wait for the zone to enter a requested state by using
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
 *   zone_status_wait() or zone_status_timedwait() with the desired
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
 *   state passed in as an argument.  Zone state transitions are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
 *   uni-directional; it is not possible to move back to an earlier state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
 *   Zone-Specific Data:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
 *   Subsystems needing to maintain zone-specific data can store that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
 *   data using the ZSD mechanism.  This provides a zone-specific data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
 *   store, similar to thread-specific data (see pthread_getspecific(3C)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
 *   or the TSD code in uts/common/disp/thread.c.  Also, ZSD can be used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
 *   to register callbacks to be invoked when a zone is created, shut
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
 *   down, or destroyed.  This can be used to initialize zone-specific
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
 *   data for new zones and to clean up when zones go away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
 *   Data Structures:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
 *   The per-zone structure (zone_t) is reference counted, and freed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
 *   when all references are released.  zone_hold and zone_rele can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
 *   used to adjust the reference count.  In addition, reference counts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
 *   associated with the cred_t structure are tracked separately using
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
 *   zone_cred_hold and zone_cred_rele.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
 *   Pointers to active zone_t's are stored in two hash tables; one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
 *   for searching by id, the other for searching by name.  Lookups
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
 *   can be performed on either basis, using zone_find_by_id and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
 *   zone_find_by_name.  Both return zone_t pointers with the zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
 *   held, so zone_rele should be called when the pointer is no longer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
 *   needed.  Zones can also be searched by path; zone_find_by_path
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
 *   returns the zone with which a path name is associated (global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
 *   zone if the path is not within some other zone's file system
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
 *   hierarchy).  This currently requires iterating through each zone,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
 *   so it is slower than an id or name search via a hash table.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
 *   Locking:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
 *   zonehash_lock: This is a top-level global lock used to protect the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
 *       zone hash tables and lists.  Zones cannot be created or destroyed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
 *       while this lock is held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
 *   zone_status_lock: This is a global lock protecting zone state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
 *       Zones cannot change state while this lock is held.  It also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
 *       protects the list of kernel threads associated with a zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
 *   zone_lock: This is a per-zone lock used to protect several fields of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
 *       the zone_t (see <sys/zone.h> for details).  In addition, holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
 *       this lock means that the zone cannot go away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
 *   zsd_key_lock: This is a global lock protecting the key state for ZSD.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
 *   zone_deathrow_lock: This is a global lock protecting the "deathrow"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
 *       list (a list of zones in the ZONE_IS_DEAD state).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
 *   Ordering requirements:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
 *       pool_lock --> cpu_lock --> zonehash_lock --> zone_status_lock -->
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
 *       	zone_lock --> zsd_key_lock --> pidlock --> p_lock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
 *   Blocking memory allocations are permitted while holding any of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
 *   zone locks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
 *   System Call Interface:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
 *   The zone subsystem can be managed and queried from user level with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
 *   the following system calls (all subcodes of the primary "zone"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
 *   system call):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
 *   - zone_create: creates a zone with selected attributes (name,
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   175
 *     root path, privileges, resource controls, ZFS datasets)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
 *   - zone_enter: allows the current process to enter a zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
 *   - zone_getattr: reports attributes of a zone
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
   178
 *   - zone_setattr: set attributes of a zone
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
   179
 *   - zone_boot: set 'init' running for the zone
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
 *   - zone_list: lists all zones active in the system
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
 *   - zone_lookup: looks up zone id based on name
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
 *   - zone_shutdown: initiates shutdown process (see states above)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
 *   - zone_destroy: completes shutdown process (see states above)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
#include <sys/priv_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
#include <sys/cred.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
#include <c2/audit.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
#include <sys/debug.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
#include <sys/file.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
#include <sys/kmem.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
#include <sys/mutex.h>
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
   194
#include <sys/note.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
#include <sys/pathname.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
#include <sys/proc.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
#include <sys/project.h>
1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   198
#include <sys/sysevent.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
#include <sys/task.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
#include <sys/systm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
#include <sys/utsname.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
#include <sys/vnode.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
#include <sys/vfs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
#include <sys/systeminfo.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
#include <sys/policy.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
#include <sys/cred_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
#include <sys/contract_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
#include <sys/contract/process_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
#include <sys/class.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
#include <sys/pool.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
#include <sys/pool_pset.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
#include <sys/pset.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
#include <sys/sysmacros.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
#include <sys/callb.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
#include <sys/vmparam.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
#include <sys/corectl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
#include <sys/door.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
#include <sys/cpuvar.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
#include <sys/uadmin.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
#include <sys/session.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
#include <sys/modhash.h>
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
   226
#include <sys/sunddi.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
#include <sys/nvpair.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
#include <sys/rctl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
#include <sys/fss.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
#include <sys/zone.h>
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
   231
#include <sys/tsol/label.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
 * cv used to signal that all references to the zone have been released.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
 * needs to be global since there may be multiple waiters, and the first to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
 * wake up will free the zone_t, hence we cannot use zone->zone_cv.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
static kcondvar_t zone_destroy_cv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
 * Lock used to serialize access to zone_cv.  This could have been per-zone,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
 * but then we'd need another lock for zone_destroy_cv, and why bother?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
static kmutex_t zone_status_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
 * ZSD-related global variables.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
static kmutex_t zsd_key_lock;	/* protects the following two */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
 * The next caller of zone_key_create() will be assigned a key of ++zsd_keyval.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
static zone_key_t zsd_keyval = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
 * Global list of registered keys.  We use this when a new zone is created.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
static list_t zsd_registered_keys;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
int zone_hash_size = 256;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
   259
static mod_hash_t *zonehashbyname, *zonehashbyid, *zonehashbylabel;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
static kmutex_t zonehash_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
static uint_t zonecount;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
static id_space_t *zoneid_space;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
 * The global zone (aka zone0) is the all-seeing, all-knowing zone in which the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
 * kernel proper runs, and which manages all other zones.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
 * Although not declared as static, the variable "zone0" should not be used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
 * except for by code that needs to reference the global zone early on in boot,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
 * before it is fully initialized.  All other consumers should use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
 * 'global_zone'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
zone_t zone0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
zone_t *global_zone = NULL;	/* Set when the global zone is initialized */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
 * List of active zones, protected by zonehash_lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
static list_t zone_active;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
 * List of destroyed zones that still have outstanding cred references.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
 * Used for debugging.  Uses a separate lock to avoid lock ordering
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
 * problems in zone_free.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
static list_t zone_deathrow;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
static kmutex_t zone_deathrow_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
/* number of zones is limited by virtual interface limit in IP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
uint_t maxzones = 8192;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   292
/* Event channel to sent zone state change notifications */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   293
evchan_t *zone_event_chan;
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   294
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   295
/*
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   296
 * This table holds the mapping from kernel zone states to
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   297
 * states visible in the state notification API.
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   298
 * The idea is that we only expose "obvious" states and
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   299
 * do not expose states which are just implementation details.
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   300
 */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   301
const char  *zone_status_table[] = {
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   302
	ZONE_EVENT_UNINITIALIZED,	/* uninitialized */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   303
	ZONE_EVENT_READY,		/* ready */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   304
	ZONE_EVENT_READY,		/* booting */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   305
	ZONE_EVENT_RUNNING,		/* running */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   306
	ZONE_EVENT_SHUTTING_DOWN,	/* shutting_down */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   307
	ZONE_EVENT_SHUTTING_DOWN,	/* empty */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   308
	ZONE_EVENT_SHUTTING_DOWN,	/* down */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   309
	ZONE_EVENT_SHUTTING_DOWN,	/* dying */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   310
	ZONE_EVENT_UNINITIALIZED,	/* dead */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   311
};
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
   312
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
 * This isn't static so lint doesn't complain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
rctl_hndl_t rc_zone_cpu_shares;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
rctl_hndl_t rc_zone_nlwps;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
 * Synchronization primitives used to synchronize between mounts and zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
 * creation/destruction.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
static int mounts_in_progress;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
static kcondvar_t mount_cv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
static kmutex_t mount_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
   326
const char * const zone_default_initname = "/sbin/init";
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
   327
static char * const zone_prefix = "/zone/";
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
static int zone_shutdown(zoneid_t zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
/*
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   332
 * Bump this number when you alter the zone syscall interfaces; this is
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   333
 * because we need to have support for previous API versions in libc
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   334
 * to support patching; libc calls into the kernel to determine this number.
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   335
 *
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   336
 * Version 1 of the API is the version originally shipped with Solaris 10
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   337
 * Version 2 alters the zone_create system call in order to support more
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   338
 *     arguments by moving the args into a structure; and to do better
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   339
 *     error reporting when zone_create() fails.
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   340
 * Version 3 alters the zone_create system call in order to support the
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   341
 *     import of ZFS datasets to zones.
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
   342
 * Version 4 alters the zone_create system call in order to support
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
   343
 *     Trusted Extensions.
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
   344
 * Version 5 alters the zone_boot system call, and converts its old
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
   345
 *     bootargs parameter to be set by the zone_setattr API instead.
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   346
 */
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
   347
static const int ZONE_SYSCALL_API_VERSION = 5;
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   348
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
   349
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
 * Certain filesystems (such as NFS and autofs) need to know which zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
 * the mount is being placed in.  Because of this, we need to be able to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
 * ensure that a zone isn't in the process of being created such that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
 * nfs_mount() thinks it is in the global zone, while by the time it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
 * gets added the list of mounted zones, it ends up on zoneA's mount
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
 * list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
 * The following functions: block_mounts()/resume_mounts() and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
 * mount_in_progress()/mount_completed() are used by zones and the VFS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
 * layer (respectively) to synchronize zone creation and new mounts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
 * The semantics are like a reader-reader lock such that there may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
 * either be multiple mounts (or zone creations, if that weren't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
 * serialized by zonehash_lock) in progress at the same time, but not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
 * both.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
 * We use cv's so the user can ctrl-C out of the operation if it's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
 * taking too long.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
 * The semantics are such that there is unfair bias towards the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
 * "current" operation.  This means that zone creations may starve if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
 * there is a rapid succession of new mounts coming in to the system, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
 * there is a remote possibility that zones will be created at such a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
 * rate that new mounts will not be able to proceed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
 * Prevent new mounts from progressing to the point of calling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
 * VFS_MOUNT().  If there are already mounts in this "region", wait for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
 * them to complete.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
block_mounts(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
	int retval = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
	 * Since it may block for a long time, block_mounts() shouldn't be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
	 * called with zonehash_lock held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
	ASSERT(MUTEX_NOT_HELD(&zonehash_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
	mutex_enter(&mount_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
	while (mounts_in_progress > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
		if (cv_wait_sig(&mount_cv, &mount_lock) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
			goto signaled;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
	 * A negative value of mounts_in_progress indicates that mounts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
	 * have been blocked by (-mounts_in_progress) different callers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
	mounts_in_progress--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
	retval = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
signaled:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
	mutex_exit(&mount_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
	return (retval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
 * The VFS layer may progress with new mounts as far as we're concerned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
 * Allow them to progress if we were the last obstacle.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
resume_mounts(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
	mutex_enter(&mount_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
	if (++mounts_in_progress == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
		cv_broadcast(&mount_cv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
	mutex_exit(&mount_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
 * The VFS layer is busy with a mount; zones should wait until all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
 * mounts are completed to progress.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
mount_in_progress(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
	mutex_enter(&mount_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
	while (mounts_in_progress < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
		cv_wait(&mount_cv, &mount_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
	mounts_in_progress++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
	mutex_exit(&mount_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
 * VFS is done with one mount; wake up any waiting block_mounts()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
 * callers if this is the last mount.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
mount_completed(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
	mutex_enter(&mount_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
	if (--mounts_in_progress == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
		cv_broadcast(&mount_cv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
	mutex_exit(&mount_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
 * ZSD routines.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
 * Zone Specific Data (ZSD) is modeled after Thread Specific Data as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
 * defined by the pthread_key_create() and related interfaces.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
 * Kernel subsystems may register one or more data items and/or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
 * callbacks to be executed when a zone is created, shutdown, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
 * destroyed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
 * Unlike the thread counterpart, destructor callbacks will be executed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
 * even if the data pointer is NULL and/or there are no constructor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
 * callbacks, so it is the responsibility of such callbacks to check for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
 * NULL data values if necessary.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
 * The locking strategy and overall picture is as follows:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
 * When someone calls zone_key_create(), a template ZSD entry is added to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
 * global list "zsd_registered_keys", protected by zsd_key_lock.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
 * constructor callback is called immediately on all existing zones, and a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
 * copy of the ZSD entry added to the per-zone zone_zsd list (protected by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
 * zone_lock).  As this operation requires the list of zones, the list of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
 * registered keys, and the per-zone list of ZSD entries to remain constant
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
 * throughout the entire operation, it must grab zonehash_lock, zone_lock for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
 * all existing zones, and zsd_key_lock, in that order.  Similar locking is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
 * needed when zone_key_delete() is called.  It is thus sufficient to hold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
 * zsd_key_lock *or* zone_lock to prevent additions to or removals from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
 * per-zone zone_zsd list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
 * Note that this implementation does not make a copy of the ZSD entry if a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
 * constructor callback is not provided.  A zone_getspecific() on such an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
 * uninitialized ZSD entry will return NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
 * When new zones are created constructor callbacks for all registered ZSD
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
 * entries will be called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
 * The framework does not provide any locking around zone_getspecific() and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
 * zone_setspecific() apart from that needed for internal consistency, so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
 * callers interested in atomic "test-and-set" semantics will need to provide
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
 * their own locking.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
zone_key_create(zone_key_t *keyp, void *(*create)(zoneid_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
    void (*shutdown)(zoneid_t, void *), void (*destroy)(zoneid_t, void *))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
	struct zsd_entry *zsdp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
	struct zsd_entry *t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
	struct zone *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
	zsdp = kmem_alloc(sizeof (*zsdp), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
	zsdp->zsd_data = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
	zsdp->zsd_create = create;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
	zsdp->zsd_shutdown = shutdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
	zsdp->zsd_destroy = destroy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
	mutex_enter(&zonehash_lock);	/* stop the world */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
	for (zone = list_head(&zone_active); zone != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
	    zone = list_next(&zone_active, zone))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
		mutex_enter(&zone->zone_lock);	/* lock all zones */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
	mutex_enter(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
	*keyp = zsdp->zsd_key = ++zsd_keyval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
	ASSERT(zsd_keyval != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
	list_insert_tail(&zsd_registered_keys, zsdp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
	mutex_exit(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
	if (create != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
		for (zone = list_head(&zone_active); zone != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
		    zone = list_next(&zone_active, zone)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
			t = kmem_alloc(sizeof (*t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
			t->zsd_key = *keyp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
			t->zsd_data = (*create)(zone->zone_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
			t->zsd_create = create;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
			t->zsd_shutdown = shutdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
			t->zsd_destroy = destroy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
			list_insert_tail(&zone->zone_zsd, t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
	for (zone = list_head(&zone_active); zone != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
	    zone = list_next(&zone_active, zone))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
		mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
 * Helper function to find the zsd_entry associated with the key in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
 * given list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
static struct zsd_entry *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
zsd_find(list_t *l, zone_key_t key)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
	struct zsd_entry *zsd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
	for (zsd = list_head(l); zsd != NULL; zsd = list_next(l, zsd)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
		if (zsd->zsd_key == key) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
			 * Move to head of list to keep list in MRU order.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
			if (zsd != list_head(l)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
				list_remove(l, zsd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
				list_insert_head(l, zsd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
			return (zsd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
 * Function called when a module is being unloaded, or otherwise wishes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
 * to unregister its ZSD key and callbacks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
zone_key_delete(zone_key_t key)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
	struct zsd_entry *zsdp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
	mutex_enter(&zonehash_lock);	/* Zone create/delete waits for us */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
	for (zone = list_head(&zone_active); zone != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
	    zone = list_next(&zone_active, zone))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
		mutex_enter(&zone->zone_lock);	/* lock all zones */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
	mutex_enter(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
	zsdp = zsd_find(&zsd_registered_keys, key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
	if (zsdp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
		goto notfound;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
	list_remove(&zsd_registered_keys, zsdp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
	mutex_exit(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
	for (zone = list_head(&zone_active); zone != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
	    zone = list_next(&zone_active, zone)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
		struct zsd_entry *del;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
		void *data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
		if (!(zone->zone_flags & ZF_DESTROYED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
			del = zsd_find(&zone->zone_zsd, key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
			if (del != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
				data = del->zsd_data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
				ASSERT(del->zsd_shutdown == zsdp->zsd_shutdown);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
				ASSERT(del->zsd_destroy == zsdp->zsd_destroy);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
				list_remove(&zone->zone_zsd, del);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
				kmem_free(del, sizeof (*del));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
				data = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
			if (zsdp->zsd_shutdown)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
				zsdp->zsd_shutdown(zone->zone_id, data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
			if (zsdp->zsd_destroy)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
				zsdp->zsd_destroy(zone->zone_id, data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
		mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
	kmem_free(zsdp, sizeof (*zsdp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
notfound:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
	mutex_exit(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
	for (zone = list_head(&zone_active); zone != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
	    zone = list_next(&zone_active, zone))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
		mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
	return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
 * ZSD counterpart of pthread_setspecific().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
zone_setspecific(zone_key_t key, zone_t *zone, const void *data)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
	struct zsd_entry *t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
	struct zsd_entry *zsdp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
	mutex_enter(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
	t = zsd_find(&zone->zone_zsd, key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
	if (t != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
		 * Replace old value with new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
		t->zsd_data = (void *)data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
		mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
	 * If there was no previous value, go through the list of registered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
	 * keys.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
	 * We avoid grabbing zsd_key_lock until we are sure we need it; this is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
	 * necessary for shutdown callbacks to be able to execute without fear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
	 * of deadlock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
	mutex_enter(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
	zsdp = zsd_find(&zsd_registered_keys, key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
	if (zsdp == NULL) { 	/* Key was not registered */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
		mutex_exit(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
		mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
	 * Add a zsd_entry to this zone, using the template we just retrieved
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
	 * to initialize the constructor and destructor(s).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
	t = kmem_alloc(sizeof (*t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
	t->zsd_key = key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
	t->zsd_data = (void *)data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
	t->zsd_create = zsdp->zsd_create;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
	t->zsd_shutdown = zsdp->zsd_shutdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
	t->zsd_destroy = zsdp->zsd_destroy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
	list_insert_tail(&zone->zone_zsd, t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
	mutex_exit(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
	mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
 * ZSD counterpart of pthread_getspecific().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
void *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
zone_getspecific(zone_key_t key, zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
	struct zsd_entry *t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
	void *data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
	mutex_enter(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
	t = zsd_find(&zone->zone_zsd, key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
	data = (t == NULL ? NULL : t->zsd_data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
	mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
	return (data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
 * Function used to initialize a zone's list of ZSD callbacks and data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
 * when the zone is being created.  The callbacks are initialized from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
 * the template list (zsd_registered_keys), and the constructor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
 * callback executed (if one exists).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
 * This is called before the zone is made publicly available, hence no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
 * need to grab zone_lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
 * Although we grab and release zsd_key_lock, new entries cannot be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
 * added to or removed from the zsd_registered_keys list until we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
 * release zonehash_lock, so there isn't a window for a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
 * zone_key_create() to come in after we've dropped zsd_key_lock but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
 * before the zone is added to the zone list, such that the constructor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
 * callbacks aren't executed for the new zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
zone_zsd_configure(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
	struct zsd_entry *zsdp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
	struct zsd_entry *t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
	zoneid_t zoneid = zone->zone_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
	ASSERT(MUTEX_HELD(&zonehash_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
	ASSERT(list_head(&zone->zone_zsd) == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
	mutex_enter(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
	for (zsdp = list_head(&zsd_registered_keys); zsdp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
	    zsdp = list_next(&zsd_registered_keys, zsdp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
		if (zsdp->zsd_create != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
			t = kmem_alloc(sizeof (*t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
			t->zsd_key = zsdp->zsd_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
			t->zsd_create = zsdp->zsd_create;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
			t->zsd_data = (*t->zsd_create)(zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
			t->zsd_shutdown = zsdp->zsd_shutdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
			t->zsd_destroy = zsdp->zsd_destroy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
			list_insert_tail(&zone->zone_zsd, t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
	mutex_exit(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
enum zsd_callback_type { ZSD_CREATE, ZSD_SHUTDOWN, ZSD_DESTROY };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
 * Helper function to execute shutdown or destructor callbacks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
zone_zsd_callbacks(zone_t *zone, enum zsd_callback_type ct)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
	struct zsd_entry *zsdp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
	struct zsd_entry *t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
	zoneid_t zoneid = zone->zone_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
	ASSERT(ct == ZSD_SHUTDOWN || ct == ZSD_DESTROY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
	ASSERT(ct != ZSD_SHUTDOWN || zone_status_get(zone) >= ZONE_IS_EMPTY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
	ASSERT(ct != ZSD_DESTROY || zone_status_get(zone) >= ZONE_IS_DOWN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
	mutex_enter(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
	if (ct == ZSD_DESTROY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
		if (zone->zone_flags & ZF_DESTROYED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
			 * Make sure destructors are only called once.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
			mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
		zone->zone_flags |= ZF_DESTROYED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
	mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
	 * Both zsd_key_lock and zone_lock need to be held in order to add or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
	 * remove a ZSD key, (either globally as part of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
	 * zone_key_create()/zone_key_delete(), or on a per-zone basis, as is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
	 * possible through zone_setspecific()), so it's sufficient to hold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
	 * zsd_key_lock here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
	 * This is a good thing, since we don't want to recursively try to grab
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
	 * zone_lock if a callback attempts to do something like a crfree() or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
	 * zone_rele().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
	mutex_enter(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
	for (zsdp = list_head(&zsd_registered_keys); zsdp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
	    zsdp = list_next(&zsd_registered_keys, zsdp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
		zone_key_t key = zsdp->zsd_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
		/* Skip if no callbacks registered */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
		if (ct == ZSD_SHUTDOWN && zsdp->zsd_shutdown == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
		if (ct == ZSD_DESTROY && zsdp->zsd_destroy == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
		 * Call the callback with the zone-specific data if we can find
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
		 * any, otherwise with NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
		t = zsd_find(&zone->zone_zsd, key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
		if (t != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
			if (ct == ZSD_SHUTDOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
				t->zsd_shutdown(zoneid, t->zsd_data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
				ASSERT(ct == ZSD_DESTROY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
				t->zsd_destroy(zoneid, t->zsd_data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
			if (ct == ZSD_SHUTDOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
				zsdp->zsd_shutdown(zoneid, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
				ASSERT(ct == ZSD_DESTROY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
				zsdp->zsd_destroy(zoneid, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
	mutex_exit(&zsd_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
 * Called when the zone is going away; free ZSD-related memory, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
 * destroy the zone_zsd list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
zone_free_zsd(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
	struct zsd_entry *t, *next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
	 * Free all the zsd_entry's we had on this zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
	for (t = list_head(&zone->zone_zsd); t != NULL; t = next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
		next = list_next(&zone->zone_zsd, t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
		list_remove(&zone->zone_zsd, t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
		kmem_free(t, sizeof (*t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
	list_destroy(&zone->zone_zsd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
/*
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   815
 * Frees memory associated with the zone dataset list.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   816
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   817
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   818
zone_free_datasets(zone_t *zone)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   819
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   820
	zone_dataset_t *t, *next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   821
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   822
	for (t = list_head(&zone->zone_datasets); t != NULL; t = next) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   823
		next = list_next(&zone->zone_datasets, t);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   824
		list_remove(&zone->zone_datasets, t);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   825
		kmem_free(t->zd_dataset, strlen(t->zd_dataset) + 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   826
		kmem_free(t, sizeof (*t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   827
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   828
	list_destroy(&zone->zone_datasets);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   829
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   830
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
   831
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
 * zone.cpu-shares resource control support.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
static rctl_qty_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
zone_cpu_shares_usage(rctl_t *rctl, struct proc *p)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
	ASSERT(MUTEX_HELD(&p->p_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
	return (p->p_zone->zone_shares);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
zone_cpu_shares_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
    rctl_qty_t nv)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
	ASSERT(MUTEX_HELD(&p->p_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
	ASSERT(e->rcep_t == RCENTITY_ZONE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
	if (e->rcep_p.zone == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
	e->rcep_p.zone->zone_shares = nv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
static rctl_ops_t zone_cpu_shares_ops = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
	rcop_no_action,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
	zone_cpu_shares_usage,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
	zone_cpu_shares_set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
	rcop_no_test
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
static rctl_qty_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
zone_lwps_usage(rctl_t *r, proc_t *p)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
	rctl_qty_t nlwps;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
	zone_t *zone = p->p_zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
	ASSERT(MUTEX_HELD(&p->p_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
	mutex_enter(&zone->zone_nlwps_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
	nlwps = zone->zone_nlwps;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
	mutex_exit(&zone->zone_nlwps_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
	return (nlwps);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
zone_lwps_test(rctl_t *r, proc_t *p, rctl_entity_p_t *e, rctl_val_t *rcntl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
    rctl_qty_t incr, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
	rctl_qty_t nlwps;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
	ASSERT(MUTEX_HELD(&p->p_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
	ASSERT(e->rcep_t == RCENTITY_ZONE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
	if (e->rcep_p.zone == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
	ASSERT(MUTEX_HELD(&(e->rcep_p.zone->zone_nlwps_lock)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
	nlwps = e->rcep_p.zone->zone_nlwps;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
	if (nlwps + incr > rcntl->rcv_value)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
		return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
zone_lwps_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e, rctl_qty_t nv) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
	ASSERT(MUTEX_HELD(&p->p_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
	ASSERT(e->rcep_t == RCENTITY_ZONE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
	if (e->rcep_p.zone == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
	e->rcep_p.zone->zone_nlwps_ctl = nv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
static rctl_ops_t zone_lwps_ops = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
	rcop_no_action,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
	zone_lwps_usage,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
	zone_lwps_set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
	zone_lwps_test,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
 * Helper function to brand the zone with a unique ID.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
zone_uniqid(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
	static uint64_t uniqid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
	ASSERT(MUTEX_HELD(&zonehash_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
	zone->zone_uniqid = uniqid++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
 * Returns a held pointer to the "kcred" for the specified zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
struct cred *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
zone_get_kcred(zoneid_t zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
	cred_t *cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
	if ((zone = zone_find_by_id(zoneid)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
	cr = zone->zone_kcred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
	crhold(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
	zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
	return (cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
 * Called very early on in boot to initialize the ZSD list so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
 * zone_key_create() can be called before zone_init().  It also initializes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
 * portions of zone0 which may be used before zone_init() is called.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
 * variable "global_zone" will be set when zone0 is fully initialized by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
 * zone_init().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
zone_zsd_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
	mutex_init(&zonehash_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
	mutex_init(&zsd_key_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
	list_create(&zsd_registered_keys, sizeof (struct zsd_entry),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
	    offsetof(struct zsd_entry, zsd_linkage));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
	list_create(&zone_active, sizeof (zone_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
	    offsetof(zone_t, zone_linkage));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
	list_create(&zone_deathrow, sizeof (zone_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
	    offsetof(zone_t, zone_linkage));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
	mutex_init(&zone0.zone_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
	mutex_init(&zone0.zone_nlwps_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
	zone0.zone_shares = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
	zone0.zone_nlwps_ctl = INT_MAX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
	zone0.zone_name = GLOBAL_ZONENAME;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
	zone0.zone_nodename = utsname.nodename;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
	zone0.zone_domain = srpc_domain;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
	zone0.zone_ref = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
	zone0.zone_id = GLOBAL_ZONEID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
	zone0.zone_status = ZONE_IS_RUNNING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
	zone0.zone_rootpath = "/";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
	zone0.zone_rootpathlen = 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
	zone0.zone_psetid = ZONE_PS_INVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
	zone0.zone_ncpus = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
	zone0.zone_ncpus_online = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
	zone0.zone_proc_initpid = 1;
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
   982
	zone0.zone_initname = initname;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
	list_create(&zone0.zone_zsd, sizeof (struct zsd_entry),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
	    offsetof(struct zsd_entry, zsd_linkage));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
	list_insert_head(&zone_active, &zone0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
	 * The root filesystem is not mounted yet, so zone_rootvp cannot be set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
	 * to anything meaningful.  It is assigned to be 'rootdir' in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
	 * vfs_mountroot().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
	zone0.zone_rootvp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
	zone0.zone_vfslist = NULL;
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
   994
	zone0.zone_bootargs = initargs;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
	zone0.zone_privset = kmem_alloc(sizeof (priv_set_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
	 * The global zone has all privileges
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
	priv_fillset(zone0.zone_privset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
	 * Add p0 to the global zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
	zone0.zone_zsched = &p0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
	p0.p_zone = &zone0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
/*
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1008
 * Compute a hash value based on the contents of the label and the DOI.  The
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1009
 * hash algorithm is somewhat arbitrary, but is based on the observation that
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1010
 * humans will likely pick labels that differ by amounts that work out to be
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1011
 * multiples of the number of hash chains, and thus stirring in some primes
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1012
 * should help.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1013
 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1014
static uint_t
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1015
hash_bylabel(void *hdata, mod_hash_key_t key)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1016
{
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1017
	const ts_label_t *lab = (ts_label_t *)key;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1018
	const uint32_t *up, *ue;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1019
	uint_t hash;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1020
	int i;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1021
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1022
	_NOTE(ARGUNUSED(hdata));
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1023
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1024
	hash = lab->tsl_doi + (lab->tsl_doi << 1);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1025
	/* we depend on alignment of label, but not representation */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1026
	up = (const uint32_t *)&lab->tsl_label;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1027
	ue = up + sizeof (lab->tsl_label) / sizeof (*up);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1028
	i = 1;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1029
	while (up < ue) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1030
		/* using 2^n + 1, 1 <= n <= 16 as source of many primes */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1031
		hash += *up + (*up << ((i % 16) + 1));
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1032
		up++;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1033
		i++;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1034
	}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1035
	return (hash);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1036
}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1037
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1038
/*
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1039
 * All that mod_hash cares about here is zero (equal) versus non-zero (not
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1040
 * equal).  This may need to be changed if less than / greater than is ever
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1041
 * needed.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1042
 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1043
static int
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1044
hash_labelkey_cmp(mod_hash_key_t key1, mod_hash_key_t key2)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1045
{
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1046
	ts_label_t *lab1 = (ts_label_t *)key1;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1047
	ts_label_t *lab2 = (ts_label_t *)key2;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1048
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1049
	return (label_equal(lab1, lab2) ? 0 : 1);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1050
}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1051
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1052
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
 * Called by main() to initialize the zones framework.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
zone_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
	rctl_dict_entry_t *rde;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
	rctl_val_t *dval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
	rctl_set_t *set;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
	rctl_alloc_gp_t *gp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
	rctl_entity_p_t e;
1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1063
	int res;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
	ASSERT(curproc == &p0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
	 * Create ID space for zone IDs.  ID 0 is reserved for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
	 * global zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
	zoneid_space = id_space_create("zoneid_space", 1, MAX_ZONEID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
	 * Initialize generic zone resource controls, if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
	rc_zone_cpu_shares = rctl_register("zone.cpu-shares",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
	    RCENTITY_ZONE, RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_DENY_NEVER |
1996
1bd5128dcd61 6294710 rctladm incorrectly claims and reports it can log to syslog for project.cpu-shares
ml93401
parents: 1876
diff changeset
  1078
	    RCTL_GLOBAL_NOBASIC | RCTL_GLOBAL_COUNT | RCTL_GLOBAL_SYSLOG_NEVER,
1bd5128dcd61 6294710 rctladm incorrectly claims and reports it can log to syslog for project.cpu-shares
ml93401
parents: 1876
diff changeset
  1079
	    FSS_MAXSHARES, FSS_MAXSHARES,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
	    &zone_cpu_shares_ops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
	rc_zone_nlwps = rctl_register("zone.max-lwps", RCENTITY_ZONE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
	    RCTL_GLOBAL_NOACTION | RCTL_GLOBAL_NOBASIC | RCTL_GLOBAL_COUNT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
	    INT_MAX, INT_MAX, &zone_lwps_ops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
	 * Create a rctl_val with PRIVILEGED, NOACTION, value = 1.  Then attach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
	 * this at the head of the rctl_dict_entry for ``zone.cpu-shares''.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
	dval = kmem_cache_alloc(rctl_val_cache, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
	bzero(dval, sizeof (rctl_val_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
	dval->rcv_value = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
	dval->rcv_privilege = RCPRIV_PRIVILEGED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
	dval->rcv_flagaction = RCTL_LOCAL_NOACTION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
	dval->rcv_action_recip_pid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
	rde = rctl_dict_lookup("zone.cpu-shares");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
	(void) rctl_val_list_insert(&rde->rcd_default_value, dval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
	 * Initialize the ``global zone''.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
	set = rctl_set_create();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
	gp = rctl_set_init_prealloc(RCENTITY_ZONE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
	mutex_enter(&p0.p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
	e.rcep_p.zone = &zone0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
	e.rcep_t = RCENTITY_ZONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
	zone0.zone_rctls = rctl_set_init(RCENTITY_ZONE, &p0, &e, set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
	    gp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
	zone0.zone_nlwps = p0.p_lwpcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
	zone0.zone_ntasks = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
	mutex_exit(&p0.p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
	rctl_prealloc_destroy(gp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
	 * pool_default hasn't been initialized yet, so we let pool_init() take
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
	 * care of making the global zone is in the default pool.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
	 */
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1118
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1119
	/*
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1120
	 * Initialize zone label.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1121
	 * mlp are initialized when tnzonecfg is loaded.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1122
	 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1123
	zone0.zone_slabel = l_admin_low;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1124
	rw_init(&zone0.zone_mlps.mlpl_rwlock, NULL, RW_DEFAULT, NULL);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1125
	label_hold(l_admin_low);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1126
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
	zone_uniqid(&zone0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
	ASSERT(zone0.zone_uniqid == GLOBAL_ZONEUNIQID);
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1130
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
	zonehashbyid = mod_hash_create_idhash("zone_by_id", zone_hash_size,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
	    mod_hash_null_valdtor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
	zonehashbyname = mod_hash_create_strhash("zone_by_name",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
	    zone_hash_size, mod_hash_null_valdtor);
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1135
	/*
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1136
	 * maintain zonehashbylabel only for labeled systems
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1137
	 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1138
	if (is_system_labeled())
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1139
		zonehashbylabel = mod_hash_create_extended("zone_by_label",
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1140
		    zone_hash_size, mod_hash_null_keydtor,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1141
		    mod_hash_null_valdtor, hash_bylabel, NULL,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1142
		    hash_labelkey_cmp, KM_SLEEP);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
	zonecount = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
	(void) mod_hash_insert(zonehashbyid, (mod_hash_key_t)GLOBAL_ZONEID,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
	    (mod_hash_val_t)&zone0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
	(void) mod_hash_insert(zonehashbyname, (mod_hash_key_t)zone0.zone_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
	    (mod_hash_val_t)&zone0);
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  1149
	if (is_system_labeled()) {
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  1150
		zone0.zone_flags |= ZF_HASHED_LABEL;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1151
		(void) mod_hash_insert(zonehashbylabel,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1152
		    (mod_hash_key_t)zone0.zone_slabel, (mod_hash_val_t)&zone0);
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  1153
	}
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1154
	mutex_exit(&zonehash_lock);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1155
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
	 * We avoid setting zone_kcred until now, since kcred is initialized
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
	 * sometime after zone_zsd_init() and before zone_init().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
	zone0.zone_kcred = kcred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
	 * The global zone is fully initialized (except for zone_rootvp which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
	 * will be set when the root filesystem is mounted).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
	global_zone = &zone0;
1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1167
	/*
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1168
	 * Setup an event channel to send zone status change notifications on
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1169
	 */
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1170
	res = sysevent_evc_bind(ZONE_EVENT_CHANNEL, &zone_event_chan,
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1171
	    EVCH_CREAT);
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1172
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1173
	if (res)
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1174
		panic("Sysevent_evc_bind failed during zone setup.\n");
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
zone_free(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
	ASSERT(zone != global_zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
	ASSERT(zone->zone_ntasks == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
	ASSERT(zone->zone_nlwps == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
	ASSERT(zone->zone_cred_ref == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
	ASSERT(zone->zone_kcred == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
	ASSERT(zone_status_get(zone) == ZONE_IS_DEAD ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
	    zone_status_get(zone) == ZONE_IS_UNINITIALIZED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
	/* remove from deathrow list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
	if (zone_status_get(zone) == ZONE_IS_DEAD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
		ASSERT(zone->zone_ref == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
		mutex_enter(&zone_deathrow_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
		list_remove(&zone_deathrow, zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
		mutex_exit(&zone_deathrow_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
	zone_free_zsd(zone);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  1197
	zone_free_datasets(zone);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
	if (zone->zone_rootvp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
		VN_RELE(zone->zone_rootvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1201
	if (zone->zone_rootpath)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
		kmem_free(zone->zone_rootpath, zone->zone_rootpathlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1203
	if (zone->zone_name != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1204
		kmem_free(zone->zone_name, ZONENAME_MAX);
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1205
	if (zone->zone_slabel != NULL)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1206
		label_rele(zone->zone_slabel);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1207
	if (zone->zone_nodename != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1208
		kmem_free(zone->zone_nodename, _SYS_NMLN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1209
	if (zone->zone_domain != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1210
		kmem_free(zone->zone_domain, _SYS_NMLN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
	if (zone->zone_privset != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1212
		kmem_free(zone->zone_privset, sizeof (priv_set_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
	if (zone->zone_rctls != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
		rctl_set_free(zone->zone_rctls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
	if (zone->zone_bootargs != NULL)
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1216
		kmem_free(zone->zone_bootargs, strlen(zone->zone_bootargs) + 1);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1217
	if (zone->zone_initname != NULL)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1218
		kmem_free(zone->zone_initname, strlen(zone->zone_initname) + 1);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
	id_free(zoneid_space, zone->zone_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
	mutex_destroy(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
	cv_destroy(&zone->zone_cv);
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1222
	rw_destroy(&zone->zone_mlps.mlpl_rwlock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
	kmem_free(zone, sizeof (zone_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
 * See block comment at the top of this file for information about zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
 * status values.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
 * Convenience function for setting zone status.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
zone_status_set(zone_t *zone, zone_status_t status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
{
1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1236
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1237
	nvlist_t *nvl = NULL;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
	ASSERT(MUTEX_HELD(&zone_status_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
	ASSERT(status > ZONE_MIN_STATE && status <= ZONE_MAX_STATE &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
	    status >= zone_status_get(zone));
1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1241
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1242
	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) ||
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1243
	    nvlist_add_string(nvl, ZONE_CB_NAME, zone->zone_name) ||
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1244
	    nvlist_add_string(nvl, ZONE_CB_NEWSTATE,
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1245
	    zone_status_table[status]) ||
1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1246
	    nvlist_add_string(nvl, ZONE_CB_OLDSTATE,
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1247
	    zone_status_table[zone->zone_status]) ||
1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1248
	    nvlist_add_int32(nvl, ZONE_CB_ZONEID, zone->zone_id) ||
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1249
	    nvlist_add_uint64(nvl, ZONE_CB_TIMESTAMP, (uint64_t)gethrtime()) ||
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1250
	    sysevent_evc_publish(zone_event_chan, ZONE_EVENT_STATUS_CLASS,
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1251
	    ZONE_EVENT_STATUS_SUBCLASS, "sun.com", "kernel", nvl, EVCH_SLEEP)) {
1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1252
#ifdef DEBUG
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1253
		(void) printf(
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1254
		    "Failed to allocate and send zone state change event.\n");
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1255
#endif
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1256
	}
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1257
	nvlist_free(nvl);
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1258
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
	zone->zone_status = status;
1166
1eedf65f1c9f PSARC/2005/607 Zone Events for Sun Cluster
dstaff
parents: 1075
diff changeset
  1260
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
	cv_broadcast(&zone->zone_cv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
 * Public function to retrieve the zone status.  The zone status may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
 * change after it is retrieved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
zone_status_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
zone_status_get(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
	return (zone->zone_status);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1272
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1273
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
zone_set_bootargs(zone_t *zone, const char *zone_bootargs)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
{
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1277
	char *bootargs = kmem_zalloc(BOOTARGS_MAX, KM_SLEEP);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1278
	int err = 0;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1279
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1280
	ASSERT(zone != global_zone);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1281
	if ((err = copyinstr(zone_bootargs, bootargs, BOOTARGS_MAX, NULL)) != 0)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1282
		goto done;	/* EFAULT or ENAMETOOLONG */
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1283
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1284
	if (zone->zone_bootargs != NULL)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1285
		kmem_free(zone->zone_bootargs, strlen(zone->zone_bootargs) + 1);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1286
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1287
	zone->zone_bootargs = kmem_alloc(strlen(bootargs) + 1, KM_SLEEP);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1288
	(void) strcpy(zone->zone_bootargs, bootargs);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1289
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1290
done:
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1291
	kmem_free(bootargs, BOOTARGS_MAX);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1292
	return (err);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1293
}
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1294
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1295
static int
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1296
zone_set_initname(zone_t *zone, const char *zone_initname)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1297
{
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1298
	char initname[INITNAME_SZ];
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
	size_t len;
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1300
	int err = 0;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1301
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1302
	ASSERT(zone != global_zone);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1303
	if ((err = copyinstr(zone_initname, initname, INITNAME_SZ, &len)) != 0)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
		return (err);	/* EFAULT or ENAMETOOLONG */
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1305
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1306
	if (zone->zone_initname != NULL)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1307
		kmem_free(zone->zone_initname, strlen(zone->zone_initname) + 1);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1308
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1309
	zone->zone_initname = kmem_alloc(strlen(initname) + 1, KM_SLEEP);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  1310
	(void) strcpy(zone->zone_initname, initname);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
 * Block indefinitely waiting for (zone_status >= status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
zone_status_wait(zone_t *zone, zone_status_t status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
	ASSERT(status > ZONE_MIN_STATE && status <= ZONE_MAX_STATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
	while (zone->zone_status < status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
		cv_wait(&zone->zone_cv, &zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
 * Private CPR-safe version of zone_status_wait().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
zone_status_wait_cpr(zone_t *zone, zone_status_t status, char *str)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
	callb_cpr_t cprinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
	ASSERT(status > ZONE_MIN_STATE && status <= ZONE_MAX_STATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
	CALLB_CPR_INIT(&cprinfo, &zone_status_lock, callb_generic_cpr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
	    str);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
	while (zone->zone_status < status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
		CALLB_CPR_SAFE_BEGIN(&cprinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
		cv_wait(&zone->zone_cv, &zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
		CALLB_CPR_SAFE_END(&cprinfo, &zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
	 * zone_status_lock is implicitly released by the following.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
	CALLB_CPR_EXIT(&cprinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
 * Block until zone enters requested state or signal is received.  Return (0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
 * if signaled, non-zero otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
zone_status_wait_sig(zone_t *zone, zone_status_t status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
	ASSERT(status > ZONE_MIN_STATE && status <= ZONE_MAX_STATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
	while (zone->zone_status < status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
		if (!cv_wait_sig(&zone->zone_cv, &zone_status_lock)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
			mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
 * Block until the zone enters the requested state or the timeout expires,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
 * whichever happens first.  Return (-1) if operation timed out, time remaining
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
 * otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
clock_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
zone_status_timedwait(zone_t *zone, clock_t tim, zone_status_t status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
	clock_t timeleft = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
	ASSERT(status > ZONE_MIN_STATE && status <= ZONE_MAX_STATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
	while (zone->zone_status < status && timeleft != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
		timeleft = cv_timedwait(&zone->zone_cv, &zone_status_lock, tim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
	return (timeleft);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
 * Block until the zone enters the requested state, the current process is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
 * signaled,  or the timeout expires, whichever happens first.  Return (-1) if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
 * operation timed out, 0 if signaled, time remaining otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
clock_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
zone_status_timedwait_sig(zone_t *zone, clock_t tim, zone_status_t status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
	clock_t timeleft = tim - lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
	ASSERT(status > ZONE_MIN_STATE && status <= ZONE_MAX_STATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1404
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1406
	while (zone->zone_status < status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
		timeleft = cv_timedwait_sig(&zone->zone_cv, &zone_status_lock,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
		    tim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
		if (timeleft <= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
	return (timeleft);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1414
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
 * Zones have two reference counts: one for references from credential
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
 * structures (zone_cred_ref), and one (zone_ref) for everything else.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
 * This is so we can allow a zone to be rebooted while there are still
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
 * outstanding cred references, since certain drivers cache dblks (which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
 * implicitly results in cached creds).  We wait for zone_ref to drop to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
 * 0 (actually 1), but not zone_cred_ref.  The zone structure itself is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
 * later freed when the zone_cred_ref drops to 0, though nothing other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
 * than the zone id and privilege set should be accessed once the zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
 * is "dead".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1426
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1427
 * A debugging flag, zone_wait_for_cred, can be set to a non-zero value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1428
 * to force halt/reboot to block waiting for the zone_cred_ref to drop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
 * to 0.  This can be useful to flush out other sources of cached creds
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
 * that may be less innocuous than the driver case.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
int zone_wait_for_cred = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
zone_hold_locked(zone_t *z)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
	ASSERT(MUTEX_HELD(&z->zone_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
	z->zone_ref++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
	ASSERT(z->zone_ref != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1443
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
zone_hold(zone_t *z)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
	mutex_enter(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
	zone_hold_locked(z);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
	mutex_exit(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
 * If the non-cred ref count drops to 1 and either the cred ref count
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
 * is 0 or we aren't waiting for cred references, the zone is ready to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
 * be destroyed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
#define	ZONE_IS_UNREF(zone)	((zone)->zone_ref == 1 && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
	    (!zone_wait_for_cred || (zone)->zone_cred_ref == 0))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
zone_rele(zone_t *z)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1462
	boolean_t wakeup;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1464
	mutex_enter(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
	ASSERT(z->zone_ref != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
	z->zone_ref--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
	if (z->zone_ref == 0 && z->zone_cred_ref == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
		/* no more refs, free the structure */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
		mutex_exit(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
		zone_free(z);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
	/* signal zone_destroy so the zone can finish halting */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
	wakeup = (ZONE_IS_UNREF(z) && zone_status_get(z) >= ZONE_IS_DEAD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1475
	mutex_exit(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1476
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1477
	if (wakeup) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1478
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1479
		 * Grabbing zonehash_lock here effectively synchronizes with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1480
		 * zone_destroy() to avoid missed signals.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1481
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1482
		mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1483
		cv_broadcast(&zone_destroy_cv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1484
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1485
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1486
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1487
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
zone_cred_hold(zone_t *z)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1491
	mutex_enter(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1492
	z->zone_cred_ref++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1493
	ASSERT(z->zone_cred_ref != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1494
	mutex_exit(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1495
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
zone_cred_rele(zone_t *z)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
	boolean_t wakeup;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
	mutex_enter(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
	ASSERT(z->zone_cred_ref != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
	z->zone_cred_ref--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
	if (z->zone_ref == 0 && z->zone_cred_ref == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
		/* no more refs, free the structure */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
		mutex_exit(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
		zone_free(z);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
	 * If zone_destroy is waiting for the cred references to drain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
	 * out, and they have, signal it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
	wakeup = (zone_wait_for_cred && ZONE_IS_UNREF(z) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
	    zone_status_get(z) >= ZONE_IS_DEAD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
	mutex_exit(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
	if (wakeup) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1520
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
		 * Grabbing zonehash_lock here effectively synchronizes with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
		 * zone_destroy() to avoid missed signals.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
		mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
		cv_broadcast(&zone_destroy_cv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
zone_task_hold(zone_t *z)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
	mutex_enter(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
	z->zone_ntasks++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
	ASSERT(z->zone_ntasks != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1536
	mutex_exit(&z->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1537
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1539
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1540
zone_task_rele(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1541
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1542
	uint_t refcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1543
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1544
	mutex_enter(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1545
	ASSERT(zone->zone_ntasks != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1546
	refcnt = --zone->zone_ntasks;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1547
	if (refcnt > 1)	{	/* Common case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1548
		mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1549
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1550
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1551
	zone_hold_locked(zone);	/* so we can use the zone_t later */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1552
	mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
	if (refcnt == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
		 * See if the zone is shutting down.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
		mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
		if (zone_status_get(zone) != ZONE_IS_SHUTTING_DOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1562
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1563
		 * Make sure the ntasks didn't change since we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
		 * dropped zone_lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1565
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1566
		mutex_enter(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
		if (refcnt != zone->zone_ntasks) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
			mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1571
		mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1572
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1574
		 * No more user processes in the zone.  The zone is empty.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1575
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
		zone_status_set(zone, ZONE_IS_EMPTY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
	ASSERT(refcnt == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
	 * zsched has exited; the zone is dead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
	zone->zone_zsched = NULL;		/* paranoia */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
	zone_status_set(zone, ZONE_IS_DEAD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
	zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
zoneid_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
getzoneid(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
	return (curproc->p_zone->zone_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
 * Internal versions of zone_find_by_*().  These don't zone_hold() or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
 * check the validity of a zone's state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
static zone_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
zone_find_all_by_id(zoneid_t zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
	mod_hash_val_t hv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
	zone_t *zone = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
	ASSERT(MUTEX_HELD(&zonehash_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
	if (mod_hash_find(zonehashbyid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
	    (mod_hash_key_t)(uintptr_t)zoneid, &hv) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
		zone = (zone_t *)hv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
	return (zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
static zone_t *
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1617
zone_find_all_by_label(const ts_label_t *label)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1618
{
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1619
	mod_hash_val_t hv;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1620
	zone_t *zone = NULL;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1621
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1622
	ASSERT(MUTEX_HELD(&zonehash_lock));
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1623
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1624
	/*
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1625
	 * zonehashbylabel is not maintained for unlabeled systems
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1626
	 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1627
	if (!is_system_labeled())
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1628
		return (NULL);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1629
	if (mod_hash_find(zonehashbylabel, (mod_hash_key_t)label, &hv) == 0)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1630
		zone = (zone_t *)hv;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1631
	return (zone);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1632
}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1633
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1634
static zone_t *
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
zone_find_all_by_name(char *name)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
	mod_hash_val_t hv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
	zone_t *zone = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
	ASSERT(MUTEX_HELD(&zonehash_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
	if (mod_hash_find(zonehashbyname, (mod_hash_key_t)name, &hv) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
		zone = (zone_t *)hv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
	return (zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
 * Public interface for looking up a zone by zoneid.  Only returns the zone if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
 * it is fully initialized, and has not yet begun the zone_destroy() sequence.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
 * Caller must call zone_rele() once it is done with the zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
 * The zone may begin the zone_destroy() sequence immediately after this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
 * function returns, but may be safely used until zone_rele() is called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1655
zone_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1656
zone_find_by_id(zoneid_t zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
	zone_status_t status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1661
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1662
	if ((zone = zone_find_all_by_id(zoneid)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1663
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1664
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1665
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
	status = zone_status_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
	if (status < ZONE_IS_READY || status > ZONE_IS_DOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
		 * For all practical purposes the zone doesn't exist.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1673
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
	zone_hold(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1675
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1676
	return (zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
/*
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1680
 * Similar to zone_find_by_id, but using zone label as the key.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1681
 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1682
zone_t *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1683
zone_find_by_label(const ts_label_t *label)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1684
{
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1685
	zone_t *zone;
2110
31cba59b38be 6403267 address remaining issues raised during TX code reviews
rica
parents: 1996
diff changeset
  1686
	zone_status_t status;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1687
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1688
	mutex_enter(&zonehash_lock);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1689
	if ((zone = zone_find_all_by_label(label)) == NULL) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1690
		mutex_exit(&zonehash_lock);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1691
		return (NULL);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1692
	}
2110
31cba59b38be 6403267 address remaining issues raised during TX code reviews
rica
parents: 1996
diff changeset
  1693
31cba59b38be 6403267 address remaining issues raised during TX code reviews
rica
parents: 1996
diff changeset
  1694
	status = zone_status_get(zone);
31cba59b38be 6403267 address remaining issues raised during TX code reviews
rica
parents: 1996
diff changeset
  1695
	if (status > ZONE_IS_DOWN) {
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1696
		/*
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1697
		 * For all practical purposes the zone doesn't exist.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1698
		 */
2110
31cba59b38be 6403267 address remaining issues raised during TX code reviews
rica
parents: 1996
diff changeset
  1699
		mutex_exit(&zonehash_lock);
31cba59b38be 6403267 address remaining issues raised during TX code reviews
rica
parents: 1996
diff changeset
  1700
		return (NULL);
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1701
	}
2110
31cba59b38be 6403267 address remaining issues raised during TX code reviews
rica
parents: 1996
diff changeset
  1702
	zone_hold(zone);
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1703
	mutex_exit(&zonehash_lock);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1704
	return (zone);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1705
}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1706
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  1707
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
 * Similar to zone_find_by_id, but using zone name as the key.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
zone_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
zone_find_by_name(char *name)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
	zone_status_t status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1715
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
	if ((zone = zone_find_all_by_name(name)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1721
	status = zone_status_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1722
	if (status < ZONE_IS_READY || status > ZONE_IS_DOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1723
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1724
		 * For all practical purposes the zone doesn't exist.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1725
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1726
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1727
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1728
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1729
	zone_hold(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1730
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1731
	return (zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1732
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1733
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1734
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1735
 * Similar to zone_find_by_id(), using the path as a key.  For instance,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1736
 * if there is a zone "foo" rooted at /foo/root, and the path argument
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1737
 * is "/foo/root/proc", it will return the held zone_t corresponding to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1738
 * zone "foo".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1739
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1740
 * zone_find_by_path() always returns a non-NULL value, since at the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1741
 * very least every path will be contained in the global zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1742
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1743
 * As with the other zone_find_by_*() functions, the caller is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1744
 * responsible for zone_rele()ing the return value of this function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1745
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1746
zone_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1747
zone_find_by_path(const char *path)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1748
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1749
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1750
	zone_t *zret = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1751
	zone_status_t status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1753
	if (path == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1754
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1755
		 * Call from rootconf().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1756
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1757
		zone_hold(global_zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1758
		return (global_zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1759
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1760
	ASSERT(*path == '/');
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1761
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1762
	for (zone = list_head(&zone_active); zone != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1763
	    zone = list_next(&zone_active, zone)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1764
		if (ZONE_PATH_VISIBLE(path, zone))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1765
			zret = zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1766
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1767
	ASSERT(zret != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1768
	status = zone_status_get(zret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1769
	if (status < ZONE_IS_READY || status > ZONE_IS_DOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1770
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1771
		 * Zone practically doesn't exist.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1772
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1773
		zret = global_zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1774
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1775
	zone_hold(zret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1776
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1777
	return (zret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1778
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1779
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1780
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1781
 * Get the number of cpus visible to this zone.  The system-wide global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1782
 * 'ncpus' is returned if pools are disabled, the caller is in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1783
 * global zone, or a NULL zone argument is passed in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1784
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1785
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1786
zone_ncpus_get(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1787
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1788
	int myncpus = zone == NULL ? 0 : zone->zone_ncpus;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1789
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1790
	return (myncpus != 0 ? myncpus : ncpus);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1791
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1792
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1793
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1794
 * Get the number of online cpus visible to this zone.  The system-wide
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1795
 * global 'ncpus_online' is returned if pools are disabled, the caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1796
 * is in the global zone, or a NULL zone argument is passed in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1797
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1798
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1799
zone_ncpus_online_get(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1800
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1801
	int myncpus_online = zone == NULL ? 0 : zone->zone_ncpus_online;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1803
	return (myncpus_online != 0 ? myncpus_online : ncpus_online);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1804
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1805
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1806
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1807
 * Return the pool to which the zone is currently bound.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1808
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1809
pool_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1810
zone_pool_get(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1811
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1812
	ASSERT(pool_lock_held());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1813
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1814
	return (zone->zone_pool);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1815
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1816
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1817
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1818
 * Set the zone's pool pointer and update the zone's visibility to match
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1819
 * the resources in the new pool.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1820
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1821
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1822
zone_pool_set(zone_t *zone, pool_t *pool)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1823
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1824
	ASSERT(pool_lock_held());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1825
	ASSERT(MUTEX_HELD(&cpu_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1827
	zone->zone_pool = pool;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1828
	zone_pset_set(zone, pool->pool_pset->pset_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1829
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1831
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1832
 * Return the cached value of the id of the processor set to which the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1833
 * zone is currently bound.  The value will be ZONE_PS_INVAL if the pools
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1834
 * facility is disabled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1835
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1836
psetid_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1837
zone_pset_get(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1838
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1839
	ASSERT(MUTEX_HELD(&cpu_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1840
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1841
	return (zone->zone_psetid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1842
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1844
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1845
 * Set the cached value of the id of the processor set to which the zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1846
 * is currently bound.  Also update the zone's visibility to match the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1847
 * resources in the new processor set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1848
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1849
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1850
zone_pset_set(zone_t *zone, psetid_t newpsetid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1851
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1852
	psetid_t oldpsetid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1854
	ASSERT(MUTEX_HELD(&cpu_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1855
	oldpsetid = zone_pset_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1857
	if (oldpsetid == newpsetid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1858
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1859
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1860
	 * Global zone sees all.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1861
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1862
	if (zone != global_zone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1863
		zone->zone_psetid = newpsetid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1864
		if (newpsetid != ZONE_PS_INVAL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1865
			pool_pset_visibility_add(newpsetid, zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1866
		if (oldpsetid != ZONE_PS_INVAL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1867
			pool_pset_visibility_remove(oldpsetid, zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1868
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1869
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1870
	 * Disabling pools, so we should start using the global values
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1871
	 * for ncpus and ncpus_online.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1872
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1873
	if (newpsetid == ZONE_PS_INVAL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1874
		zone->zone_ncpus = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1875
		zone->zone_ncpus_online = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1876
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1877
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1879
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1880
 * Walk the list of active zones and issue the provided callback for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1881
 * each of them.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1882
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1883
 * Caller must not be holding any locks that may be acquired under
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1884
 * zonehash_lock.  See comment at the beginning of the file for a list of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1885
 * common locks and their interactions with zones.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1886
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1887
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1888
zone_walk(int (*cb)(zone_t *, void *), void *data)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1889
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1890
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1891
	int ret = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1892
	zone_status_t status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1893
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1894
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1895
	for (zone = list_head(&zone_active); zone != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1896
	    zone = list_next(&zone_active, zone)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1897
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1898
		 * Skip zones that shouldn't be externally visible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1899
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1900
		status = zone_status_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1901
		if (status < ZONE_IS_READY || status > ZONE_IS_DOWN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1902
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1903
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1904
		 * Bail immediately if any callback invocation returns a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1905
		 * non-zero value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1906
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1907
		ret = (*cb)(zone, data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1908
		if (ret != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1909
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1910
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1911
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1912
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1913
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1914
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1915
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1916
zone_set_root(zone_t *zone, const char *upath)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1917
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1918
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1919
	int trycount;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1920
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1921
	char *path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1922
	struct pathname upn, pn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1923
	size_t pathlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1924
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1925
	if ((error = pn_get((char *)upath, UIO_USERSPACE, &upn)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1926
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1928
	pn_alloc(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1930
	/* prevent infinite loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1931
	trycount = 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1932
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1933
		if (--trycount <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1934
			error = ESTALE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1935
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1936
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1937
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1938
		if ((error = lookuppn(&upn, &pn, FOLLOW, NULLVPP, &vp)) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1939
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1940
			 * VOP_ACCESS() may cover 'vp' with a new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1941
			 * filesystem, if 'vp' is an autoFS vnode.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1942
			 * Get the new 'vp' if so.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1943
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1944
			if ((error = VOP_ACCESS(vp, VEXEC, 0, CRED())) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1945
			    (vp->v_vfsmountedhere == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1946
			    (error = traverse(&vp)) == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1947
				pathlen = pn.pn_pathlen + 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1948
				path = kmem_alloc(pathlen, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1949
				(void) strncpy(path, pn.pn_path,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1950
				    pn.pn_pathlen + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1951
				path[pathlen - 2] = '/';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1952
				path[pathlen - 1] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1953
				pn_free(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1954
				pn_free(&upn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1955
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1956
				/* Success! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1957
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1958
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1959
			VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1960
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1961
		if (error != ESTALE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1962
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1963
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1965
	ASSERT(error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1966
	zone->zone_rootvp = vp;		/* we hold a reference to vp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1967
	zone->zone_rootpath = path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1968
	zone->zone_rootpathlen = pathlen;
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  1969
	if (pathlen > 5 && strcmp(path + pathlen - 5, "/lu/") == 0)
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  1970
		zone->zone_flags |= ZF_IS_SCRATCH;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1971
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1972
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1973
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1974
	pn_free(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1975
	pn_free(&upn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1976
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1977
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1978
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1979
#define	isalnum(c)	(((c) >= '0' && (c) <= '9') || \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1980
			((c) >= 'a' && (c) <= 'z') || \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1981
			((c) >= 'A' && (c) <= 'Z'))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1982
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1983
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1984
zone_set_name(zone_t *zone, const char *uname)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1985
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1986
	char *kname = kmem_zalloc(ZONENAME_MAX, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1987
	size_t len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1988
	int i, err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1989
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1990
	if ((err = copyinstr(uname, kname, ZONENAME_MAX, &len)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1991
		kmem_free(kname, ZONENAME_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1992
		return (err);	/* EFAULT or ENAMETOOLONG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1993
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1995
	/* must be less than ZONENAME_MAX */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1996
	if (len == ZONENAME_MAX && kname[ZONENAME_MAX - 1] != '\0') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1997
		kmem_free(kname, ZONENAME_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1998
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1999
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2000
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2001
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2002
	 * Name must start with an alphanumeric and must contain only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2003
	 * alphanumerics, '-', '_' and '.'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2004
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2005
	if (!isalnum(kname[0])) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2006
		kmem_free(kname, ZONENAME_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2007
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2008
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2009
	for (i = 1; i < len - 1; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2010
		if (!isalnum(kname[i]) && kname[i] != '-' && kname[i] != '_' &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2011
		    kname[i] != '.') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2012
			kmem_free(kname, ZONENAME_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2013
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2014
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2015
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2016
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2017
	zone->zone_name = kname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2018
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2019
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2020
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2021
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2022
 * Similar to thread_create(), but makes sure the thread is in the appropriate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2023
 * zone's zsched process (curproc->p_zone->zone_zsched) before returning.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2024
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2025
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2026
kthread_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2027
zthread_create(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2028
    caddr_t stk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2029
    size_t stksize,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2030
    void (*proc)(),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2031
    void *arg,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2032
    size_t len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2033
    pri_t pri)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2034
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2035
	kthread_t *t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2036
	zone_t *zone = curproc->p_zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2037
	proc_t *pp = zone->zone_zsched;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2038
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2039
	zone_hold(zone);	/* Reference to be dropped when thread exits */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2040
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2041
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2042
	 * No-one should be trying to create threads if the zone is shutting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2043
	 * down and there aren't any kernel threads around.  See comment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2044
	 * in zthread_exit().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2045
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2046
	ASSERT(!(zone->zone_kthreads == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2047
	    zone_status_get(zone) >= ZONE_IS_EMPTY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2048
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2049
	 * Create a thread, but don't let it run until we've finished setting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2050
	 * things up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2051
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2052
	t = thread_create(stk, stksize, proc, arg, len, pp, TS_STOPPED, pri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2053
	ASSERT(t->t_forw == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2054
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2055
	if (zone->zone_kthreads == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2056
		t->t_forw = t->t_back = t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2057
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2058
		kthread_t *tx = zone->zone_kthreads;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2059
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2060
		t->t_forw = tx;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2061
		t->t_back = tx->t_back;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2062
		tx->t_back->t_forw = t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2063
		tx->t_back = t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2064
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2065
	zone->zone_kthreads = t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2066
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2068
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2069
	t->t_proc_flag |= TP_ZTHREAD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2070
	project_rele(t->t_proj);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2071
	t->t_proj = project_hold(pp->p_task->tk_proj);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2072
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2073
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2074
	 * Setup complete, let it run.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2075
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2076
	thread_lock(t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2077
	t->t_schedflag |= TS_ALLSTART;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2078
	setrun_locked(t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2079
	thread_unlock(t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2081
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2082
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2083
	return (t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2084
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2085
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2086
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2087
 * Similar to thread_exit().  Must be called by threads created via
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2088
 * zthread_exit().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2089
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2090
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2091
zthread_exit(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2092
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2093
	kthread_t *t = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2094
	proc_t *pp = curproc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2095
	zone_t *zone = pp->p_zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2096
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2097
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2098
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2099
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2100
	 * Reparent to p0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2101
	 */
1075
5ef61094f66a 6355953 assertion failed: cpu == CPU, file: ../../i86pc/vm/hat_i86.c, line: 925
josephb
parents: 816
diff changeset
  2102
	kpreempt_disable();
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2103
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2104
	t->t_proc_flag &= ~TP_ZTHREAD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2105
	t->t_procp = &p0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2106
	hat_thread_exit(t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2107
	mutex_exit(&pp->p_lock);
1075
5ef61094f66a 6355953 assertion failed: cpu == CPU, file: ../../i86pc/vm/hat_i86.c, line: 925
josephb
parents: 816
diff changeset
  2108
	kpreempt_enable();
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2109
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2110
	if (t->t_back == t) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2111
		ASSERT(t->t_forw == t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2112
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2113
		 * If the zone is empty, once the thread count
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2114
		 * goes to zero no further kernel threads can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2115
		 * created.  This is because if the creator is a process
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2116
		 * in the zone, then it must have exited before the zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2117
		 * state could be set to ZONE_IS_EMPTY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2118
		 * Otherwise, if the creator is a kernel thread in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2119
		 * zone, the thread count is non-zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2120
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2121
		 * This really means that non-zone kernel threads should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2122
		 * not create zone kernel threads.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2123
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2124
		zone->zone_kthreads = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2125
		if (zone_status_get(zone) == ZONE_IS_EMPTY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2126
			zone_status_set(zone, ZONE_IS_DOWN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2127
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2128
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2129
		t->t_forw->t_back = t->t_back;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2130
		t->t_back->t_forw = t->t_forw;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2131
		if (zone->zone_kthreads == t)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2132
			zone->zone_kthreads = t->t_forw;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2133
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2134
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2135
	zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2136
	thread_exit();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2137
	/* NOTREACHED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2138
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2139
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2140
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2141
zone_chdir(vnode_t *vp, vnode_t **vpp, proc_t *pp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2142
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2143
	vnode_t *oldvp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2144
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2145
	/* we're going to hold a reference here to the directory */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2146
	VN_HOLD(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2147
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2148
#ifdef C2_AUDIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2149
	if (audit_active)	/* update abs cwd/root path see c2audit.c */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2150
		audit_chdirec(vp, vpp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2151
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2153
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2154
	oldvp = *vpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2155
	*vpp = vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2156
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2157
	if (oldvp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2158
		VN_RELE(oldvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2159
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2160
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2161
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2162
 * Convert an rctl value represented by an nvlist_t into an rctl_val_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2163
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2164
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2165
nvlist2rctlval(nvlist_t *nvl, rctl_val_t *rv)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2166
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2167
	nvpair_t *nvp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2168
	boolean_t priv_set = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2169
	boolean_t limit_set = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2170
	boolean_t action_set = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2171
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2172
	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2173
		const char *name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2174
		uint64_t ui64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2175
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2176
		name = nvpair_name(nvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2177
		if (nvpair_type(nvp) != DATA_TYPE_UINT64)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2178
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2179
		(void) nvpair_value_uint64(nvp, &ui64);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2180
		if (strcmp(name, "privilege") == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2181
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2182
			 * Currently only privileged values are allowed, but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2183
			 * this may change in the future.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2184
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2185
			if (ui64 != RCPRIV_PRIVILEGED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2186
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2187
			rv->rcv_privilege = ui64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2188
			priv_set = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2189
		} else if (strcmp(name, "limit") == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2190
			rv->rcv_value = ui64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2191
			limit_set = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2192
		} else if (strcmp(name, "action") == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2193
			if (ui64 != RCTL_LOCAL_NOACTION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2194
			    ui64 != RCTL_LOCAL_DENY)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2195
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2196
			rv->rcv_flagaction = ui64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2197
			action_set = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2198
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2199
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2200
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2201
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2203
	if (!(priv_set && limit_set && action_set))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2204
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2205
	rv->rcv_action_signal = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2206
	rv->rcv_action_recipient = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2207
	rv->rcv_action_recip_pid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2208
	rv->rcv_firing_time = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2210
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2211
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2212
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2213
/*
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2214
 * Non-global zone version of start_init.
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2215
 */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2216
void
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2217
zone_start_init(void)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2218
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2219
	proc_t *p = ttoproc(curthread);
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2220
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2221
	ASSERT(!INGLOBALZONE(curproc));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2223
	/*
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2224
	 * We maintain zone_boot_err so that we can return the cause of the
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2225
	 * failure back to the caller of the zone_boot syscall.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2226
	 */
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2227
	p->p_zone->zone_boot_err = start_init_common();
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2229
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2230
	if (p->p_zone->zone_boot_err != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2231
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2232
		 * Make sure we are still in the booting state-- we could have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2233
		 * raced and already be shutting down, or even further along.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2234
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2235
		if (zone_status_get(p->p_zone) == ZONE_IS_BOOTING)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2236
			zone_status_set(p->p_zone, ZONE_IS_SHUTTING_DOWN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2237
		mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2238
		/* It's gone bad, dispose of the process */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2239
		if (proc_exit(CLD_EXITED, p->p_zone->zone_boot_err) != 0) {
390
ff89f8283e6c 6272865 race condition between SIGKILL and /proc PCAGENT
raf
parents: 0
diff changeset
  2240
			mutex_enter(&p->p_lock);
ff89f8283e6c 6272865 race condition between SIGKILL and /proc PCAGENT
raf
parents: 0
diff changeset
  2241
			ASSERT(p->p_flag & SEXITLWPS);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2242
			lwp_exit();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2243
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2244
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2245
		if (zone_status_get(p->p_zone) == ZONE_IS_BOOTING)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2246
			zone_status_set(p->p_zone, ZONE_IS_RUNNING);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2247
		mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2248
		/* cause the process to return to userland. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2249
		lwp_rtt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2250
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2251
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2253
struct zsched_arg {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2254
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2255
	nvlist_t *nvlist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2256
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2258
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2259
 * Per-zone "sched" workalike.  The similarity to "sched" doesn't have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2260
 * anything to do with scheduling, but rather with the fact that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2261
 * per-zone kernel threads are parented to zsched, just like regular
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2262
 * kernel threads are parented to sched (p0).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2263
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2264
 * zsched is also responsible for launching init for the zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2265
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2266
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2267
zsched(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2268
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2269
	struct zsched_arg *za = arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2270
	proc_t *pp = curproc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2271
	proc_t *initp = proc_init;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2272
	zone_t *zone = za->zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2273
	cred_t *cr, *oldcred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2274
	rctl_set_t *set;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2275
	rctl_alloc_gp_t *gp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2276
	contract_t *ct = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2277
	task_t *tk, *oldtk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2278
	rctl_entity_p_t e;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2279
	kproject_t *pj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2280
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2281
	nvlist_t *nvl = za->nvlist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2282
	nvpair_t *nvp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2283
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2284
	bcopy("zsched", u.u_psargs, sizeof ("zsched"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2285
	bcopy("zsched", u.u_comm, sizeof ("zsched"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2286
	u.u_argc = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2287
	u.u_argv = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2288
	u.u_envp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2289
	closeall(P_FINFO(pp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2291
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2292
	 * We are this zone's "zsched" process.  As the zone isn't generally
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2293
	 * visible yet we don't need to grab any locks before initializing its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2294
	 * zone_proc pointer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2295
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2296
	zone_hold(zone);  /* this hold is released by zone_destroy() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2297
	zone->zone_zsched = pp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2298
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2299
	pp->p_zone = zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2300
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2301
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2302
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2303
	 * Disassociate process from its 'parent'; parent ourselves to init
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2304
	 * (pid 1) and change other values as needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2305
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2306
	sess_create();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2307
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2308
	mutex_enter(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2309
	proc_detach(pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2310
	pp->p_ppid = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2311
	pp->p_flag |= SZONETOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2312
	pp->p_ancpid = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2313
	pp->p_parent = initp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2314
	pp->p_psibling = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2315
	if (initp->p_child)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2316
		initp->p_child->p_psibling = pp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2317
	pp->p_sibling = initp->p_child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2318
	initp->p_child = pp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2320
	/* Decrement what newproc() incremented. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2321
	upcount_dec(crgetruid(CRED()), GLOBAL_ZONEID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2322
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2323
	 * Our credentials are about to become kcred-like, so we don't care
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2324
	 * about the caller's ruid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2325
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2326
	upcount_inc(crgetruid(kcred), zone->zone_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2327
	mutex_exit(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2329
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2330
	 * getting out of global zone, so decrement lwp counts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2331
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2332
	pj = pp->p_task->tk_proj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2333
	mutex_enter(&global_zone->zone_nlwps_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2334
	pj->kpj_nlwps -= pp->p_lwpcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2335
	global_zone->zone_nlwps -= pp->p_lwpcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2336
	mutex_exit(&global_zone->zone_nlwps_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2337
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2338
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2339
	 * Create and join a new task in project '0' of this zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2340
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2341
	 * We don't need to call holdlwps() since we know we're the only lwp in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2342
	 * this process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2343
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2344
	 * task_join() returns with p_lock held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2345
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2346
	tk = task_create(0, zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2347
	mutex_enter(&cpu_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2348
	oldtk = task_join(tk, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2349
	mutex_exit(&curproc->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2350
	mutex_exit(&cpu_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2351
	task_rele(oldtk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2353
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2354
	 * add lwp counts to zsched's zone, and increment project's task count
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2355
	 * due to the task created in the above tasksys_settaskid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2356
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2357
	pj = pp->p_task->tk_proj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2358
	mutex_enter(&zone->zone_nlwps_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2359
	pj->kpj_nlwps += pp->p_lwpcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2360
	pj->kpj_ntasks += 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2361
	zone->zone_nlwps += pp->p_lwpcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2362
	mutex_exit(&zone->zone_nlwps_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2363
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2364
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2365
	 * The process was created by a process in the global zone, hence the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2366
	 * credentials are wrong.  We might as well have kcred-ish credentials.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2367
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2368
	cr = zone->zone_kcred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2369
	crhold(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2370
	mutex_enter(&pp->p_crlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2371
	oldcred = pp->p_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2372
	pp->p_cred = cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2373
	mutex_exit(&pp->p_crlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2374
	crfree(oldcred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2375
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2376
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2377
	 * Hold credentials again (for thread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2378
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2379
	crhold(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2380
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2381
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2382
	 * p_lwpcnt can't change since this is a kernel process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2383
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2384
	crset(pp, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2386
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2387
	 * Chroot
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2388
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2389
	zone_chdir(zone->zone_rootvp, &PTOU(pp)->u_cdir, pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2390
	zone_chdir(zone->zone_rootvp, &PTOU(pp)->u_rdir, pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2391
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2392
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2393
	 * Initialize zone's rctl set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2394
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2395
	set = rctl_set_create();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2396
	gp = rctl_set_init_prealloc(RCENTITY_ZONE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2397
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2398
	e.rcep_p.zone = zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2399
	e.rcep_t = RCENTITY_ZONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2400
	zone->zone_rctls = rctl_set_init(RCENTITY_ZONE, pp, &e, set, gp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2401
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2402
	rctl_prealloc_destroy(gp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2403
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2404
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2405
	 * Apply the rctls passed in to zone_create().  This is basically a list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2406
	 * assignment: all of the old values are removed and the new ones
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2407
	 * inserted.  That is, if an empty list is passed in, all values are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2408
	 * removed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2409
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2410
	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2411
		rctl_dict_entry_t *rde;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2412
		rctl_hndl_t hndl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2413
		char *name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2414
		nvlist_t **nvlarray;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2415
		uint_t i, nelem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2416
		int error;	/* For ASSERT()s */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2417
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2418
		name = nvpair_name(nvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2419
		hndl = rctl_hndl_lookup(name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2420
		ASSERT(hndl != -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2421
		rde = rctl_dict_lookup_hndl(hndl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2422
		ASSERT(rde != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2424
		for (; /* ever */; ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2425
			rctl_val_t oval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2427
			mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2428
			error = rctl_local_get(hndl, NULL, &oval, pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2429
			mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2430
			ASSERT(error == 0);	/* Can't fail for RCTL_FIRST */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2431
			ASSERT(oval.rcv_privilege != RCPRIV_BASIC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2432
			if (oval.rcv_privilege == RCPRIV_SYSTEM)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2433
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2434
			mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2435
			error = rctl_local_delete(hndl, &oval, pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2436
			mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2437
			ASSERT(error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2438
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2439
		error = nvpair_value_nvlist_array(nvp, &nvlarray, &nelem);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2440
		ASSERT(error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2441
		for (i = 0; i < nelem; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2442
			rctl_val_t *nvalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2443
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2444
			nvalp = kmem_cache_alloc(rctl_val_cache, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2445
			error = nvlist2rctlval(nvlarray[i], nvalp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2446
			ASSERT(error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2447
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2448
			 * rctl_local_insert can fail if the value being
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2449
			 * inserted is a duplicate; this is OK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2450
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2451
			mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2452
			if (rctl_local_insert(hndl, nvalp, pp) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2453
				kmem_cache_free(rctl_val_cache, nvalp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2454
			mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2455
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2456
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2457
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2458
	 * Tell the world that we're done setting up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2459
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2460
	 * At this point we want to set the zone status to ZONE_IS_READY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2461
	 * and atomically set the zone's processor set visibility.  Once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2462
	 * we drop pool_lock() this zone will automatically get updated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2463
	 * to reflect any future changes to the pools configuration.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2464
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2465
	pool_lock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2466
	mutex_enter(&cpu_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2467
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2468
	zone_uniqid(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2469
	zone_zsd_configure(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2470
	if (pool_state == POOL_ENABLED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2471
		zone_pset_set(zone, pool_default->pool_pset->pset_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2472
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2473
	ASSERT(zone_status_get(zone) == ZONE_IS_UNINITIALIZED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2474
	zone_status_set(zone, ZONE_IS_READY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2475
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2476
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2477
	mutex_exit(&cpu_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2478
	pool_unlock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2479
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2480
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2481
	 * Once we see the zone transition to the ZONE_IS_BOOTING state,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2482
	 * we launch init, and set the state to running.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2483
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2484
	zone_status_wait_cpr(zone, ZONE_IS_BOOTING, "zsched");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2486
	if (zone_status_get(zone) == ZONE_IS_BOOTING) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2487
		id_t cid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2488
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2489
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2490
		 * Ok, this is a little complicated.  We need to grab the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2491
		 * zone's pool's scheduling class ID; note that by now, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2492
		 * are already bound to a pool if we need to be (zoneadmd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2493
		 * will have done that to us while we're in the READY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2494
		 * state).  *But* the scheduling class for the zone's 'init'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2495
		 * must be explicitly passed to newproc, which doesn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2496
		 * respect pool bindings.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2497
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2498
		 * We hold the pool_lock across the call to newproc() to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2499
		 * close the obvious race: the pool's scheduling class
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2500
		 * could change before we manage to create the LWP with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2501
		 * classid 'cid'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2502
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2503
		pool_lock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2504
		cid = pool_get_class(zone->zone_pool);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2505
		if (cid == -1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2506
			cid = defaultcid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2508
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2509
		 * If this fails, zone_boot will ultimately fail.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2510
		 * state of the zone will be set to SHUTTING_DOWN-- userland
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2511
		 * will have to tear down the zone, and fail, or try again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2512
		 */
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2513
		if ((zone->zone_boot_err = newproc(zone_start_init, NULL, cid,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2514
		    minclsyspri - 1, &ct)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2515
			mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2516
			zone_status_set(zone, ZONE_IS_SHUTTING_DOWN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2517
			mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2518
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2519
		pool_unlock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2520
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2522
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2523
	 * Wait for zone_destroy() to be called.  This is what we spend
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2524
	 * most of our life doing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2525
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2526
	zone_status_wait_cpr(zone, ZONE_IS_DYING, "zsched");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2527
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2528
	if (ct)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2529
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2530
		 * At this point the process contract should be empty.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2531
		 * (Though if it isn't, it's not the end of the world.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2532
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2533
		VERIFY(contract_abandon(ct, curproc, B_TRUE) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2534
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2535
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2536
	 * Allow kcred to be freed when all referring processes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2537
	 * (including this one) go away.  We can't just do this in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2538
	 * zone_free because we need to wait for the zone_cred_ref to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2539
	 * drop to 0 before calling zone_free, and the existence of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2540
	 * zone_kcred will prevent that.  Thus, we call crfree here to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2541
	 * balance the crdup in zone_create.  The crhold calls earlier
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2542
	 * in zsched will be dropped when the thread and process exit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2543
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2544
	crfree(zone->zone_kcred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2545
	zone->zone_kcred = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2546
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2547
	exit(CLD_EXITED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2548
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2550
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2551
 * Helper function to determine if there are any submounts of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2552
 * provided path.  Used to make sure the zone doesn't "inherit" any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2553
 * mounts from before it is created.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2554
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2555
static uint_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2556
zone_mount_count(const char *rootpath)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2557
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2558
	vfs_t *vfsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2559
	uint_t count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2560
	size_t rootpathlen = strlen(rootpath);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2561
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2562
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2563
	 * Holding zonehash_lock prevents race conditions with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2564
	 * vfs_list_add()/vfs_list_remove() since we serialize with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2565
	 * zone_find_by_path().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2566
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2567
	ASSERT(MUTEX_HELD(&zonehash_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2568
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2569
	 * The rootpath must end with a '/'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2570
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2571
	ASSERT(rootpath[rootpathlen - 1] == '/');
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2572
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2573
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2574
	 * This intentionally does not count the rootpath itself if that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2575
	 * happens to be a mount point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2576
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2577
	vfs_list_read_lock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2578
	vfsp = rootvfs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2579
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2580
		if (strncmp(rootpath, refstr_value(vfsp->vfs_mntpt),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2581
		    rootpathlen) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2582
			count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2583
		vfsp = vfsp->vfs_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2584
	} while (vfsp != rootvfs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2585
	vfs_list_unlock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2586
	return (count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2587
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2588
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2589
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2590
 * Helper function to make sure that a zone created on 'rootpath'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2591
 * wouldn't end up containing other zones' rootpaths.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2592
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2593
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2594
zone_is_nested(const char *rootpath)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2595
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2596
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2597
	size_t rootpathlen = strlen(rootpath);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2598
	size_t len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2599
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2600
	ASSERT(MUTEX_HELD(&zonehash_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2602
	for (zone = list_head(&zone_active); zone != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2603
	    zone = list_next(&zone_active, zone)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2604
		if (zone == global_zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2605
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2606
		len = strlen(zone->zone_rootpath);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2607
		if (strncmp(rootpath, zone->zone_rootpath,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2608
		    MIN(rootpathlen, len)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2609
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2610
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2611
	return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2612
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2613
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2614
static int
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  2615
zone_set_privset(zone_t *zone, const priv_set_t *zone_privs,
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  2616
    size_t zone_privssz)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2617
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2618
	priv_set_t *privs = kmem_alloc(sizeof (priv_set_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2619
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  2620
	if (zone_privssz < sizeof (priv_set_t))
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  2621
		return (set_errno(ENOMEM));
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  2622
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2623
	if (copyin(zone_privs, privs, sizeof (priv_set_t))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2624
		kmem_free(privs, sizeof (priv_set_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2625
		return (EFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2626
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2627
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2628
	zone->zone_privset = privs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2629
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2630
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2631
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2632
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2633
 * We make creative use of nvlists to pass in rctls from userland.  The list is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2634
 * a list of the following structures:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2635
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2636
 * (name = rctl_name, value = nvpair_list_array)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2637
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2638
 * Where each element of the nvpair_list_array is of the form:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2639
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2640
 * [(name = "privilege", value = RCPRIV_PRIVILEGED),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2641
 * 	(name = "limit", value = uint64_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2642
 * 	(name = "action", value = (RCTL_LOCAL_NOACTION || RCTL_LOCAL_DENY))]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2643
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2644
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2645
parse_rctls(caddr_t ubuf, size_t buflen, nvlist_t **nvlp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2646
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2647
	nvpair_t *nvp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2648
	nvlist_t *nvl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2649
	char *kbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2650
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2651
	rctl_val_t rv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2652
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2653
	*nvlp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2655
	if (buflen == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2656
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2657
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2658
	if ((kbuf = kmem_alloc(buflen, KM_NOSLEEP)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2659
		return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2660
	if (copyin(ubuf, kbuf, buflen)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2661
		error = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2662
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2663
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2664
	if (nvlist_unpack(kbuf, buflen, &nvl, KM_SLEEP) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2665
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2666
		 * nvl may have been allocated/free'd, but the value set to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2667
		 * non-NULL, so we reset it here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2668
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2669
		nvl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2670
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2671
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2672
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2673
	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2674
		rctl_dict_entry_t *rde;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2675
		rctl_hndl_t hndl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2676
		nvlist_t **nvlarray;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2677
		uint_t i, nelem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2678
		char *name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2680
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2681
		name = nvpair_name(nvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2682
		if (strncmp(nvpair_name(nvp), "zone.", sizeof ("zone.") - 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2683
		    != 0 || nvpair_type(nvp) != DATA_TYPE_NVLIST_ARRAY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2684
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2685
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2686
		if ((hndl = rctl_hndl_lookup(name)) == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2687
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2688
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2689
		rde = rctl_dict_lookup_hndl(hndl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2690
		error = nvpair_value_nvlist_array(nvp, &nvlarray, &nelem);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2691
		ASSERT(error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2692
		for (i = 0; i < nelem; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2693
			if (error = nvlist2rctlval(nvlarray[i], &rv))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2694
				goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2695
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2696
		if (rctl_invalid_value(rde, &rv)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2697
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2698
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2699
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2700
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2701
	error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2702
	*nvlp = nvl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2703
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2704
	kmem_free(kbuf, buflen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2705
	if (error && nvl != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2706
		nvlist_free(nvl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2707
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2708
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2709
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2710
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2711
zone_create_error(int er_error, int er_ext, int *er_out) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2712
	if (er_out != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2713
		if (copyout(&er_ext, er_out, sizeof (int))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2714
			return (set_errno(EFAULT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2715
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2716
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2717
	return (set_errno(er_error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2718
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2719
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2720
static int
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2721
zone_set_label(zone_t *zone, const bslabel_t *lab, uint32_t doi)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2722
{
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2723
	ts_label_t *tsl;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2724
	bslabel_t blab;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2725
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2726
	/* Get label from user */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2727
	if (copyin(lab, &blab, sizeof (blab)) != 0)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2728
		return (EFAULT);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2729
	tsl = labelalloc(&blab, doi, KM_NOSLEEP);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2730
	if (tsl == NULL)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2731
		return (ENOMEM);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2732
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2733
	zone->zone_slabel = tsl;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2734
	return (0);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2735
}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2736
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2737
/*
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2738
 * Parses a comma-separated list of ZFS datasets into a per-zone dictionary.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2739
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2740
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2741
parse_zfs(zone_t *zone, caddr_t ubuf, size_t buflen)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2742
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2743
	char *kbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2744
	char *dataset, *next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2745
	zone_dataset_t *zd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2746
	size_t len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2747
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2748
	if (ubuf == NULL || buflen == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2749
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2750
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2751
	if ((kbuf = kmem_alloc(buflen, KM_NOSLEEP)) == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2752
		return (ENOMEM);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2753
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2754
	if (copyin(ubuf, kbuf, buflen) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2755
		kmem_free(kbuf, buflen);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2756
		return (EFAULT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2757
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2758
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2759
	dataset = next = kbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2760
	for (;;) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2761
		zd = kmem_alloc(sizeof (zone_dataset_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2762
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2763
		next = strchr(dataset, ',');
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2764
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2765
		if (next == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2766
			len = strlen(dataset);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2767
		else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2768
			len = next - dataset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2769
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2770
		zd->zd_dataset = kmem_alloc(len + 1, KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2771
		bcopy(dataset, zd->zd_dataset, len);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2772
		zd->zd_dataset[len] = '\0';
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2773
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2774
		list_insert_head(&zone->zone_datasets, zd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2775
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2776
		if (next == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2777
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2778
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2779
		dataset = next + 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2780
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2781
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2782
	kmem_free(kbuf, buflen);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2783
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2784
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2785
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2786
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2787
 * System call to create/initialize a new zone named 'zone_name', rooted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2788
 * at 'zone_root', with a zone-wide privilege limit set of 'zone_privs',
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2789
 * and initialized with the zone-wide rctls described in 'rctlbuf', and
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2790
 * with labeling set by 'match', 'doi', and 'label'.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2791
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2792
 * If extended error is non-null, we may use it to return more detailed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2793
 * error information.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2794
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2795
static zoneid_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2796
zone_create(const char *zone_name, const char *zone_root,
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  2797
    const priv_set_t *zone_privs, size_t zone_privssz,
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  2798
    caddr_t rctlbuf, size_t rctlbufsz,
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2799
    caddr_t zfsbuf, size_t zfsbufsz, int *extended_error,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2800
    int match, uint32_t doi, const bslabel_t *label)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2801
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2802
	struct zsched_arg zarg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2803
	nvlist_t *rctls = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2804
	proc_t *pp = curproc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2805
	zone_t *zone, *ztmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2806
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2807
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2808
	int error2 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2809
	char *str;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2810
	cred_t *zkcr;
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  2811
	boolean_t insert_label_hash;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2812
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2813
	if (secpolicy_zone_config(CRED()) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2814
		return (set_errno(EPERM));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2815
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2816
	/* can't boot zone from within chroot environment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2817
	if (PTOU(pp)->u_rdir != NULL && PTOU(pp)->u_rdir != rootdir)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2818
		return (zone_create_error(ENOTSUP, ZE_CHROOTED,
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  2819
		    extended_error));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2820
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2821
	zone = kmem_zalloc(sizeof (zone_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2822
	zoneid = zone->zone_id = id_alloc(zoneid_space);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2823
	zone->zone_status = ZONE_IS_UNINITIALIZED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2824
	zone->zone_pool = pool_default;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2825
	zone->zone_pool_mod = gethrtime();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2826
	zone->zone_psetid = ZONE_PS_INVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2827
	zone->zone_ncpus = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2828
	zone->zone_ncpus_online = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2829
	mutex_init(&zone->zone_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2830
	mutex_init(&zone->zone_nlwps_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2831
	cv_init(&zone->zone_cv, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2832
	list_create(&zone->zone_zsd, sizeof (struct zsd_entry),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2833
	    offsetof(struct zsd_entry, zsd_linkage));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2834
	list_create(&zone->zone_datasets, sizeof (zone_dataset_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2835
	    offsetof(zone_dataset_t, zd_linkage));
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2836
	rw_init(&zone->zone_mlps.mlpl_rwlock, NULL, RW_DEFAULT, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2838
	if ((error = zone_set_name(zone, zone_name)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2839
		zone_free(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2840
		return (zone_create_error(error, 0, extended_error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2841
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2843
	if ((error = zone_set_root(zone, zone_root)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2844
		zone_free(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2845
		return (zone_create_error(error, 0, extended_error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2846
	}
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  2847
	if ((error = zone_set_privset(zone, zone_privs, zone_privssz)) != 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2848
		zone_free(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2849
		return (zone_create_error(error, 0, extended_error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2850
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2851
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2852
	/* initialize node name to be the same as zone name */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2853
	zone->zone_nodename = kmem_alloc(_SYS_NMLN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2854
	(void) strncpy(zone->zone_nodename, zone->zone_name, _SYS_NMLN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2855
	zone->zone_nodename[_SYS_NMLN - 1] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2857
	zone->zone_domain = kmem_alloc(_SYS_NMLN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2858
	zone->zone_domain[0] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2859
	zone->zone_shares = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2860
	zone->zone_bootargs = NULL;
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2861
	zone->zone_initname =
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2862
	    kmem_alloc(strlen(zone_default_initname) + 1, KM_SLEEP);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  2863
	(void) strcpy(zone->zone_initname, zone_default_initname);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2864
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2865
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2866
	 * Zsched initializes the rctls.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2867
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2868
	zone->zone_rctls = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2869
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2870
	if ((error = parse_rctls(rctlbuf, rctlbufsz, &rctls)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2871
		zone_free(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2872
		return (zone_create_error(error, 0, extended_error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2873
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2874
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2875
	if ((error = parse_zfs(zone, zfsbuf, zfsbufsz)) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2876
		zone_free(zone);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2877
		return (set_errno(error));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2878
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  2879
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2880
	/*
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2881
	 * Read in the trusted system parameters:
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2882
	 * match flag and sensitivity label.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2883
	 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2884
	zone->zone_match = match;
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  2885
	if (is_system_labeled() && !(zone->zone_flags & ZF_IS_SCRATCH)) {
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2886
		error = zone_set_label(zone, label, doi);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2887
		if (error != 0) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2888
			zone_free(zone);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2889
			return (set_errno(error));
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2890
		}
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  2891
		insert_label_hash = B_TRUE;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2892
	} else {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2893
		/* all zones get an admin_low label if system is not labeled */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2894
		zone->zone_slabel = l_admin_low;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2895
		label_hold(l_admin_low);
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  2896
		insert_label_hash = B_FALSE;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2897
	}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2898
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2899
	/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2900
	 * Stop all lwps since that's what normally happens as part of fork().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2901
	 * This needs to happen before we grab any locks to avoid deadlock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2902
	 * (another lwp in the process could be waiting for the held lock).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2903
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2904
	if (curthread != pp->p_agenttp && !holdlwps(SHOLDFORK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2905
		zone_free(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2906
		if (rctls)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2907
			nvlist_free(rctls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2908
		return (zone_create_error(error, 0, extended_error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2909
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2911
	if (block_mounts() == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2912
		mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2913
		if (curthread != pp->p_agenttp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2914
			continuelwps(pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2915
		mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2916
		zone_free(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2917
		if (rctls)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2918
			nvlist_free(rctls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2919
		return (zone_create_error(error, 0, extended_error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2920
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2922
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2923
	 * Set up credential for kernel access.  After this, any errors
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2924
	 * should go through the dance in errout rather than calling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2925
	 * zone_free directly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2926
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2927
	zone->zone_kcred = crdup(kcred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2928
	crsetzone(zone->zone_kcred, zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2929
	priv_intersect(zone->zone_privset, &CR_PPRIV(zone->zone_kcred));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2930
	priv_intersect(zone->zone_privset, &CR_EPRIV(zone->zone_kcred));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2931
	priv_intersect(zone->zone_privset, &CR_IPRIV(zone->zone_kcred));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2932
	priv_intersect(zone->zone_privset, &CR_LPRIV(zone->zone_kcred));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2933
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2934
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2935
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2936
	 * Make sure zone doesn't already exist.
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2937
	 *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2938
	 * If the system and zone are labeled,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2939
	 * make sure no other zone exists that has the same label.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2940
	 */
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2941
	if ((ztmp = zone_find_all_by_name(zone->zone_name)) != NULL ||
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  2942
	    (insert_label_hash &&
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2943
	    (ztmp = zone_find_all_by_label(zone->zone_slabel)) != NULL)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2944
		zone_status_t status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2945
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2946
		status = zone_status_get(ztmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2947
		if (status == ZONE_IS_READY || status == ZONE_IS_RUNNING)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2948
			error = EEXIST;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2949
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2950
			error = EBUSY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2951
		goto errout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2952
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2953
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2954
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2955
	 * Don't allow zone creations which would cause one zone's rootpath to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2956
	 * be accessible from that of another (non-global) zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2957
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2958
	if (zone_is_nested(zone->zone_rootpath)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2959
		error = EBUSY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2960
		goto errout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2961
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2962
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2963
	ASSERT(zonecount != 0);		/* check for leaks */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2964
	if (zonecount + 1 > maxzones) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2965
		error = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2966
		goto errout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2967
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2968
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2969
	if (zone_mount_count(zone->zone_rootpath) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2970
		error = EBUSY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2971
		error2 = ZE_AREMOUNTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2972
		goto errout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2973
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2974
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2975
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2976
	 * Zone is still incomplete, but we need to drop all locks while
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2977
	 * zsched() initializes this zone's kernel process.  We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2978
	 * optimistically add the zone to the hashtable and associated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2979
	 * lists so a parallel zone_create() doesn't try to create the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2980
	 * same zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2981
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2982
	zonecount++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2983
	(void) mod_hash_insert(zonehashbyid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2984
	    (mod_hash_key_t)(uintptr_t)zone->zone_id,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2985
	    (mod_hash_val_t)(uintptr_t)zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2986
	str = kmem_alloc(strlen(zone->zone_name) + 1, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2987
	(void) strcpy(str, zone->zone_name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2988
	(void) mod_hash_insert(zonehashbyname, (mod_hash_key_t)str,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2989
	    (mod_hash_val_t)(uintptr_t)zone);
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  2990
	if (insert_label_hash) {
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2991
		(void) mod_hash_insert(zonehashbylabel,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2992
		    (mod_hash_key_t)zone->zone_slabel, (mod_hash_val_t)zone);
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  2993
		zone->zone_flags |= ZF_HASHED_LABEL;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2994
	}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  2995
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2996
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2997
	 * Insert into active list.  At this point there are no 'hold's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2998
	 * on the zone, but everyone else knows not to use it, so we can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2999
	 * continue to use it.  zsched() will do a zone_hold() if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3000
	 * newproc() is successful.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3001
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3002
	list_insert_tail(&zone_active, zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3003
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3004
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3005
	zarg.zone = zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3006
	zarg.nvlist = rctls;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3007
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3008
	 * The process, task, and project rctls are probably wrong;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3009
	 * we need an interface to get the default values of all rctls,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3010
	 * and initialize zsched appropriately.  I'm not sure that that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3011
	 * makes much of a difference, though.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3012
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3013
	if (error = newproc(zsched, (void *)&zarg, syscid, minclsyspri, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3014
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3015
		 * We need to undo all globally visible state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3016
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3017
		mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3018
		list_remove(&zone_active, zone);
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  3019
		if (zone->zone_flags & ZF_HASHED_LABEL) {
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3020
			ASSERT(zone->zone_slabel != NULL);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3021
			(void) mod_hash_destroy(zonehashbylabel,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3022
			    (mod_hash_key_t)zone->zone_slabel);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3023
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3024
		(void) mod_hash_destroy(zonehashbyname,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3025
		    (mod_hash_key_t)(uintptr_t)zone->zone_name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3026
		(void) mod_hash_destroy(zonehashbyid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3027
		    (mod_hash_key_t)(uintptr_t)zone->zone_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3028
		ASSERT(zonecount > 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3029
		zonecount--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3030
		goto errout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3031
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3032
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3033
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3034
	 * Zone creation can't fail from now on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3035
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3036
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3037
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3038
	 * Let the other lwps continue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3039
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3040
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3041
	if (curthread != pp->p_agenttp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3042
		continuelwps(pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3043
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3045
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3046
	 * Wait for zsched to finish initializing the zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3047
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3048
	zone_status_wait(zone, ZONE_IS_READY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3049
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3050
	 * The zone is fully visible, so we can let mounts progress.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3051
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3052
	resume_mounts();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3053
	if (rctls)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3054
		nvlist_free(rctls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3055
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3056
	return (zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3057
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3058
errout:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3059
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3060
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3061
	 * Let the other lwps continue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3062
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3063
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3064
	if (curthread != pp->p_agenttp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3065
		continuelwps(pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3066
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3068
	resume_mounts();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3069
	if (rctls)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3070
		nvlist_free(rctls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3071
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3072
	 * There is currently one reference to the zone, a cred_ref from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3073
	 * zone_kcred.  To free the zone, we call crfree, which will call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3074
	 * zone_cred_rele, which will call zone_free.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3075
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3076
	ASSERT(zone->zone_cred_ref == 1);	/* for zone_kcred */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3077
	ASSERT(zone->zone_kcred->cr_ref == 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3078
	ASSERT(zone->zone_ref == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3079
	zkcr = zone->zone_kcred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3080
	zone->zone_kcred = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3081
	crfree(zkcr);				/* triggers call to zone_free */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3082
	return (zone_create_error(error, error2, extended_error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3083
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3084
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3085
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3086
 * Cause the zone to boot.  This is pretty simple, since we let zoneadmd do
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3087
 * the heavy lifting.  initname is the path to the program to launch
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3088
 * at the "top" of the zone; if this is NULL, we use the system default,
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3089
 * which is stored at zone_default_initname.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3090
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3091
static int
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3092
zone_boot(zoneid_t zoneid)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3093
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3094
	int err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3095
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3096
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3097
	if (secpolicy_zone_config(CRED()) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3098
		return (set_errno(EPERM));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3099
	if (zoneid < MIN_USERZONEID || zoneid > MAX_ZONEID)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3100
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3102
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3103
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3104
	 * Look for zone under hash lock to prevent races with calls to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3105
	 * zone_shutdown, zone_destroy, etc.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3106
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3107
	if ((zone = zone_find_all_by_id(zoneid)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3108
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3109
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3110
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3112
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3113
	if (zone_status_get(zone) != ZONE_IS_READY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3114
		mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3115
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3116
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3117
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3118
	zone_status_set(zone, ZONE_IS_BOOTING);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3119
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3120
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3121
	zone_hold(zone);	/* so we can use the zone_t later */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3122
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3123
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3124
	if (zone_status_wait_sig(zone, ZONE_IS_RUNNING) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3125
		zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3126
		return (set_errno(EINTR));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3127
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3128
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3129
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3130
	 * Boot (starting init) might have failed, in which case the zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3131
	 * will go to the SHUTTING_DOWN state; an appropriate errno will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3132
	 * be placed in zone->zone_boot_err, and so we return that.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3133
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3134
	err = zone->zone_boot_err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3135
	zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3136
	return (err ? set_errno(err) : 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3137
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3138
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3139
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3140
 * Kills all user processes in the zone, waiting for them all to exit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3141
 * before returning.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3142
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3143
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3144
zone_empty(zone_t *zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3145
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3146
	int waitstatus;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3147
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3148
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3149
	 * We need to drop zonehash_lock before killing all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3150
	 * processes, otherwise we'll deadlock with zone_find_*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3151
	 * which can be called from the exit path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3152
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3153
	ASSERT(MUTEX_NOT_HELD(&zonehash_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3154
	while ((waitstatus = zone_status_timedwait_sig(zone, lbolt + hz,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3155
	    ZONE_IS_EMPTY)) == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3156
		killall(zone->zone_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3157
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3158
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3159
	 * return EINTR if we were signaled
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3160
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3161
	if (waitstatus == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3162
		return (EINTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3163
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3164
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3165
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3166
/*
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3167
 * This function implements the policy for zone visibility.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3168
 *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3169
 * In standard Solaris, a non-global zone can only see itself.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3170
 *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3171
 * In Trusted Extensions, a labeled zone can lookup any zone whose label
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3172
 * it dominates. For this test, the label of the global zone is treated as
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3173
 * admin_high so it is special-cased instead of being checked for dominance.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3174
 *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3175
 * Returns true if zone attributes are viewable, false otherwise.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3176
 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3177
static boolean_t
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3178
zone_list_access(zone_t *zone)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3179
{
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3180
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3181
	if (curproc->p_zone == global_zone ||
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3182
	    curproc->p_zone == zone) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3183
		return (B_TRUE);
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  3184
	} else if (is_system_labeled() && !(zone->zone_flags & ZF_IS_SCRATCH)) {
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3185
		bslabel_t *curproc_label;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3186
		bslabel_t *zone_label;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3187
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3188
		curproc_label = label2bslabel(curproc->p_zone->zone_slabel);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3189
		zone_label = label2bslabel(zone->zone_slabel);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3190
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3191
		if (zone->zone_id != GLOBAL_ZONEID &&
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3192
		    bldominates(curproc_label, zone_label)) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3193
			return (B_TRUE);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3194
		} else {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3195
			return (B_FALSE);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3196
		}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3197
	} else {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3198
		return (B_FALSE);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3199
	}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3200
}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3201
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3202
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3203
 * Systemcall to start the zone's halt sequence.  By the time this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3204
 * function successfully returns, all user processes and kernel threads
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3205
 * executing in it will have exited, ZSD shutdown callbacks executed,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3206
 * and the zone status set to ZONE_IS_DOWN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3207
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3208
 * It is possible that the call will interrupt itself if the caller is the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3209
 * parent of any process running in the zone, and doesn't have SIGCHLD blocked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3210
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3211
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3212
zone_shutdown(zoneid_t zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3213
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3214
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3215
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3216
	zone_status_t status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3217
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3218
	if (secpolicy_zone_config(CRED()) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3219
		return (set_errno(EPERM));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3220
	if (zoneid < MIN_USERZONEID || zoneid > MAX_ZONEID)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3221
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3223
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3224
	 * Block mounts so that VFS_MOUNT() can get an accurate view of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3225
	 * the zone's status with regards to ZONE_IS_SHUTTING down.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3226
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3227
	 * e.g. NFS can fail the mount if it determines that the zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3228
	 * has already begun the shutdown sequence.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3229
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3230
	if (block_mounts() == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3231
		return (set_errno(EINTR));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3232
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3233
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3234
	 * Look for zone under hash lock to prevent races with other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3235
	 * calls to zone_shutdown and zone_destroy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3236
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3237
	if ((zone = zone_find_all_by_id(zoneid)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3238
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3239
		resume_mounts();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3240
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3241
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3242
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3243
	status = zone_status_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3244
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3245
	 * Fail if the zone isn't fully initialized yet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3246
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3247
	if (status < ZONE_IS_READY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3248
		mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3249
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3250
		resume_mounts();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3251
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3252
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3253
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3254
	 * If conditions required for zone_shutdown() to return have been met,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3255
	 * return success.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3256
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3257
	if (status >= ZONE_IS_DOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3258
		mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3259
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3260
		resume_mounts();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3261
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3262
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3263
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3264
	 * If zone_shutdown() hasn't been called before, go through the motions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3265
	 * If it has, there's nothing to do but wait for the kernel threads to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3266
	 * drain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3267
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3268
	if (status < ZONE_IS_EMPTY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3269
		uint_t ntasks;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3270
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3271
		mutex_enter(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3272
		if ((ntasks = zone->zone_ntasks) != 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3273
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3274
			 * There's still stuff running.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3275
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3276
			zone_status_set(zone, ZONE_IS_SHUTTING_DOWN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3277
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3278
		mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3279
		if (ntasks == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3280
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3281
			 * The only way to create another task is through
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3282
			 * zone_enter(), which will block until we drop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3283
			 * zonehash_lock.  The zone is empty.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3284
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3285
			if (zone->zone_kthreads == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3286
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3287
				 * Skip ahead to ZONE_IS_DOWN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3288
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3289
				zone_status_set(zone, ZONE_IS_DOWN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3290
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3291
				zone_status_set(zone, ZONE_IS_EMPTY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3292
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3293
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3294
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3295
	zone_hold(zone);	/* so we can use the zone_t later */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3296
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3297
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3298
	resume_mounts();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3299
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3300
	if (error = zone_empty(zone)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3301
		zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3302
		return (set_errno(error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3303
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3304
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3305
	 * After the zone status goes to ZONE_IS_DOWN this zone will no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3306
	 * longer be notified of changes to the pools configuration, so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3307
	 * in order to not end up with a stale pool pointer, we point
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3308
	 * ourselves at the default pool and remove all resource
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3309
	 * visibility.  This is especially important as the zone_t may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3310
	 * languish on the deathrow for a very long time waiting for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3311
	 * cred's to drain out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3312
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3313
	 * This rebinding of the zone can happen multiple times
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3314
	 * (presumably due to interrupted or parallel systemcalls)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3315
	 * without any adverse effects.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3316
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3317
	if (pool_lock_intr() != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3318
		zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3319
		return (set_errno(EINTR));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3320
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3321
	if (pool_state == POOL_ENABLED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3322
		mutex_enter(&cpu_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3323
		zone_pool_set(zone, pool_default);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3324
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3325
		 * The zone no longer needs to be able to see any cpus.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3326
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3327
		zone_pset_set(zone, ZONE_PS_INVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3328
		mutex_exit(&cpu_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3329
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3330
	pool_unlock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3331
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3332
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3333
	 * ZSD shutdown callbacks can be executed multiple times, hence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3334
	 * it is safe to not be holding any locks across this call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3335
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3336
	zone_zsd_callbacks(zone, ZSD_SHUTDOWN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3337
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3338
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3339
	if (zone->zone_kthreads == NULL && zone_status_get(zone) < ZONE_IS_DOWN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3340
		zone_status_set(zone, ZONE_IS_DOWN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3341
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3342
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3343
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3344
	 * Wait for kernel threads to drain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3345
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3346
	if (!zone_status_wait_sig(zone, ZONE_IS_DOWN)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3347
		zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3348
		return (set_errno(EINTR));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3349
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3350
	zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3351
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3352
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3353
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3354
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3355
 * Systemcall entry point to finalize the zone halt process.  The caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3356
 * must have already successfully callefd zone_shutdown().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3357
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3358
 * Upon successful completion, the zone will have been fully destroyed:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3359
 * zsched will have exited, destructor callbacks executed, and the zone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3360
 * removed from the list of active zones.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3361
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3362
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3363
zone_destroy(zoneid_t zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3364
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3365
	uint64_t uniqid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3366
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3367
	zone_status_t status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3368
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3369
	if (secpolicy_zone_config(CRED()) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3370
		return (set_errno(EPERM));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3371
	if (zoneid < MIN_USERZONEID || zoneid > MAX_ZONEID)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3372
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3374
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3375
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3376
	 * Look for zone under hash lock to prevent races with other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3377
	 * calls to zone_destroy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3378
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3379
	if ((zone = zone_find_all_by_id(zoneid)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3380
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3381
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3382
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3384
	if (zone_mount_count(zone->zone_rootpath) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3385
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3386
		return (set_errno(EBUSY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3387
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3388
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3389
	status = zone_status_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3390
	if (status < ZONE_IS_DOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3391
		mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3392
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3393
		return (set_errno(EBUSY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3394
	} else if (status == ZONE_IS_DOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3395
		zone_status_set(zone, ZONE_IS_DYING); /* Tell zsched to exit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3396
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3397
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3398
	zone_hold(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3399
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3401
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3402
	 * wait for zsched to exit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3403
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3404
	zone_status_wait(zone, ZONE_IS_DEAD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3405
	zone_zsd_callbacks(zone, ZSD_DESTROY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3406
	uniqid = zone->zone_uniqid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3407
	zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3408
	zone = NULL;	/* potentially free'd */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3410
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3411
	for (; /* ever */; ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3412
		boolean_t unref;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3413
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3414
		if ((zone = zone_find_all_by_id(zoneid)) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3415
		    zone->zone_uniqid != uniqid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3416
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3417
			 * The zone has gone away.  Necessary conditions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3418
			 * are met, so we return success.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3419
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3420
			mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3421
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3422
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3423
		mutex_enter(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3424
		unref = ZONE_IS_UNREF(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3425
		mutex_exit(&zone->zone_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3426
		if (unref) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3427
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3428
			 * There is only one reference to the zone -- that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3429
			 * added when the zone was added to the hashtables --
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3430
			 * and things will remain this way until we drop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3431
			 * zonehash_lock... we can go ahead and cleanup the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3432
			 * zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3433
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3434
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3435
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3437
		if (cv_wait_sig(&zone_destroy_cv, &zonehash_lock) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3438
			/* Signaled */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3439
			mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3440
			return (set_errno(EINTR));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3441
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3443
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3444
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3445
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3446
	 * It is now safe to let the zone be recreated; remove it from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3447
	 * lists.  The memory will not be freed until the last cred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3448
	 * reference goes away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3449
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3450
	ASSERT(zonecount > 1);	/* must be > 1; can't destroy global zone */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3451
	zonecount--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3452
	/* remove from active list and hash tables */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3453
	list_remove(&zone_active, zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3454
	(void) mod_hash_destroy(zonehashbyname,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3455
	    (mod_hash_key_t)zone->zone_name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3456
	(void) mod_hash_destroy(zonehashbyid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3457
	    (mod_hash_key_t)(uintptr_t)zone->zone_id);
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  3458
	if (zone->zone_flags & ZF_HASHED_LABEL)
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3459
		(void) mod_hash_destroy(zonehashbylabel,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3460
		    (mod_hash_key_t)zone->zone_slabel);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3461
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3462
766
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 390
diff changeset
  3463
	/*
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 390
diff changeset
  3464
	 * Release the root vnode; we're not using it anymore.  Nor should any
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 390
diff changeset
  3465
	 * other thread that might access it exist.
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 390
diff changeset
  3466
	 */
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 390
diff changeset
  3467
	if (zone->zone_rootvp != NULL) {
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 390
diff changeset
  3468
		VN_RELE(zone->zone_rootvp);
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 390
diff changeset
  3469
		zone->zone_rootvp = NULL;
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 390
diff changeset
  3470
	}
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 390
diff changeset
  3471
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3472
	/* add to deathrow list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3473
	mutex_enter(&zone_deathrow_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3474
	list_insert_tail(&zone_deathrow, zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3475
	mutex_exit(&zone_deathrow_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3476
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3477
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3478
	 * Drop last reference (which was added by zsched()), this will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3479
	 * free the zone unless there are outstanding cred references.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3480
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3481
	zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3482
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3483
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3484
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3485
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3486
 * Systemcall entry point for zone_getattr(2).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3487
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3488
static ssize_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3489
zone_getattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3490
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3491
	size_t size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3492
	int error = 0, err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3493
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3494
	char *zonepath;
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3495
	char *outstr;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3496
	zone_status_t zone_status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3497
	pid_t initpid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3498
	boolean_t global = (curproc->p_zone == global_zone);
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3499
	boolean_t curzone = (curproc->p_zone->zone_id == zoneid);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3500
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3501
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3502
	if ((zone = zone_find_all_by_id(zoneid)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3503
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3504
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3505
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3506
	zone_status = zone_status_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3507
	if (zone_status < ZONE_IS_READY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3508
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3509
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3510
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3511
	zone_hold(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3512
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3513
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3514
	/*
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3515
	 * If not in the global zone, don't show information about other zones,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3516
	 * unless the system is labeled and the local zone's label dominates
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3517
	 * the other zone.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3518
	 */
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3519
	if (!zone_list_access(zone)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3520
		zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3521
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3522
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3524
	switch (attr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3525
	case ZONE_ATTR_ROOT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3526
		if (global) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3527
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3528
			 * Copy the path to trim the trailing "/" (except for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3529
			 * the global zone).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3530
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3531
			if (zone != global_zone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3532
				size = zone->zone_rootpathlen - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3533
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3534
				size = zone->zone_rootpathlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3535
			zonepath = kmem_alloc(size, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3536
			bcopy(zone->zone_rootpath, zonepath, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3537
			zonepath[size - 1] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3538
		} else {
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3539
			if (curzone || !is_system_labeled()) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3540
				/*
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3541
				 * Caller is not in the global zone.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3542
				 * if the query is on the current zone
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3543
				 * or the system is not labeled,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3544
				 * just return faked-up path for current zone.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3545
				 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3546
				zonepath = "/";
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3547
				size = 2;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3548
			} else {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3549
				/*
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3550
				 * Return related path for current zone.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3551
				 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3552
				int prefix_len = strlen(zone_prefix);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3553
				int zname_len = strlen(zone->zone_name);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3554
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3555
				size = prefix_len + zname_len + 1;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3556
				zonepath = kmem_alloc(size, KM_SLEEP);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3557
				bcopy(zone_prefix, zonepath, prefix_len);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3558
				bcopy(zone->zone_name, zonepath +
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3559
				    prefix_len, zname_len);
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3560
				zonepath[size - 1] = '\0';
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3561
			}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3562
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3563
		if (bufsize > size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3564
			bufsize = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3565
		if (buf != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3566
			err = copyoutstr(zonepath, buf, bufsize, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3567
			if (err != 0 && err != ENAMETOOLONG)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3568
				error = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3569
		}
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3570
		if (global || (is_system_labeled() && !curzone))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3571
			kmem_free(zonepath, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3572
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3573
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3574
	case ZONE_ATTR_NAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3575
		size = strlen(zone->zone_name) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3576
		if (bufsize > size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3577
			bufsize = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3578
		if (buf != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3579
			err = copyoutstr(zone->zone_name, buf, bufsize, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3580
			if (err != 0 && err != ENAMETOOLONG)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3581
				error = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3582
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3583
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3584
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3585
	case ZONE_ATTR_STATUS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3586
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3587
		 * Since we're not holding zonehash_lock, the zone status
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3588
		 * may be anything; leave it up to userland to sort it out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3589
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3590
		size = sizeof (zone_status);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3591
		if (bufsize > size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3592
			bufsize = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3593
		zone_status = zone_status_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3594
		if (buf != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3595
		    copyout(&zone_status, buf, bufsize) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3596
			error = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3597
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3598
	case ZONE_ATTR_PRIVSET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3599
		size = sizeof (priv_set_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3600
		if (bufsize > size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3601
			bufsize = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3602
		if (buf != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3603
		    copyout(zone->zone_privset, buf, bufsize) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3604
			error = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3605
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3606
	case ZONE_ATTR_UNIQID:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3607
		size = sizeof (zone->zone_uniqid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3608
		if (bufsize > size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3609
			bufsize = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3610
		if (buf != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3611
		    copyout(&zone->zone_uniqid, buf, bufsize) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3612
			error = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3613
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3614
	case ZONE_ATTR_POOLID:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3615
		{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3616
			pool_t *pool;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3617
			poolid_t poolid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3618
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3619
			if (pool_lock_intr() != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3620
				error = EINTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3621
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3622
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3623
			pool = zone_pool_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3624
			poolid = pool->pool_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3625
			pool_unlock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3626
			size = sizeof (poolid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3627
			if (bufsize > size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3628
				bufsize = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3629
			if (buf != NULL && copyout(&poolid, buf, size) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3630
				error = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3631
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3632
		break;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3633
	case ZONE_ATTR_SLBL:
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3634
		size = sizeof (bslabel_t);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3635
		if (bufsize > size)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3636
			bufsize = size;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3637
		if (zone->zone_slabel == NULL)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3638
			error = EINVAL;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3639
		else if (buf != NULL &&
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3640
		    copyout(label2bslabel(zone->zone_slabel), buf,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3641
		    bufsize) != 0)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3642
			error = EFAULT;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  3643
		break;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3644
	case ZONE_ATTR_INITPID:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3645
		size = sizeof (initpid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3646
		if (bufsize > size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3647
			bufsize = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3648
		initpid = zone->zone_proc_initpid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3649
		if (initpid == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3650
			error = ESRCH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3651
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3652
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3653
		if (buf != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3654
		    copyout(&initpid, buf, bufsize) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3655
			error = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3656
		break;
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3657
	case ZONE_ATTR_INITNAME:
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3658
		size = strlen(zone->zone_initname) + 1;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3659
		if (bufsize > size)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3660
			bufsize = size;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3661
		if (buf != NULL) {
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3662
			err = copyoutstr(zone->zone_initname, buf, bufsize,
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3663
			    NULL);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3664
			if (err != 0 && err != ENAMETOOLONG)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3665
				error = EFAULT;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3666
		}
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3667
		break;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3668
	case ZONE_ATTR_BOOTARGS:
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3669
		if (zone->zone_bootargs == NULL)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3670
			outstr = "";
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3671
		else
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3672
			outstr = zone->zone_bootargs;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3673
		size = strlen(outstr) + 1;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3674
		if (bufsize > size)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3675
			bufsize = size;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3676
		if (buf != NULL) {
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3677
			err = copyoutstr(outstr, buf, bufsize, NULL);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3678
			if (err != 0 && err != ENAMETOOLONG)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3679
				error = EFAULT;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3680
		}
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3681
		break;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3682
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3683
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3684
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3685
	zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3687
	if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3688
		return (set_errno(error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3689
	return ((ssize_t)size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3690
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3692
/*
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3693
 * Systemcall entry point for zone_setattr(2).
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3694
 */
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3695
/*ARGSUSED*/
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3696
static int
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3697
zone_setattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3698
{
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3699
	zone_t *zone;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3700
	zone_status_t zone_status;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3701
	int err;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3702
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3703
	if (secpolicy_zone_config(CRED()) != 0)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3704
		return (set_errno(EPERM));
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3705
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3706
	/*
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3707
	 * At present, attributes can only be set on non-running,
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3708
	 * non-global zones.
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3709
	 */
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3710
	if (zoneid == GLOBAL_ZONEID) {
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3711
		return (set_errno(EINVAL));
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3712
	}
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3713
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3714
	mutex_enter(&zonehash_lock);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3715
	if ((zone = zone_find_all_by_id(zoneid)) == NULL) {
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3716
		mutex_exit(&zonehash_lock);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3717
		return (set_errno(EINVAL));
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3718
	}
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3719
	zone_hold(zone);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3720
	mutex_exit(&zonehash_lock);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3721
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3722
	zone_status = zone_status_get(zone);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3723
	if (zone_status > ZONE_IS_READY)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3724
		goto done;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3725
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3726
	switch (attr) {
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3727
	case ZONE_ATTR_INITNAME:
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3728
		err = zone_set_initname(zone, (const char *)buf);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3729
		break;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3730
	case ZONE_ATTR_BOOTARGS:
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3731
		err = zone_set_bootargs(zone, (const char *)buf);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3732
		break;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3733
	default:
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3734
		err = EINVAL;
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3735
	}
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3736
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3737
done:
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3738
	zone_rele(zone);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3739
	return (err != 0 ? set_errno(err) : 0);
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3740
}
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3741
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  3742
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3743
 * Return zero if the process has at least one vnode mapped in to its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3744
 * address space which shouldn't be allowed to change zones.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3745
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3746
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3747
as_can_change_zones(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3748
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3749
	proc_t *pp = curproc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3750
	struct seg *seg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3751
	struct as *as = pp->p_as;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3752
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3753
	int allow = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3754
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3755
	ASSERT(pp->p_as != &kas);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3756
	AS_LOCK_ENTER(&as, &as->a_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3757
	for (seg = AS_SEGFIRST(as); seg != NULL; seg = AS_SEGNEXT(as, seg)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3758
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3759
		 * if we can't get a backing vnode for this segment then skip
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3760
		 * it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3761
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3762
		vp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3763
		if (SEGOP_GETVP(seg, seg->s_base, &vp) != 0 || vp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3764
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3765
		if (!vn_can_change_zones(vp)) { /* bail on first match */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3766
			allow = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3767
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3768
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3769
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3770
	AS_LOCK_EXIT(&as, &as->a_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3771
	return (allow);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3772
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3774
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3775
 * Systemcall entry point for zone_enter().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3776
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3777
 * The current process is injected into said zone.  In the process
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3778
 * it will change its project membership, privileges, rootdir/cwd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3779
 * zone-wide rctls, and pool association to match those of the zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3780
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3781
 * The first zone_enter() called while the zone is in the ZONE_IS_READY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3782
 * state will transition it to ZONE_IS_RUNNING.  Processes may only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3783
 * enter a zone that is "ready" or "running".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3784
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3785
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3786
zone_enter(zoneid_t zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3787
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3788
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3789
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3790
	proc_t *pp = curproc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3791
	contract_t *ct;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3792
	cont_process_t *ctp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3793
	task_t *tk, *oldtk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3794
	kproject_t *zone_proj0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3795
	cred_t *cr, *newcr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3796
	pool_t *oldpool, *newpool;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3797
	sess_t *sp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3798
	uid_t uid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3799
	zone_status_t status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3800
	int err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3801
	rctl_entity_p_t e;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3803
	if (secpolicy_zone_config(CRED()) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3804
		return (set_errno(EPERM));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3805
	if (zoneid < MIN_USERZONEID || zoneid > MAX_ZONEID)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3806
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3807
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3808
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3809
	 * Stop all lwps so we don't need to hold a lock to look at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3810
	 * curproc->p_zone.  This needs to happen before we grab any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3811
	 * locks to avoid deadlock (another lwp in the process could
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3812
	 * be waiting for the held lock).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3813
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3814
	if (curthread != pp->p_agenttp && !holdlwps(SHOLDFORK))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3815
		return (set_errno(EINTR));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3816
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3817
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3818
	 * Make sure we're not changing zones with files open or mapped in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3819
	 * to our address space which shouldn't be changing zones.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3820
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3821
	if (!files_can_change_zones()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3822
		err = EBADF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3823
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3824
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3825
	if (!as_can_change_zones()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3826
		err = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3827
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3828
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3829
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3830
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3831
	if (pp->p_zone != global_zone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3832
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3833
		err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3834
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3835
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3836
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3837
	zone = zone_find_all_by_id(zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3838
	if (zone == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3839
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3840
		err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3841
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3842
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3844
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3845
	 * To prevent processes in a zone from holding contracts on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3846
	 * extrazonal resources, and to avoid process contract
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3847
	 * memberships which span zones, contract holders and processes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3848
	 * which aren't the sole members of their encapsulating process
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3849
	 * contracts are not allowed to zone_enter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3850
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3851
	ctp = pp->p_ct_process;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3852
	ct = &ctp->conp_contract;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3853
	mutex_enter(&ct->ct_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3854
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3855
	if ((avl_numnodes(&pp->p_ct_held) != 0) || (ctp->conp_nmembers != 1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3856
		mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3857
		mutex_exit(&ct->ct_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3858
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3859
		pool_unlock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3860
		err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3861
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3862
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3864
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3865
	 * Moreover, we don't allow processes whose encapsulating
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3866
	 * process contracts have inherited extrazonal contracts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3867
	 * While it would be easier to eliminate all process contracts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3868
	 * with inherited contracts, we need to be able to give a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3869
	 * restarted init (or other zone-penetrating process) its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3870
	 * predecessor's contracts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3871
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3872
	if (ctp->conp_ninherited != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3873
		contract_t *next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3874
		for (next = list_head(&ctp->conp_inherited); next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3875
		    next = list_next(&ctp->conp_inherited, next)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3876
			if (contract_getzuniqid(next) != zone->zone_uniqid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3877
				mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3878
				mutex_exit(&ct->ct_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3879
				mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3880
				pool_unlock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3881
				err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3882
				goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3883
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3884
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3885
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3886
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3887
	mutex_exit(&ct->ct_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3888
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3889
	status = zone_status_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3890
	if (status < ZONE_IS_READY || status >= ZONE_IS_SHUTTING_DOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3891
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3892
		 * Can't join
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3893
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3894
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3895
		err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3896
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3897
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3899
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3900
	 * Make sure new priv set is within the permitted set for caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3901
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3902
	if (!priv_issubset(zone->zone_privset, &CR_OPPRIV(CRED()))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3903
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3904
		err = EPERM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3905
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3906
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3907
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3908
	 * We want to momentarily drop zonehash_lock while we optimistically
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3909
	 * bind curproc to the pool it should be running in.  This is safe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3910
	 * since the zone can't disappear (we have a hold on it).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3911
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3912
	zone_hold(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3913
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3914
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3915
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3916
	 * Grab pool_lock to keep the pools configuration from changing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3917
	 * and to stop ourselves from getting rebound to another pool
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3918
	 * until we join the zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3919
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3920
	if (pool_lock_intr() != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3921
		zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3922
		err = EINTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3923
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3924
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3925
	ASSERT(secpolicy_pool(CRED()) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3926
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3927
	 * Bind ourselves to the pool currently associated with the zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3928
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3929
	oldpool = curproc->p_pool;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3930
	newpool = zone_pool_get(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3931
	if (pool_state == POOL_ENABLED && newpool != oldpool &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3932
	    (err = pool_do_bind(newpool, P_PID, P_MYID,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3933
	    POOL_BIND_ALL)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3934
		pool_unlock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3935
		zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3936
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3937
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3939
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3940
	 * Grab cpu_lock now; we'll need it later when we call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3941
	 * task_join().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3942
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3943
	mutex_enter(&cpu_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3944
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3945
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3946
	 * Make sure the zone hasn't moved on since we dropped zonehash_lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3947
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3948
	if (zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3949
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3950
		 * Can't join anymore.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3951
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3952
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3953
		mutex_exit(&cpu_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3954
		if (pool_state == POOL_ENABLED &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3955
		    newpool != oldpool)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3956
			(void) pool_do_bind(oldpool, P_PID, P_MYID,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3957
			    POOL_BIND_ALL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3958
		pool_unlock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3959
		zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3960
		err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3961
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3962
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3963
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3964
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3965
	zone_proj0 = zone->zone_zsched->p_task->tk_proj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3966
	/* verify that we do not exceed and task or lwp limits */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3967
	mutex_enter(&zone->zone_nlwps_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3968
	/* add new lwps to zone and zone's proj0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3969
	zone_proj0->kpj_nlwps += pp->p_lwpcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3970
	zone->zone_nlwps += pp->p_lwpcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3971
	/* add 1 task to zone's proj0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3972
	zone_proj0->kpj_ntasks += 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3973
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3974
	mutex_exit(&zone->zone_nlwps_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3975
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3976
	/* remove lwps from proc's old zone and old project */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3977
	mutex_enter(&pp->p_zone->zone_nlwps_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3978
	pp->p_zone->zone_nlwps -= pp->p_lwpcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3979
	pp->p_task->tk_proj->kpj_nlwps -= pp->p_lwpcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3980
	mutex_exit(&pp->p_zone->zone_nlwps_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3981
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3982
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3983
	 * Joining the zone cannot fail from now on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3984
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3985
	 * This means that a lot of the following code can be commonized and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3986
	 * shared with zsched().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3987
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3989
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3990
	 * Reset the encapsulating process contract's zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3991
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3992
	ASSERT(ct->ct_mzuniqid == GLOBAL_ZONEUNIQID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3993
	contract_setzuniqid(ct, zone->zone_uniqid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3995
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3996
	 * Create a new task and associate the process with the project keyed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3997
	 * by (projid,zoneid).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3998
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3999
	 * We might as well be in project 0; the global zone's projid doesn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4000
	 * make much sense in a zone anyhow.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4001
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4002
	 * This also increments zone_ntasks, and returns with p_lock held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4003
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4004
	tk = task_create(0, zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4005
	oldtk = task_join(tk, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4006
	mutex_exit(&cpu_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4007
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4008
	pp->p_flag |= SZONETOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4009
	pp->p_zone = zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4010
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4011
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4012
	 * call RCTLOP_SET functions on this proc
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4013
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4014
	e.rcep_p.zone = zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4015
	e.rcep_t = RCENTITY_ZONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4016
	(void) rctl_set_dup(NULL, NULL, pp, &e, zone->zone_rctls, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4017
	    RCD_CALLBACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4018
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4019
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4020
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4021
	 * We don't need to hold any of zsched's locks here; not only do we know
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4022
	 * the process and zone aren't going away, we know its session isn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4023
	 * changing either.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4024
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4025
	 * By joining zsched's session here, we mimic the behavior in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4026
	 * global zone of init's sid being the pid of sched.  We extend this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4027
	 * to all zlogin-like zone_enter()'ing processes as well.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4028
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4029
	mutex_enter(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4030
	sp = zone->zone_zsched->p_sessp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4031
	SESS_HOLD(sp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4032
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4033
	pgexit(pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4034
	SESS_RELE(pp->p_sessp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4035
	pp->p_sessp = sp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4036
	pgjoin(pp, zone->zone_zsched->p_pidp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4037
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4038
	mutex_exit(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4039
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4040
	mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4041
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4042
	 * We're firmly in the zone; let pools progress.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4043
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4044
	pool_unlock();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4045
	task_rele(oldtk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4046
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4047
	 * We don't need to retain a hold on the zone since we already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4048
	 * incremented zone_ntasks, so the zone isn't going anywhere.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4049
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4050
	zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4051
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4052
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4053
	 * Chroot
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4054
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4055
	vp = zone->zone_rootvp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4056
	zone_chdir(vp, &PTOU(pp)->u_cdir, pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4057
	zone_chdir(vp, &PTOU(pp)->u_rdir, pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4058
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4059
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4060
	 * Change process credentials
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4061
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4062
	newcr = cralloc();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4063
	mutex_enter(&pp->p_crlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4064
	cr = pp->p_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4065
	crcopy_to(cr, newcr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4066
	crsetzone(newcr, zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4067
	pp->p_cred = newcr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4068
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4069
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4070
	 * Restrict all process privilege sets to zone limit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4071
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4072
	priv_intersect(zone->zone_privset, &CR_PPRIV(newcr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4073
	priv_intersect(zone->zone_privset, &CR_EPRIV(newcr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4074
	priv_intersect(zone->zone_privset, &CR_IPRIV(newcr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4075
	priv_intersect(zone->zone_privset, &CR_LPRIV(newcr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4076
	mutex_exit(&pp->p_crlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4077
	crset(pp, newcr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4078
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4079
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4080
	 * Adjust upcount to reflect zone entry.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4081
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4082
	uid = crgetruid(newcr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4083
	mutex_enter(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4084
	upcount_dec(uid, GLOBAL_ZONEID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4085
	upcount_inc(uid, zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4086
	mutex_exit(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4087
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4088
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4089
	 * Set up core file path and content.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4090
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4091
	set_core_defaults();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4092
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4093
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4094
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4095
	 * Let the other lwps continue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4096
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4097
	mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4098
	if (curthread != pp->p_agenttp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4099
		continuelwps(pp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4100
	mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4102
	return (err != 0 ? set_errno(err) : 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4103
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4105
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4106
 * Systemcall entry point for zone_list(2).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4107
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4108
 * Processes running in a (non-global) zone only see themselves.
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4109
 * On labeled systems, they see all zones whose label they dominate.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4110
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4111
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4112
zone_list(zoneid_t *zoneidlist, uint_t *numzones)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4113
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4114
	zoneid_t *zoneids;
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4115
	zone_t *zone, *myzone;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4116
	uint_t user_nzones, real_nzones;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4117
	uint_t domi_nzones;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4118
	int error;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4120
	if (copyin(numzones, &user_nzones, sizeof (uint_t)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4121
		return (set_errno(EFAULT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4122
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4123
	myzone = curproc->p_zone;
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4124
	if (myzone != global_zone) {
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4125
		bslabel_t *mybslab;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4126
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4127
		if (!is_system_labeled()) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4128
			/* just return current zone */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4129
			real_nzones = domi_nzones = 1;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4130
			zoneids = kmem_alloc(sizeof (zoneid_t), KM_SLEEP);
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4131
			zoneids[0] = myzone->zone_id;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4132
		} else {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4133
			/* return all zones that are dominated */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4134
			mutex_enter(&zonehash_lock);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4135
			real_nzones = zonecount;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4136
			domi_nzones = 0;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4137
			if (real_nzones > 0) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4138
				zoneids = kmem_alloc(real_nzones *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4139
				    sizeof (zoneid_t), KM_SLEEP);
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4140
				mybslab = label2bslabel(myzone->zone_slabel);
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4141
				for (zone = list_head(&zone_active);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4142
				    zone != NULL;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4143
				    zone = list_next(&zone_active, zone)) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4144
					if (zone->zone_id == GLOBAL_ZONEID)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4145
						continue;
1769
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4146
					if (zone != myzone &&
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4147
					    (zone->zone_flags & ZF_IS_SCRATCH))
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4148
						continue;
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4149
					/*
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4150
					 * Note that a label always dominates
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4151
					 * itself, so myzone is always included
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4152
					 * in the list.
338500d67d4f 6404654 zoneadm mount command fails on labeled systems
carlsonj
parents: 1676
diff changeset
  4153
					 */
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4154
					if (bldominates(mybslab,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4155
					    label2bslabel(zone->zone_slabel))) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4156
						zoneids[domi_nzones++] =
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4157
						    zone->zone_id;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4158
					}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4159
				}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4160
			}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4161
			mutex_exit(&zonehash_lock);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4162
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4163
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4164
		mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4165
		real_nzones = zonecount;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4166
		domi_nzones = 0;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4167
		if (real_nzones > 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4168
			zoneids = kmem_alloc(real_nzones * sizeof (zoneid_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4169
			    KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4170
			for (zone = list_head(&zone_active); zone != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4171
			    zone = list_next(&zone_active, zone))
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4172
				zoneids[domi_nzones++] = zone->zone_id;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4173
			ASSERT(domi_nzones == real_nzones);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4174
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4175
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4176
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4177
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4178
	/*
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4179
	 * If user has allocated space for fewer entries than we found, then
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4180
	 * return only up to his limit.  Either way, tell him exactly how many
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4181
	 * we found.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4182
	 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4183
	if (domi_nzones < user_nzones)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4184
		user_nzones = domi_nzones;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4185
	error = 0;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4186
	if (copyout(&domi_nzones, numzones, sizeof (uint_t)) != 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4187
		error = EFAULT;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4188
	} else if (zoneidlist != NULL && user_nzones != 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4189
		if (copyout(zoneids, zoneidlist,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4190
		    user_nzones * sizeof (zoneid_t)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4191
			error = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4192
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4193
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4194
	if (real_nzones > 0)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4195
		kmem_free(zoneids, real_nzones * sizeof (zoneid_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4196
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4197
	if (error != 0)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4198
		return (set_errno(error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4199
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4200
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4201
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4203
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4204
 * Systemcall entry point for zone_lookup(2).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4205
 *
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4206
 * Non-global zones are only able to see themselves and (on labeled systems)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4207
 * the zones they dominate.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4208
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4209
static zoneid_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4210
zone_lookup(const char *zone_name)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4211
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4212
	char *kname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4213
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4214
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4215
	int err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4217
	if (zone_name == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4218
		/* return caller's zone id */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4219
		return (getzoneid());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4220
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4221
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4222
	kname = kmem_zalloc(ZONENAME_MAX, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4223
	if ((err = copyinstr(zone_name, kname, ZONENAME_MAX, NULL)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4224
		kmem_free(kname, ZONENAME_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4225
		return (set_errno(err));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4226
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4227
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4228
	mutex_enter(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4229
	zone = zone_find_all_by_name(kname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4230
	kmem_free(kname, ZONENAME_MAX);
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4231
	/*
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4232
	 * In a non-global zone, can only lookup global and own name.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4233
	 * In Trusted Extensions zone label dominance rules apply.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4234
	 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4235
	if (zone == NULL ||
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4236
	    zone_status_get(zone) < ZONE_IS_READY ||
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4237
	    !zone_list_access(zone)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4238
		mutex_exit(&zonehash_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4239
		return (set_errno(EINVAL));
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4240
	} else {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4241
		zoneid = zone->zone_id;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4242
		mutex_exit(&zonehash_lock);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4243
		return (zoneid);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4244
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4245
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4246
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4247
static int
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4248
zone_version(int *version_arg)
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4249
{
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4250
	int version = ZONE_SYSCALL_API_VERSION;
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4251
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4252
	if (copyout(&version, version_arg, sizeof (int)) != 0)
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4253
		return (set_errno(EFAULT));
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4254
	return (0);
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4255
}
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4256
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4257
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4258
long
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4259
zone(int cmd, void *arg1, void *arg2, void *arg3, void *arg4)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4260
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4261
	zone_def zs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4262
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4263
	switch (cmd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4264
	case ZONE_CREATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4265
		if (get_udatamodel() == DATAMODEL_NATIVE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4266
			if (copyin(arg1, &zs, sizeof (zone_def))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4267
				return (set_errno(EFAULT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4268
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4269
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4270
#ifdef _SYSCALL32_IMPL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4271
			zone_def32 zs32;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4273
			if (copyin(arg1, &zs32, sizeof (zone_def32))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4274
				return (set_errno(EFAULT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4275
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4276
			zs.zone_name =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4277
			    (const char *)(unsigned long)zs32.zone_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4278
			zs.zone_root =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4279
			    (const char *)(unsigned long)zs32.zone_root;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4280
			zs.zone_privs =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4281
			    (const struct priv_set *)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4282
			    (unsigned long)zs32.zone_privs;
1409
c25d6f2622c9 6366674 zones service common name could be more descriptive
dp
parents: 1166
diff changeset
  4283
			zs.zone_privssz = zs32.zone_privssz;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4284
			zs.rctlbuf = (caddr_t)(unsigned long)zs32.rctlbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4285
			zs.rctlbufsz = zs32.rctlbufsz;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4286
			zs.zfsbuf = (caddr_t)(unsigned long)zs32.zfsbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4287
			zs.zfsbufsz = zs32.zfsbufsz;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4288
			zs.extended_error =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4289
			    (int *)(unsigned long)zs32.extended_error;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4290
			zs.match = zs32.match;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4291
			zs.doi = zs32.doi;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4292
			zs.label = (const bslabel_t *)(uintptr_t)zs32.label;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4293
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4294
			panic("get_udatamodel() returned bogus result\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4295
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4296
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4297
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4298
		return (zone_create(zs.zone_name, zs.zone_root,
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4299
		    zs.zone_privs, zs.zone_privssz,
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4300
		    (caddr_t)zs.rctlbuf, zs.rctlbufsz,
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4301
		    (caddr_t)zs.zfsbuf, zs.zfsbufsz,
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4302
		    zs.extended_error, zs.match, zs.doi,
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4303
		    zs.label));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4304
	case ZONE_BOOT:
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4305
		return (zone_boot((zoneid_t)(uintptr_t)arg1));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4306
	case ZONE_DESTROY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4307
		return (zone_destroy((zoneid_t)(uintptr_t)arg1));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4308
	case ZONE_GETATTR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4309
		return (zone_getattr((zoneid_t)(uintptr_t)arg1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4310
		    (int)(uintptr_t)arg2, arg3, (size_t)arg4));
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4311
	case ZONE_SETATTR:
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4312
		return (zone_setattr((zoneid_t)(uintptr_t)arg1,
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4313
		    (int)(uintptr_t)arg2, arg3, (size_t)arg4));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4314
	case ZONE_ENTER:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4315
		return (zone_enter((zoneid_t)(uintptr_t)arg1));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4316
	case ZONE_LIST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4317
		return (zone_list((zoneid_t *)arg1, (uint_t *)arg2));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4318
	case ZONE_SHUTDOWN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4319
		return (zone_shutdown((zoneid_t)(uintptr_t)arg1));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4320
	case ZONE_LOOKUP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4321
		return (zone_lookup((const char *)arg1));
813
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4322
	case ZONE_VERSION:
0e6d3e880863 6317239 zone(2) needs subcode to query API version
dp
parents: 789
diff changeset
  4323
		return (zone_version((int *)arg1));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4324
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4325
		return (set_errno(EINVAL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4326
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4327
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4329
struct zarg {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4330
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4331
	zone_cmd_arg_t arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4332
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4334
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4335
zone_lookup_door(const char *zone_name, door_handle_t *doorp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4336
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4337
	char *buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4338
	size_t buflen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4339
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4340
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4341
	buflen = sizeof (ZONE_DOOR_PATH) + strlen(zone_name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4342
	buf = kmem_alloc(buflen, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4343
	(void) snprintf(buf, buflen, ZONE_DOOR_PATH, zone_name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4344
	error = door_ki_open(buf, doorp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4345
	kmem_free(buf, buflen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4346
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4347
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4349
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4350
zone_release_door(door_handle_t *doorp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4351
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4352
	door_ki_rele(*doorp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4353
	*doorp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4354
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4355
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4356
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4357
zone_ki_call_zoneadmd(struct zarg *zargp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4358
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4359
	door_handle_t door = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4360
	door_arg_t darg, save_arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4361
	char *zone_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4362
	size_t zone_namelen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4363
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4364
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4365
	zone_cmd_arg_t arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4366
	uint64_t uniqid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4367
	size_t size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4368
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4369
	int retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4370
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4371
	zone = zargp->zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4372
	arg = zargp->arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4373
	kmem_free(zargp, sizeof (*zargp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4374
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4375
	zone_namelen = strlen(zone->zone_name) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4376
	zone_name = kmem_alloc(zone_namelen, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4377
	bcopy(zone->zone_name, zone_name, zone_namelen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4378
	zoneid = zone->zone_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4379
	uniqid = zone->zone_uniqid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4380
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4381
	 * zoneadmd may be down, but at least we can empty out the zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4382
	 * We can ignore the return value of zone_empty() since we're called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4383
	 * from a kernel thread and know we won't be delivered any signals.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4384
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4385
	ASSERT(curproc == &p0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4386
	(void) zone_empty(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4387
	ASSERT(zone_status_get(zone) >= ZONE_IS_EMPTY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4388
	zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4390
	size = sizeof (arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4391
	darg.rbuf = (char *)&arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4392
	darg.data_ptr = (char *)&arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4393
	darg.rsize = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4394
	darg.data_size = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4395
	darg.desc_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4396
	darg.desc_num = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4397
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4398
	save_arg = darg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4399
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4400
	 * Since we're not holding a reference to the zone, any number of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4401
	 * things can go wrong, including the zone disappearing before we get a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4402
	 * chance to talk to zoneadmd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4403
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4404
	for (retry = 0; /* forever */; retry++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4405
		if (door == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4406
		    (error = zone_lookup_door(zone_name, &door)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4407
			goto next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4408
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4409
		ASSERT(door != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4411
		if ((error = door_ki_upcall(door, &darg)) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4412
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4413
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4414
		switch (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4415
		case EINTR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4416
			/* FALLTHROUGH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4417
		case EAGAIN:	/* process may be forking */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4418
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4419
			 * Back off for a bit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4420
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4421
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4422
		case EBADF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4423
			zone_release_door(&door);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4424
			if (zone_lookup_door(zone_name, &door) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4425
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4426
				 * zoneadmd may be dead, but it may come back to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4427
				 * life later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4428
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4429
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4430
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4431
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4432
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4433
			cmn_err(CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4434
			    "zone_ki_call_zoneadmd: door_ki_upcall error %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4435
			    error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4436
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4437
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4438
next:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4439
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4440
		 * If this isn't the same zone_t that we originally had in mind,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4441
		 * then this is the same as if two kadmin requests come in at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4442
		 * the same time: the first one wins.  This means we lose, so we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4443
		 * bail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4444
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4445
		if ((zone = zone_find_by_id(zoneid)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4446
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4447
			 * Problem is solved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4448
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4449
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4450
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4451
		if (zone->zone_uniqid != uniqid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4452
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4453
			 * zoneid recycled
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4454
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4455
			zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4456
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4457
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4458
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4459
		 * We could zone_status_timedwait(), but there doesn't seem to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4460
		 * be much point in doing that (plus, it would mean that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4461
		 * zone_free() isn't called until this thread exits).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4462
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4463
		zone_rele(zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4464
		delay(hz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4465
		darg = save_arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4466
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4467
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4468
	if (door != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4469
		zone_release_door(&door);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4470
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4471
	kmem_free(zone_name, zone_namelen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4472
	thread_exit();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4473
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4474
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4475
/*
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4476
 * Entry point for uadmin() to tell the zone to go away or reboot.  Analog to
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4477
 * kadmin().  The caller is a process in the zone.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4478
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4479
 * In order to shutdown the zone, we will hand off control to zoneadmd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4480
 * (running in the global zone) via a door.  We do a half-hearted job at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4481
 * killing all processes in the zone, create a kernel thread to contact
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4482
 * zoneadmd, and make note of the "uniqid" of the zone.  The uniqid is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4483
 * a form of generation number used to let zoneadmd (as well as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4484
 * zone_destroy()) know exactly which zone they're re talking about.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4485
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4486
int
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4487
zone_kadmin(int cmd, int fcn, const char *mdep, cred_t *credp)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4488
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4489
	struct zarg *zargp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4490
	zone_cmd_t zcmd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4491
	zone_t *zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4492
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4493
	zone = curproc->p_zone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4494
	ASSERT(getzoneid() != GLOBAL_ZONEID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4496
	switch (cmd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4497
	case A_SHUTDOWN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4498
		switch (fcn) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4499
		case AD_HALT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4500
		case AD_POWEROFF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4501
			zcmd = Z_HALT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4502
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4503
		case AD_BOOT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4504
			zcmd = Z_REBOOT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4505
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4506
		case AD_IBOOT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4507
		case AD_SBOOT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4508
		case AD_SIBOOT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4509
		case AD_NOSYNC:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4510
			return (ENOTSUP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4511
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4512
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4513
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4514
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4515
	case A_REBOOT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4516
		zcmd = Z_REBOOT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4517
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4518
	case A_FTRACE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4519
	case A_REMOUNT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4520
	case A_FREEZE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4521
	case A_DUMP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4522
		return (ENOTSUP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4523
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4524
		ASSERT(cmd != A_SWAPCTL);	/* handled by uadmin() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4525
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4526
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4527
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4528
	if (secpolicy_zone_admin(credp, B_FALSE))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4529
		return (EPERM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4530
	mutex_enter(&zone_status_lock);
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4531
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4532
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4533
	 * zone_status can't be ZONE_IS_EMPTY or higher since curproc
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4534
	 * is in the zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4535
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4536
	ASSERT(zone_status_get(zone) < ZONE_IS_EMPTY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4537
	if (zone_status_get(zone) > ZONE_IS_RUNNING) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4538
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4539
		 * This zone is already on its way down.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4540
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4541
		mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4542
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4543
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4544
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4545
	 * Prevent future zone_enter()s
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4546
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4547
	zone_status_set(zone, ZONE_IS_SHUTTING_DOWN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4548
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4550
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4551
	 * Kill everyone now and call zoneadmd later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4552
	 * zone_ki_call_zoneadmd() will do a more thorough job of this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4553
	 * later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4554
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4555
	killall(zone->zone_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4556
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4557
	 * Now, create the thread to contact zoneadmd and do the rest of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4558
	 * work.  This thread can't be created in our zone otherwise
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4559
	 * zone_destroy() would deadlock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4560
	 */
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4561
	zargp = kmem_zalloc(sizeof (*zargp), KM_SLEEP);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4562
	zargp->arg.cmd = zcmd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4563
	zargp->arg.uniqid = zone->zone_uniqid;
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4564
	zargp->zone = zone;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4565
	(void) strcpy(zargp->arg.locale, "C");
2267
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4566
	/* mdep was already copied in for us by uadmin */
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4567
	if (mdep != NULL)
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4568
		(void) strlcpy(zargp->arg.bootbuf, mdep,
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4569
		    sizeof (zargp->arg.bootbuf));
c5d9a656170f PSARC/2006/269 Zone Boot Arguments II
dp
parents: 2110
diff changeset
  4570
	zone_hold(zone);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4571
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4572
	(void) thread_create(NULL, 0, zone_ki_call_zoneadmd, zargp, 0, &p0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4573
	    TS_RUN, minclsyspri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4574
	exit(CLD_EXITED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4575
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4576
	return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4577
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4578
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4579
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4580
 * Entry point so kadmin(A_SHUTDOWN, ...) can set the global zone's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4581
 * status to ZONE_IS_SHUTTING_DOWN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4582
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4583
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4584
zone_shutdown_global(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4585
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4586
	ASSERT(curproc->p_zone == global_zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4587
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4588
	mutex_enter(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4589
	ASSERT(zone_status_get(global_zone) == ZONE_IS_RUNNING);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4590
	zone_status_set(global_zone, ZONE_IS_SHUTTING_DOWN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4591
	mutex_exit(&zone_status_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4592
}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4593
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4594
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4595
 * Returns true if the named dataset is visible in the current zone.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4596
 * The 'write' parameter is set to 1 if the dataset is also writable.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4597
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4598
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4599
zone_dataset_visible(const char *dataset, int *write)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4600
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4601
	zone_dataset_t *zd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4602
	size_t len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4603
	zone_t *zone = curproc->p_zone;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4604
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4605
	if (dataset[0] == '\0')
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4606
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4607
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4608
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4609
	 * Walk the list once, looking for datasets which match exactly, or
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4610
	 * specify a dataset underneath an exported dataset.  If found, return
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4611
	 * true and note that it is writable.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4612
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4613
	for (zd = list_head(&zone->zone_datasets); zd != NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4614
	    zd = list_next(&zone->zone_datasets, zd)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4615
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4616
		len = strlen(zd->zd_dataset);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4617
		if (strlen(dataset) >= len &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4618
		    bcmp(dataset, zd->zd_dataset, len) == 0 &&
816
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 813
diff changeset
  4619
		    (dataset[len] == '\0' || dataset[len] == '/' ||
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 813
diff changeset
  4620
		    dataset[len] == '@')) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4621
			if (write)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4622
				*write = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4623
			return (1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4624
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4625
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4626
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4627
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4628
	 * Walk the list a second time, searching for datasets which are parents
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4629
	 * of exported datasets.  These should be visible, but read-only.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4630
	 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4631
	 * Note that we also have to support forms such as 'pool/dataset/', with
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4632
	 * a trailing slash.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4633
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4634
	for (zd = list_head(&zone->zone_datasets); zd != NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4635
	    zd = list_next(&zone->zone_datasets, zd)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4636
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4637
		len = strlen(dataset);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4638
		if (dataset[len - 1] == '/')
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4639
			len--;	/* Ignore trailing slash */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4640
		if (len < strlen(zd->zd_dataset) &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4641
		    bcmp(dataset, zd->zd_dataset, len) == 0 &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4642
		    zd->zd_dataset[len] == '/') {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4643
			if (write)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4644
				*write = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4645
			return (1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4646
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4647
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4648
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4649
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 766
diff changeset
  4650
}
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4651
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4652
/*
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4653
 * zone_find_by_any_path() -
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4654
 *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4655
 * kernel-private routine similar to zone_find_by_path(), but which
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4656
 * effectively compares against zone paths rather than zonerootpath
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4657
 * (i.e., the last component of zonerootpaths, which should be "root/",
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4658
 * are not compared.)  This is done in order to accurately identify all
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4659
 * paths, whether zone-visible or not, including those which are parallel
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4660
 * to /root/, such as /dev/, /home/, etc...
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4661
 *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4662
 * If the specified path does not fall under any zone path then global
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4663
 * zone is returned.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4664
 *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4665
 * The treat_abs parameter indicates whether the path should be treated as
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4666
 * an absolute path although it does not begin with "/".  (This supports
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4667
 * nfs mount syntax such as host:any/path.)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4668
 *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4669
 * The caller is responsible for zone_rele of the returned zone.
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4670
 */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4671
zone_t *
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4672
zone_find_by_any_path(const char *path, boolean_t treat_abs)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4673
{
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4674
	zone_t *zone;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4675
	int path_offset = 0;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4677
	if (path == NULL) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4678
		zone_hold(global_zone);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4679
		return (global_zone);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4680
	}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4681
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4682
	if (*path != '/') {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4683
		ASSERT(treat_abs);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4684
		path_offset = 1;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4685
	}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4686
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4687
	mutex_enter(&zonehash_lock);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4688
	for (zone = list_head(&zone_active); zone != NULL;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4689
	    zone = list_next(&zone_active, zone)) {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4690
		char	*c;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4691
		size_t	pathlen;
1876
1427ed2daa73 6414797 code in zone_find_by_any_path generates bad assembly code and panic, can be worked around w/ change
mp46848
parents: 1769
diff changeset
  4692
		char *rootpath_start;
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4693
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4694
		if (zone == global_zone)	/* skip global zone */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4695
			continue;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4696
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4697
		/* scan backwards to find start of last component */
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4698
		c = zone->zone_rootpath + zone->zone_rootpathlen - 2;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4699
		do {
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4700
			c--;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4701
		} while (*c != '/');
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4702
1876
1427ed2daa73 6414797 code in zone_find_by_any_path generates bad assembly code and panic, can be worked around w/ change
mp46848
parents: 1769
diff changeset
  4703
		pathlen = c - zone->zone_rootpath + 1 - path_offset;
1427ed2daa73 6414797 code in zone_find_by_any_path generates bad assembly code and panic, can be worked around w/ change
mp46848
parents: 1769
diff changeset
  4704
		rootpath_start = (zone->zone_rootpath + path_offset);
1427ed2daa73 6414797 code in zone_find_by_any_path generates bad assembly code and panic, can be worked around w/ change
mp46848
parents: 1769
diff changeset
  4705
		if (strncmp(path, rootpath_start, pathlen) == 0)
1676
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4706
			break;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4707
	}
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4708
	if (zone == NULL)
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4709
		zone = global_zone;
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4710
	zone_hold(zone);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4711
	mutex_exit(&zonehash_lock);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4712
	return (zone);
37f4a3e2bd99 PSARC/2002/762 Layered Trusted Solaris
jpk
parents: 1409
diff changeset
  4713
}