Print this page
@@ -19,12 +19,12 @@
* CDDL HEADER END
*/
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2016, Joyent Inc.
* Copyright (c) 2015 by Delphix. All rights reserved.
+ * Copyright 2016, Joyent Inc.
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
@@ -134,13 +134,10 @@
MNTOPT_RO "," MNTOPT_LOFS_NOSUB "," MNTOPT_NODEVICES
#define DFSTYPES "/etc/dfs/fstypes"
#define MAXTNZLEN 2048
-/* Number of times to retry unmounting if it fails */
-#define UMOUNT_RETRIES 30
-
/* a reasonable estimate for the number of lwps per process */
#define LWPS_PER_PROCESS 10
/* for routing socket */
static int rts_seqno = 0;
@@ -178,11 +175,10 @@
/* from libsocket, not in any header file */
extern int getnetmaskbyaddr(struct in_addr, struct in_addr *);
/* from zoneadmd */
extern char query_hook[];
-extern char post_statechg_hook[];
/*
* For each "net" resource configured in zonecfg, we track a zone_addr_list_t
* node in a linked list that is sorted by linkid. The list is constructed as
* the xml configuration file is parsed, and the information
@@ -215,11 +211,11 @@
autofs_cleanup(zoneid_t zoneid)
{
/*
* Ask autofs to unmount all trigger nodes in the given zone.
*/
- return (_autofssys(AUTOFS_UNMOUNTALL, (void *)((uintptr_t)zoneid)));
+ return (_autofssys(AUTOFS_UNMOUNTALL, (void *)zoneid));
}
static void
free_mnttable(struct mnttab *mnt_array, uint_t nelem)
{
@@ -606,28 +602,10 @@
resolve_lofs(zlogp, zroot, zrootlen);
(void) strcpy(strrchr(zroot, '/') + 1, "lu");
}
/*
- * Perform brand-specific cleanup if we are unable to unmount a FS.
- */
-static void
-brand_umount_cleanup(zlog_t *zlogp, char *path)
-{
- char cmdbuf[2 * MAXPATHLEN];
-
- if (post_statechg_hook[0] == '\0')
- return;
-
- if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", post_statechg_hook,
- ZONE_STATE_DOWN, Z_UNMOUNT, path) > sizeof (cmdbuf))
- return;
-
- (void) do_subproc(zlogp, cmdbuf, NULL, B_FALSE);
-}
-
-/*
* The general strategy for unmounting filesystems is as follows:
*
* - Remote filesystems may be dead, and attempting to contact them as
* part of a regular unmount may hang forever; we want to always try to
* forcibly unmount such filesystems and only fall back to regular
@@ -656,11 +634,10 @@
*/
static int
unmount_filesystems(zlog_t *zlogp, zoneid_t zoneid, boolean_t unmount_cmd)
{
int error = 0;
- int fail = 0;
FILE *mnttab;
struct mnttab *mnts;
uint_t nmnt;
char zroot[MAXPATHLEN + 1];
size_t zrootlen;
@@ -744,45 +721,24 @@
*/
if (stuck) {
if (umount2(path, MS_FORCE) == 0) {
unmounted = B_TRUE;
stuck = B_FALSE;
- fail = 0;
} else {
/*
- * We may hit a failure here if there
- * is an app in the GZ with an open
- * pipe into the zone (commonly into
- * the zone's /var/run). This type
- * of app will notice the closed
- * connection and cleanup, but it may
- * take a while and we have no easy
- * way to notice that. To deal with
- * this case, we will wait and retry
- * a few times before we give up.
+ * The first failure indicates a
+ * mount we won't be able to get
+ * rid of automatically, so we
+ * bail.
*/
- fail++;
- if (fail < (UMOUNT_RETRIES - 1)) {
- zerror(zlogp, B_FALSE,
- "unable to unmount '%s', "
- "retrying in 2 seconds",
- path);
- (void) sleep(2);
- } else if (fail > UMOUNT_RETRIES) {
error++;
zerror(zlogp, B_FALSE,
- "unmount of '%s' failed",
- path);
+ "unable to unmount '%s'", path);
free_mnttable(mnts, nmnt);
goto out;
- } else {
- /* Try the hook 2 times */
- brand_umount_cleanup(zlogp,
- path);
}
}
- }
/*
* Try regular unmounts for everything else.
*/
if (!unmounted && umount2(path, 0) != 0)
newcount++;
@@ -1114,14 +1070,27 @@
}
int
vplat_get_iptype(zlog_t *zlogp, zone_iptype_t *iptypep)
{
- if (zonecfg_get_iptype(snap_hndl, iptypep) != Z_OK) {
+ zone_dochandle_t handle;
+
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (-1);
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+ if (zonecfg_get_iptype(handle, iptypep) != Z_OK) {
zerror(zlogp, B_FALSE, "invalid ip-type configuration");
+ zonecfg_fini_handle(handle);
return (-1);
}
+ zonecfg_fini_handle(handle);
return (0);
}
/*
* Apply the standard lists of devices/symlinks/mappings and the user-specified
@@ -1130,17 +1099,18 @@
*/
static int
mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd)
{
char brand[MAXNAMELEN];
+ zone_dochandle_t handle = NULL;
brand_handle_t bh = NULL;
struct zone_devtab ztab;
di_prof_t prof = NULL;
int err;
int retval = -1;
zone_iptype_t iptype;
- const char *curr_iptype = NULL;
+ const char *curr_iptype;
if (di_prof_init(devpath, &prof)) {
zerror(zlogp, B_TRUE, "failed to initialize profile");
goto cleanup;
}
@@ -1171,12 +1141,10 @@
break;
case ZS_EXCLUSIVE:
curr_iptype = "exclusive";
break;
}
- if (curr_iptype == NULL)
- abort();
if (brand_platform_iter_devices(bh, zone_name,
mount_one_dev_device_cb, prof, curr_iptype) != 0) {
zerror(zlogp, B_TRUE, "failed to add standard device");
goto cleanup;
@@ -1187,23 +1155,32 @@
zerror(zlogp, B_TRUE, "failed to add standard symlink");
goto cleanup;
}
/* Add user-specified devices and directories */
- if ((err = zonecfg_setdevent(snap_hndl)) != 0) {
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_FALSE, "can't initialize zone handle");
+ goto cleanup;
+ }
+ if ((err = zonecfg_get_handle(zone_name, handle)) != 0) {
+ zerror(zlogp, B_FALSE, "can't get handle for zone "
+ "%s: %s", zone_name, zonecfg_strerror(err));
+ goto cleanup;
+ }
+ if ((err = zonecfg_setdevent(handle)) != 0) {
zerror(zlogp, B_FALSE, "%s: %s", zone_name,
zonecfg_strerror(err));
goto cleanup;
}
- while (zonecfg_getdevent(snap_hndl, &ztab) == Z_OK) {
+ while (zonecfg_getdevent(handle, &ztab) == Z_OK) {
if (di_prof_add_dev(prof, ztab.zone_dev_match)) {
zerror(zlogp, B_TRUE, "failed to add "
"user-specified device");
goto cleanup;
}
}
- (void) zonecfg_enddevent(snap_hndl);
+ (void) zonecfg_enddevent(handle);
/* Send profile to kernel */
if (di_prof_commit(prof)) {
zerror(zlogp, B_TRUE, "failed to commit profile");
goto cleanup;
@@ -1212,10 +1189,12 @@
retval = 0;
cleanup:
if (bh != NULL)
brand_close(bh);
+ if (handle != NULL)
+ zonecfg_fini_handle(handle);
if (prof)
di_prof_fini(prof);
return (retval);
}
@@ -1705,10 +1684,11 @@
char rootpath[MAXPATHLEN];
char brand[MAXNAMELEN];
char luroot[MAXPATHLEN];
int i, num_fs = 0;
struct zone_fstab *fs_ptr = NULL;
+ zone_dochandle_t handle = NULL;
zone_state_t zstate;
brand_handle_t bh;
plat_gmount_cb_data_t cb;
if (zone_get_state(zone_name, &zstate) != Z_OK ||
@@ -1723,11 +1703,16 @@
if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
zerror(zlogp, B_TRUE, "unable to determine zone root");
goto bad;
}
- if (zonecfg_setfsent(snap_hndl) != Z_OK) {
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ goto bad;
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK ||
+ zonecfg_setfsent(handle) != Z_OK) {
zerror(zlogp, B_FALSE, "invalid configuration");
goto bad;
}
/*
@@ -1741,10 +1726,11 @@
}
/* Get a handle to the brand info for this zone */
if ((bh = brand_open(brand)) == NULL) {
zerror(zlogp, B_FALSE, "unable to determine zone brand");
+ zonecfg_fini_handle(handle);
return (-1);
}
/*
* Get the list of global filesystems to mount from the brand
@@ -1755,10 +1741,11 @@
cb.pgcd_num_fs = &num_fs;
if (brand_platform_iter_gmounts(bh, zone_name, zonepath,
plat_gmount_cb, &cb) != 0) {
zerror(zlogp, B_FALSE, "unable to mount filesystems");
brand_close(bh);
+ zonecfg_fini_handle(handle);
return (-1);
}
brand_close(bh);
/*
@@ -1765,14 +1752,17 @@
* Iterate through the rest of the filesystems. Sort them all,
* then mount them in sorted order. This is to make sure the
* higher level directories (e.g., /usr) get mounted before
* any beneath them (e.g., /usr/local).
*/
- if (mount_filesystems_fsent(snap_hndl, zlogp, &fs_ptr, &num_fs,
+ if (mount_filesystems_fsent(handle, zlogp, &fs_ptr, &num_fs,
mount_cmd) != 0)
goto bad;
+ zonecfg_fini_handle(handle);
+ handle = NULL;
+
/*
* Normally when we mount a zone all the zone filesystems
* get mounted relative to rootpath, which is usually
* <zonepath>/root. But when mounting a zone for administration
* purposes via the zone "mount" state, build_mounted_pre_var()
@@ -1864,10 +1854,12 @@
* Everything looks fine.
*/
return (0);
bad:
+ if (handle != NULL)
+ zonecfg_fini_handle(handle);
free_fs_data(fs_ptr, num_fs);
return (-1);
}
/* caller makes sure neither parameter is NULL */
@@ -2219,11 +2211,17 @@
(void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
if (ioctl(s, SIOCLIFADDIF, (caddr_t)&lifr) < 0) {
/*
* Here, we know that the interface can't be brought up.
+ * A similar warning message was already printed out to
+ * the console by zoneadm(1M) so instead we log the
+ * message to syslog and continue.
*/
+ zerror(&logsys, B_TRUE, "WARNING: skipping network interface "
+ "'%s' which may not be present/plumbed in the "
+ "global zone.", lifr.lifr_name);
(void) close(s);
return (Z_OK);
}
/* Preserve literal IPv4 address for later potential printing. */
@@ -2432,31 +2430,42 @@
* whatever we set up, and return an error.
*/
static int
configure_shared_network_interfaces(zlog_t *zlogp)
{
+ zone_dochandle_t handle;
struct zone_nwiftab nwiftab, loopback_iftab;
zoneid_t zoneid;
if ((zoneid = getzoneidbyname(zone_name)) == ZONE_ID_UNDEFINED) {
zerror(zlogp, B_TRUE, "unable to get zoneid");
return (-1);
}
- if (zonecfg_setnwifent(snap_hndl) == Z_OK) {
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (-1);
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+ if (zonecfg_setnwifent(handle) == Z_OK) {
for (;;) {
- if (zonecfg_getnwifent(snap_hndl, &nwiftab) != Z_OK)
+ if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK)
break;
- nwifent_free_attrs(&nwiftab);
if (configure_one_interface(zlogp, zoneid, &nwiftab) !=
Z_OK) {
- (void) zonecfg_endnwifent(snap_hndl);
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
return (-1);
}
}
- (void) zonecfg_endnwifent(snap_hndl);
+ (void) zonecfg_endnwifent(handle);
}
+ zonecfg_fini_handle(handle);
if (is_system_labeled()) {
/*
* Labeled zones share the loopback interface
* so it is not plumbed for shared stack instances.
*/
@@ -2899,45 +2908,78 @@
free(new);
}
}
/*
+ * For IP networking, we need to use the illumos-native device tree. For most
+ * zones, this is $ZONEROOT/dev. For LX ones, it's $ZONEROOT/native/dev.
+ * Return the appropriate post-$ZONEROOT path.
+ */
+static char *
+get_brand_dev(void)
+{
+ static char *lxpath = "/native/dev";
+ /* Cheesy hard-coding of strlen("/native") */
+ char *default_path = lxpath + 7;
+
+ /* LX zones are the exception... */
+ if (strcmp(brand_name, "lx") == 0)
+ return (lxpath);
+
+ return (default_path);
+}
+
+/*
* Add the kernel access control information for the interface names.
* If anything goes wrong, we log a general error message, attempt to tear down
* whatever we set up, and return an error.
*/
static int
configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
{
+ zone_dochandle_t handle;
struct zone_nwiftab nwiftab;
char rootpath[MAXPATHLEN];
char path[MAXPATHLEN];
datalink_id_t linkid;
di_prof_t prof = NULL;
boolean_t added = B_FALSE;
zone_addr_list_t *zalist = NULL, *new;
- if (zonecfg_setnwifent(snap_hndl) != Z_OK)
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (-1);
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+
+ if (zonecfg_setnwifent(handle) != Z_OK) {
+ zonecfg_fini_handle(handle);
return (0);
+ }
for (;;) {
- if (zonecfg_getnwifent(snap_hndl, &nwiftab) != Z_OK)
+ if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK)
break;
- nwifent_free_attrs(&nwiftab);
if (prof == NULL) {
if (zone_get_devroot(zone_name, rootpath,
sizeof (rootpath)) != Z_OK) {
- (void) zonecfg_endnwifent(snap_hndl);
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
zerror(zlogp, B_TRUE,
"unable to determine dev root");
return (-1);
}
(void) snprintf(path, sizeof (path), "%s%s", rootpath,
- "/dev");
+ get_brand_dev());
if (di_prof_init(path, &prof) != 0) {
- (void) zonecfg_endnwifent(snap_hndl);
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
zerror(zlogp, B_TRUE,
"failed to initialize profile");
return (-1);
}
}
@@ -2957,38 +2999,40 @@
&linkid, NULL, NULL, NULL) == DLADM_STATUS_OK &&
add_datalink(zlogp, zone_name, linkid,
nwiftab.zone_nwif_physical) == 0) {
added = B_TRUE;
} else {
- /*
- * Failed to add network device, but the brand hook
- * might be doing this for us, so keep silent.
- */
- continue;
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
+ zerror(zlogp, B_TRUE, "failed to add network device");
+ return (-1);
}
/* set up the new IP interface, and add them all later */
new = malloc(sizeof (*new));
if (new == NULL) {
zerror(zlogp, B_TRUE, "no memory for %s",
nwiftab.zone_nwif_physical);
+ zonecfg_fini_handle(handle);
free_ip_interface(zalist);
}
bzero(new, sizeof (*new));
new->za_nwiftab = nwiftab;
new->za_linkid = linkid;
zalist = add_ip_interface(zalist, new);
}
if (zalist != NULL) {
if ((errno = add_net(zlogp, zoneid, zalist)) != 0) {
- (void) zonecfg_endnwifent(snap_hndl);
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
zerror(zlogp, B_TRUE, "failed to add address");
free_ip_interface(zalist);
return (-1);
}
free_ip_interface(zalist);
}
- (void) zonecfg_endnwifent(snap_hndl);
+ (void) zonecfg_endnwifent(handle);
+ zonecfg_fini_handle(handle);
if (prof != NULL && added) {
if (di_prof_commit(prof) != 0) {
zerror(zlogp, B_TRUE, "failed to commit profile");
return (-1);
@@ -3120,27 +3164,52 @@
"protection", NULL, 0, DLADM_OPT_ACTIVE);
if (dlstatus == DLADM_STATUS_NOTFOUND) {
/* datalink does not belong to the GZ */
continue;
}
- if (dlstatus != DLADM_STATUS_OK)
+ if (dlstatus != DLADM_STATUS_OK) {
zerror(zlogp, B_FALSE,
- "clear 'protection' link property: %s",
dladm_status2str(dlstatus, dlerr));
-
+ free(dllinks);
+ return (-1);
+ }
dlstatus = dladm_set_linkprop(dld_handle, *dllink,
"allowed-ips", NULL, 0, DLADM_OPT_ACTIVE);
- if (dlstatus != DLADM_STATUS_OK)
+ if (dlstatus != DLADM_STATUS_OK) {
zerror(zlogp, B_FALSE,
- "clear 'allowed-ips' link property: %s",
dladm_status2str(dlstatus, dlerr));
+ free(dllinks);
+ return (-1);
}
+ }
free(dllinks);
return (0);
}
static int
+unconfigure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
+{
+ int dlnum = 0;
+
+ /*
+ * The kernel shutdown callback for the dls module should have removed
+ * all datalinks from this zone. If any remain, then there's a
+ * problem.
+ */
+ if (zone_list_datalink(zoneid, &dlnum, NULL) != 0) {
+ zerror(zlogp, B_TRUE, "unable to list network interfaces");
+ return (-1);
+ }
+ if (dlnum != 0) {
+ zerror(zlogp, B_FALSE,
+ "datalinks remain in zone after shutdown");
+ return (-1);
+ }
+ return (0);
+}
+
+static int
tcp_abort_conn(zlog_t *zlogp, zoneid_t zoneid,
const struct sockaddr_storage *local, const struct sockaddr_storage *remote)
{
int fd;
struct strioctl ioc;
@@ -3218,18 +3287,30 @@
static int
get_privset(zlog_t *zlogp, priv_set_t *privs, zone_mnt_t mount_cmd)
{
int error = -1;
+ zone_dochandle_t handle;
char *privname = NULL;
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (-1);
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+
if (ALT_MOUNT(mount_cmd)) {
zone_iptype_t iptype;
- const char *curr_iptype = NULL;
+ const char *curr_iptype;
- if (zonecfg_get_iptype(snap_hndl, &iptype) != Z_OK) {
+ if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
zerror(zlogp, B_TRUE, "unable to determine ip-type");
+ zonecfg_fini_handle(handle);
return (-1);
}
switch (iptype) {
case ZS_SHARED:
@@ -3238,19 +3319,21 @@
case ZS_EXCLUSIVE:
curr_iptype = "exclusive";
break;
}
- if (zonecfg_default_privset(privs, curr_iptype) == Z_OK)
+ if (zonecfg_default_privset(privs, curr_iptype) == Z_OK) {
+ zonecfg_fini_handle(handle);
return (0);
-
+ }
zerror(zlogp, B_FALSE,
"failed to determine the zone's default privilege set");
+ zonecfg_fini_handle(handle);
return (-1);
}
- switch (zonecfg_get_privset(snap_hndl, privs, &privname)) {
+ switch (zonecfg_get_privset(handle, privs, &privname)) {
case Z_OK:
error = 0;
break;
case Z_PRIV_PROHIBITED:
zerror(zlogp, B_FALSE, "privilege \"%s\" is not permitted "
@@ -3269,10 +3352,11 @@
"privilege set");
break;
}
free(privname);
+ zonecfg_fini_handle(handle);
return (error);
}
static char *
zone_proj_rctl(const char *name)
@@ -3294,19 +3378,30 @@
char *nvl_packed = NULL;
size_t nvl_size = 0;
nvlist_t **nvlv = NULL;
int rctlcount = 0;
int error = -1;
+ zone_dochandle_t handle;
struct zone_rctltab rctltab;
rctlblk_t *rctlblk = NULL;
uint64_t maxlwps;
uint64_t maxprocs;
int rproc, rlwp;
*bufp = NULL;
*bufsizep = 0;
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (-1);
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+
rctltab.zone_rctl_valptr = NULL;
if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
zerror(zlogp, B_TRUE, "%s failed", "nvlist_alloc");
goto out;
}
@@ -3335,20 +3430,20 @@
"unable to set max-processes alias");
goto out;
}
}
- if (zonecfg_setrctlent(snap_hndl) != Z_OK) {
+ if (zonecfg_setrctlent(handle) != Z_OK) {
zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent");
goto out;
}
if ((rctlblk = malloc(rctlblk_size())) == NULL) {
zerror(zlogp, B_TRUE, "memory allocation failed");
goto out;
}
- while (zonecfg_getrctlent(snap_hndl, &rctltab) == Z_OK) {
+ while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
struct zone_rctlvaltab *rctlval;
uint_t i, count;
const char *name = rctltab.zone_rctl_name;
char *proj_nm;
@@ -3447,11 +3542,11 @@
nvlist_free(nvlv[i]);
free(nvlv);
nvlv = NULL;
rctlcount++;
}
- (void) zonecfg_endrctlent(snap_hndl);
+ (void) zonecfg_endrctlent(handle);
if (rctlcount == 0) {
error = 0;
goto out;
}
@@ -3471,10 +3566,12 @@
if (error && nvl_packed != NULL)
free(nvl_packed);
nvlist_free(nvl);
if (nvlv != NULL)
free(nvlv);
+ if (handle != NULL)
+ zonecfg_fini_handle(handle);
return (error);
}
static int
get_implicit_datasets(zlog_t *zlogp, char **retstr)
@@ -3486,19 +3583,20 @@
if (snprintf(cmdbuf, sizeof (cmdbuf), "%s datasets", query_hook)
> sizeof (cmdbuf))
return (-1);
- if (do_subproc(zlogp, cmdbuf, retstr, B_FALSE) != 0)
+ if (do_subproc(zlogp, cmdbuf, retstr) != 0)
return (-1);
return (0);
}
static int
get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep)
{
+ zone_dochandle_t handle;
struct zone_dstab dstab;
size_t total, offset, len;
int error = -1;
char *str = NULL;
char *implicit_datasets = NULL;
@@ -3505,24 +3603,34 @@
int implicit_len = 0;
*bufp = NULL;
*bufsizep = 0;
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (-1);
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+
if (get_implicit_datasets(zlogp, &implicit_datasets) != 0) {
zerror(zlogp, B_FALSE, "getting implicit datasets failed");
goto out;
}
- if (zonecfg_setdsent(snap_hndl) != Z_OK) {
+ if (zonecfg_setdsent(handle) != Z_OK) {
zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent");
goto out;
}
total = 0;
- while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK)
+ while (zonecfg_getdsent(handle, &dstab) == Z_OK)
total += strlen(dstab.zone_dataset_name) + 1;
- (void) zonecfg_enddsent(snap_hndl);
+ (void) zonecfg_enddsent(handle);
if (implicit_datasets != NULL)
implicit_len = strlen(implicit_datasets);
if (implicit_len > 0)
total += implicit_len + 1;
@@ -3535,24 +3643,24 @@
if ((str = malloc(total)) == NULL) {
zerror(zlogp, B_TRUE, "memory allocation failed");
goto out;
}
- if (zonecfg_setdsent(snap_hndl) != Z_OK) {
+ if (zonecfg_setdsent(handle) != Z_OK) {
zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent");
goto out;
}
offset = 0;
- while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) {
+ while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
len = strlen(dstab.zone_dataset_name);
(void) strlcpy(str + offset, dstab.zone_dataset_name,
total - offset);
offset += len;
if (offset < total - 1)
str[offset++] = ',';
}
- (void) zonecfg_enddsent(snap_hndl);
+ (void) zonecfg_enddsent(handle);
if (implicit_len > 0)
(void) strlcpy(str + offset, implicit_datasets, total - offset);
error = 0;
@@ -3560,39 +3668,55 @@
*bufsizep = total;
out:
if (error != 0 && str != NULL)
free(str);
+ if (handle != NULL)
+ zonecfg_fini_handle(handle);
if (implicit_datasets != NULL)
free(implicit_datasets);
return (error);
}
static int
validate_datasets(zlog_t *zlogp)
{
+ zone_dochandle_t handle;
struct zone_dstab dstab;
zfs_handle_t *zhp;
libzfs_handle_t *hdl;
- if (zonecfg_setdsent(snap_hndl) != Z_OK) {
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (-1);
+ }
+ if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
return (-1);
}
+ if (zonecfg_setdsent(handle) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (-1);
+ }
+
if ((hdl = libzfs_init()) == NULL) {
zerror(zlogp, B_FALSE, "opening ZFS library");
+ zonecfg_fini_handle(handle);
return (-1);
}
- while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) {
+ while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
if ((zhp = zfs_open(hdl, dstab.zone_dataset_name,
ZFS_TYPE_FILESYSTEM)) == NULL) {
zerror(zlogp, B_FALSE, "cannot open ZFS dataset '%s'",
dstab.zone_dataset_name);
+ zonecfg_fini_handle(handle);
libzfs_fini(hdl);
return (-1);
}
/*
@@ -3603,19 +3727,21 @@
zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_ZONED),
"on") != 0) {
zerror(zlogp, B_FALSE, "cannot set 'zoned' "
"property for ZFS dataset '%s'\n",
dstab.zone_dataset_name);
+ zonecfg_fini_handle(handle);
zfs_close(zhp);
libzfs_fini(hdl);
return (-1);
}
zfs_close(zhp);
}
- (void) zonecfg_enddsent(snap_hndl);
+ (void) zonecfg_enddsent(handle);
+ zonecfg_fini_handle(handle);
libzfs_fini(hdl);
return (0);
}
@@ -4348,14 +4474,26 @@
setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid)
{
int res;
uint64_t tmp;
char sched[MAXNAMELEN];
+ zone_dochandle_t handle = NULL;
char pool_err[128];
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (Z_BAD_HANDLE);
+ }
+
+ if ((res = zonecfg_get_snapshot_handle(zone_name, handle)) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
+ zonecfg_fini_handle(handle);
+ return (res);
+ }
+
/* Get the scheduling class set in the zone configuration. */
- if (zonecfg_get_sched_class(snap_hndl, sched, sizeof (sched)) == Z_OK &&
+ if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK &&
strlen(sched) > 0) {
if (zone_setattr(zoneid, ZONE_ATTR_SCHED_CLASS, sched,
strlen(sched)) == -1)
zerror(zlogp, B_TRUE, "WARNING: unable to set the "
"default scheduling class");
@@ -4396,11 +4534,11 @@
* in by default so we can print a warning and modify the class
* if we wouldn't be using FSS.
*/
char class_name[PC_CLNMSZ];
- if (zonecfg_get_dflt_sched_class(snap_hndl, class_name,
+ if (zonecfg_get_dflt_sched_class(handle, class_name,
sizeof (class_name)) != Z_OK) {
zerror(zlogp, B_FALSE, "WARNING: unable to determine "
"the zone's scheduling class");
} else if (strcmp("FSS", class_name) != 0) {
@@ -4429,36 +4567,37 @@
* If we are rebooting we want to attempt to reuse any temporary pool
* that was previously set up. zonecfg_bind_tmp_pool() will do the
* right thing in all cases (reuse or create) based on the current
* zonecfg.
*/
- if ((res = zonecfg_bind_tmp_pool(snap_hndl, zoneid, pool_err,
+ if ((res = zonecfg_bind_tmp_pool(handle, zoneid, pool_err,
sizeof (pool_err))) != Z_OK) {
if (res == Z_POOL || res == Z_POOL_CREATE || res == Z_POOL_BIND)
zerror(zlogp, B_FALSE, "%s: %s\ndedicated-cpu setting "
"cannot be instantiated", zonecfg_strerror(res),
pool_err);
else
zerror(zlogp, B_FALSE, "could not bind zone to "
"temporary pool: %s", zonecfg_strerror(res));
+ zonecfg_fini_handle(handle);
return (Z_POOL_BIND);
}
/*
* Check if we need to warn about poold not being enabled.
*/
- if (zonecfg_warn_poold(snap_hndl)) {
+ if (zonecfg_warn_poold(handle)) {
zerror(zlogp, B_FALSE, "WARNING: A range of dedicated-cpus has "
"been specified\nbut the dynamic pool service is not "
"enabled.\nThe system will not dynamically adjust the\n"
"processor allocation within the specified range\n"
"until svc:/system/pools/dynamic is enabled.\n"
"See poold(1M).");
}
/* The following is a warning, not an error. */
- if ((res = zonecfg_bind_pool(snap_hndl, zoneid, pool_err,
+ if ((res = zonecfg_bind_pool(handle, zoneid, pool_err,
sizeof (pool_err))) != Z_OK) {
if (res == Z_POOL_BIND)
zerror(zlogp, B_FALSE, "WARNING: unable to bind to "
"pool '%s'; using default pool.", pool_err);
else if (res == Z_POOL)
@@ -4468,13 +4607,14 @@
zerror(zlogp, B_FALSE, "WARNING: %s",
zonecfg_strerror(res));
}
/* Update saved pool name in case it has changed */
- (void) zonecfg_get_poolname(snap_hndl, zone_name, pool_name,
+ (void) zonecfg_get_poolname(handle, zone_name, pool_name,
sizeof (pool_name));
+ zonecfg_fini_handle(handle);
return (Z_OK);
}
static void
report_prop_err(zlog_t *zlogp, const char *name, const char *value, int res)
@@ -4571,32 +4711,37 @@
return (Z_OK);
}
static int
-setup_zone_attrs(zlog_t *zlogp, zoneid_t zoneid)
+setup_zone_attrs(zlog_t *zlogp, char *zone_namep, zoneid_t zoneid)
{
+ zone_dochandle_t handle;
int res = Z_OK;
- if ((res = setup_zone_hostid(snap_hndl, zlogp, zoneid)) != Z_OK)
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zerror(zlogp, B_TRUE, "getting zone configuration handle");
+ return (Z_BAD_HANDLE);
+ }
+ if ((res = zonecfg_get_snapshot_handle(zone_namep, handle)) != Z_OK) {
+ zerror(zlogp, B_FALSE, "invalid configuration");
goto out;
+ }
- if ((res = setup_zone_fs_allowed(snap_hndl, zlogp, zoneid)) != Z_OK)
+ if ((res = setup_zone_hostid(handle, zlogp, zoneid)) != Z_OK)
goto out;
+ if ((res = setup_zone_fs_allowed(handle, zlogp, zoneid)) != Z_OK)
+ goto out;
+
out:
+ zonecfg_fini_handle(handle);
return (res);
}
-/*
- * The zone_did is a persistent debug ID. Each zone should have a unique ID
- * in the kernel. This is used for things like DTrace which want to monitor
- * zones across reboots. They can't use the zoneid since that changes on
- * each boot.
- */
zoneid_t
-vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zone_did)
+vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd)
{
zoneid_t rval = -1;
priv_set_t *privs;
char rootpath[MAXPATHLEN];
char *rctlbuf = NULL;
@@ -4608,11 +4753,11 @@
char *kzone;
FILE *fp = NULL;
tsol_zcent_t *zcent = NULL;
int match = 0;
int doi = 0;
- int flags = -1;
+ int flags;
zone_iptype_t iptype;
if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
zerror(zlogp, B_TRUE, "unable to determine zone root");
return (-1);
@@ -4630,12 +4775,10 @@
break;
case ZS_EXCLUSIVE:
flags = ZCF_NET_EXCL;
break;
}
- if (flags == -1)
- abort();
if ((privs = priv_allocset()) == NULL) {
zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
return (-1);
}
@@ -4735,11 +4878,11 @@
}
xerr = 0;
if ((zoneid = zone_create(kzone, rootpath, privs, rctlbuf,
rctlbufsz, zfsbuf, zfsbufsz, &xerr, match, doi, zlabel,
- flags, zone_did)) == -1) {
+ flags)) == -1) {
if (xerr == ZE_AREMOUNTS) {
if (zonecfg_find_mounts(rootpath, NULL, NULL) < 1) {
zerror(zlogp, B_FALSE,
"An unknown file-system is mounted on "
"a subdirectory of %s", rootpath);
@@ -4781,11 +4924,11 @@
if (mount_cmd == Z_MNT_BOOT) {
brand_handle_t bh;
struct brand_attr attr;
char modname[MAXPATHLEN];
- if (setup_zone_attrs(zlogp, zoneid) != Z_OK)
+ if (setup_zone_attrs(zlogp, zone_name, zoneid) != Z_OK)
goto error;
if ((bh = brand_open(brand_name)) == NULL) {
zerror(zlogp, B_FALSE,
"unable to determine brand name");
@@ -4839,12 +4982,10 @@
(void) zone_shutdown(zoneid);
(void) zone_destroy(zoneid);
}
if (rctlbuf != NULL)
free(rctlbuf);
- if (zfsbuf != NULL)
- free(zfsbuf);
priv_freeset(privs);
if (fp != NULL)
zonecfg_close_scratch(fp);
lofs_discard_mnttab();
if (zcent != NULL)
@@ -4979,12 +5120,10 @@
0) {
lofs_discard_mnttab();
return (-1);
}
break;
- default:
- abort();
}
}
write_index_file(zoneid);
@@ -5056,12 +5195,11 @@
return (0);
}
}
int
-vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting,
- boolean_t debug)
+vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting)
{
char *kzone;
zoneid_t zoneid;
int res;
char pool_err[128];
@@ -5095,16 +5233,20 @@
if (unmount_cmd)
(void) lu_root_teardown(zlogp);
goto error;
}
- if (remove_datalink_pool(zlogp, zoneid) != 0)
+ if (remove_datalink_pool(zlogp, zoneid) != 0) {
zerror(zlogp, B_FALSE, "unable clear datalink pool property");
+ goto error;
+ }
- if (remove_datalink_protect(zlogp, zoneid) != 0)
+ if (remove_datalink_protect(zlogp, zoneid) != 0) {
zerror(zlogp, B_FALSE,
"unable clear datalink protect property");
+ goto error;
+ }
/*
* The datalinks assigned to the zone will be removed from the NGZ as
* part of zone_shutdown() so that we need to remove protect/pool etc.
* before zone_shutdown(). Even if the shutdown itself fails, the zone
@@ -5134,11 +5276,11 @@
goto error;
}
brand_close(bh);
if ((strlen(cmdbuf) > EXEC_LEN) &&
- (do_subproc(zlogp, cmdbuf, NULL, debug) != Z_OK)) {
+ (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) {
zerror(zlogp, B_FALSE, "%s failed", cmdbuf);
goto error;
}
if (!unmount_cmd) {
@@ -5166,10 +5308,16 @@
"network interfaces in zone");
goto error;
}
break;
case ZS_EXCLUSIVE:
+ if (unconfigure_exclusive_network_interfaces(zlogp,
+ zoneid) != 0) {
+ zerror(zlogp, B_FALSE, "unable to unconfigure "
+ "network interfaces in zone");
+ goto error;
+ }
status = dladm_zone_halt(dld_handle, zoneid);
if (status != DLADM_STATUS_OK) {
zerror(zlogp, B_FALSE, "unable to notify "
"dlmgmtd of zone halt: %s",
dladm_status2str(status, errmsg));
@@ -5202,13 +5350,18 @@
if (!unmount_cmd) {
boolean_t destroy_tmp_pool = B_TRUE;
if (rebooting) {
struct zone_psettab pset_tab;
+ zone_dochandle_t handle;
- if (zonecfg_lookup_pset(snap_hndl, &pset_tab) == Z_OK)
+ if ((handle = zonecfg_init_handle()) != NULL &&
+ zonecfg_get_handle(zone_name, handle) == Z_OK &&
+ zonecfg_lookup_pset(handle, &pset_tab) == Z_OK)
destroy_tmp_pool = B_FALSE;
+
+ zonecfg_fini_handle(handle);
}
if (destroy_tmp_pool) {
if ((res = zonecfg_destroy_tmp_pool(zone_name, pool_err,
sizeof (pool_err))) != Z_OK) {