Print this page
OS-5330 zoneadm mounting an lx or joyent branded zone fails
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
(NOTE: Manual port, because of divergence from SmartOS.)
Network interfaces need to configure in /native/dev for LX.
Mismerged snap_hndl (should be handle) blocked lipkg zone boot
(NOTE: There are other instances of snap_hndl we pulled in from
illumos-joyent that may need to be nuked too.)
OS-1571 Placate gcc -Wparentheses
Reviewed by: Robert Mustacchi <rm@joyent.com>
OS-5292 zoneadmd should infer zone.max-processes
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
OS-4915 want FX high priority zone configuration option
OS-4925 ps pri shows misleading value for zone in RT scheduling class
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
OS-4254 libbrand token substitution incomplete for mount entries
OS-3776 project rctls should be in sync with zone rctls
OS-3524 in order to support interaction with docker containers, need to be able to connect to stdio for init from GZ
OS-3525 in order to support 'docker logs' need to be able to get stdio from zone to log file
OS-399 zone phys. mem. cap should be a rctl and have associated kstat
*** 19,30 ****
* CDDL HEADER END
*/
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, Joyent Inc. All rights reserved.
* Copyright (c) 2015 by Delphix. All rights reserved.
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
--- 19,30 ----
* CDDL HEADER END
*/
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015 by Delphix. All rights reserved.
+ * Copyright 2016, Joyent Inc.
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
*** 134,145 ****
MNTOPT_RO "," MNTOPT_LOFS_NOSUB "," MNTOPT_NODEVICES
#define DFSTYPES "/etc/dfs/fstypes"
#define MAXTNZLEN 2048
- #define ALT_MOUNT(mount_cmd) ((mount_cmd) != Z_MNT_BOOT)
-
/* a reasonable estimate for the number of lwps per process */
#define LWPS_PER_PROCESS 10
/* for routing socket */
static int rts_seqno = 0;
--- 134,143 ----
*** 159,168 ****
--- 157,179 ----
static m_label_t *zid_label = NULL;
static priv_set_t *zprivs = NULL;
static const char *DFLT_FS_ALLOWED = "hsfs,smbfs,nfs,nfs3,nfs4,nfsdyn";
+ typedef struct zone_proj_rctl_map {
+ char *zpr_zone_rctl;
+ char *zpr_project_rctl;
+ } zone_proj_rctl_map_t;
+
+ static zone_proj_rctl_map_t zone_proj_rctl_map[] = {
+ {"zone.max-msg-ids", "project.max-msg-ids"},
+ {"zone.max-sem-ids", "project.max-sem-ids"},
+ {"zone.max-shm-ids", "project.max-shm-ids"},
+ {"zone.max-shm-memory", "project.max-shm-memory"},
+ {NULL, NULL}
+ };
+
/* from libsocket, not in any header file */
extern int getnetmaskbyaddr(struct in_addr, struct in_addr *);
/* from zoneadmd */
extern char query_hook[];
*** 1148,1163 ****
/* Add user-specified devices and directories */
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)) {
zerror(zlogp, B_FALSE, "can't get handle for zone "
"%s: %s", zone_name, zonecfg_strerror(err));
goto cleanup;
}
! if (err = zonecfg_setdevent(handle)) {
zerror(zlogp, B_FALSE, "%s: %s", zone_name,
zonecfg_strerror(err));
goto cleanup;
}
while (zonecfg_getdevent(handle, &ztab) == Z_OK) {
--- 1159,1174 ----
/* Add user-specified devices and directories */
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(handle, &ztab) == Z_OK) {
*** 1669,1679 ****
static int
mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd)
{
char rootpath[MAXPATHLEN];
- char zonepath[MAXPATHLEN];
char brand[MAXNAMELEN];
char luroot[MAXPATHLEN];
int i, num_fs = 0;
struct zone_fstab *fs_ptr = NULL;
zone_dochandle_t handle = NULL;
--- 1680,1689 ----
*** 1688,1702 ****
zone_state_str(ZONE_STATE_READY),
zone_state_str(ZONE_STATE_MOUNTED));
goto bad;
}
- if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
- zerror(zlogp, B_TRUE, "unable to determine zone path");
- goto bad;
- }
-
if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
zerror(zlogp, B_TRUE, "unable to determine zone root");
goto bad;
}
--- 1698,1707 ----
*** 1793,1819 ****
goto bad;
qsort(fs_ptr, num_fs, sizeof (*fs_ptr), fs_compare);
for (i = 0; i < num_fs; i++) {
! if (ALT_MOUNT(mount_cmd) &&
! strcmp(fs_ptr[i].zone_fs_dir, "/dev") == 0) {
size_t slen = strlen(rootpath) - 2;
/*
! * By default we'll try to mount /dev as /a/dev
! * but /dev is special and always goes at the top
! * so strip the trailing '/a' from the rootpath.
*/
assert(strcmp(&rootpath[slen], "/a") == 0);
rootpath[slen] = '\0';
! if (mount_one(zlogp, &fs_ptr[i], rootpath, mount_cmd)
! != 0)
goto bad;
rootpath[slen] = '/';
continue;
}
if (mount_one(zlogp, &fs_ptr[i], rootpath, mount_cmd) != 0)
goto bad;
}
if (ALT_MOUNT(mount_cmd) &&
!build_mounted_post_var(zlogp, mount_cmd, rootpath, luroot))
--- 1798,1841 ----
goto bad;
qsort(fs_ptr, num_fs, sizeof (*fs_ptr), fs_compare);
for (i = 0; i < num_fs; i++) {
! if (ALT_MOUNT(mount_cmd)) {
! if (strcmp(fs_ptr[i].zone_fs_dir, "/dev") == 0) {
size_t slen = strlen(rootpath) - 2;
/*
! * By default we'll try to mount /dev
! * as /a/dev but /dev is special and
! * always goes at the top so strip the
! * trailing '/a' from the rootpath.
*/
assert(strcmp(&rootpath[slen], "/a") == 0);
rootpath[slen] = '\0';
! if (mount_one(zlogp, &fs_ptr[i], rootpath,
! mount_cmd) != 0)
goto bad;
rootpath[slen] = '/';
continue;
+ } else if (strcmp(brand_name, default_brand) != 0) {
+ /*
+ * If mounting non-native brand, skip
+ * mounting global mounts and
+ * filesystem entries since they are
+ * only needed for native pkg upgrade
+ * tools.
+ *
+ * The only exception right now is
+ * /dev (handled above), which is
+ * needed in the luroot in order to
+ * zlogin -S into the zone.
+ */
+ continue;
}
+ }
+
if (mount_one(zlogp, &fs_ptr[i], rootpath, mount_cmd) != 0)
goto bad;
}
if (ALT_MOUNT(mount_cmd) &&
!build_mounted_post_var(zlogp, mount_cmd, rootpath, luroot))
*** 2886,2895 ****
--- 2908,2936 ----
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
*** 2931,2941 ****
zerror(zlogp, B_TRUE,
"unable to determine dev root");
return (-1);
}
(void) snprintf(path, sizeof (path), "%s%s", rootpath,
! "/dev");
if (di_prof_init(path, &prof) != 0) {
(void) zonecfg_endnwifent(handle);
zonecfg_fini_handle(handle);
zerror(zlogp, B_TRUE,
"failed to initialize profile");
--- 2972,2982 ----
zerror(zlogp, B_TRUE,
"unable to determine dev root");
return (-1);
}
(void) snprintf(path, sizeof (path), "%s%s", rootpath,
! get_brand_dev());
if (di_prof_init(path, &prof) != 0) {
(void) zonecfg_endnwifent(handle);
zonecfg_fini_handle(handle);
zerror(zlogp, B_TRUE,
"failed to initialize profile");
*** 3315,3324 ****
--- 3356,3378 ----
free(privname);
zonecfg_fini_handle(handle);
return (error);
}
+ static char *
+ zone_proj_rctl(const char *name)
+ {
+ int i;
+
+ for (i = 0; zone_proj_rctl_map[i].zpr_zone_rctl != NULL; i++) {
+ if (strcmp(name, zone_proj_rctl_map[i].zpr_zone_rctl) == 0) {
+ return (zone_proj_rctl_map[i].zpr_project_rctl);
+ }
+ }
+ return (NULL);
+ }
+
static int
get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep)
{
nvlist_t *nvl = NULL;
char *nvl_packed = NULL;
*** 3329,3338 ****
--- 3383,3393 ----
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) {
*** 3351,3374 ****
goto out;
}
/*
* Allow the administrator to control both the maximum number of
! * process table slots and the maximum number of lwps with just the
! * max-processes property. If only the max-processes property is set,
! * we add a max-lwps property with a limit derived from max-processes.
*/
! if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXPROCS, &maxprocs)
! == Z_OK &&
! zonecfg_get_aliased_rctl(handle, ALIAS_MAXLWPS, &maxlwps)
! == Z_NO_ENTRY) {
! if (zonecfg_set_aliased_rctl(handle, ALIAS_MAXLWPS,
maxprocs * LWPS_PER_PROCESS) != Z_OK) {
zerror(zlogp, B_FALSE, "unable to set max-lwps alias");
goto out;
}
}
if (zonecfg_setrctlent(handle) != Z_OK) {
zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent");
goto out;
}
--- 3406,3438 ----
goto out;
}
/*
* Allow the administrator to control both the maximum number of
! * process table slots, and the maximum number of lwps, with a single
! * max-processes or max-lwps property. If only the max-processes
! * property is set, we add a max-lwps property with a limit derived
! * from max-processes. If only the max-lwps property is set, we add a
! * max-processes property with the same limit as max-lwps.
*/
! rproc = zonecfg_get_aliased_rctl(snap_hndl, ALIAS_MAXPROCS, &maxprocs);
! rlwp = zonecfg_get_aliased_rctl(snap_hndl, ALIAS_MAXLWPS, &maxlwps);
! if (rproc == Z_OK && rlwp == Z_NO_ENTRY) {
! if (zonecfg_set_aliased_rctl(snap_hndl, ALIAS_MAXLWPS,
maxprocs * LWPS_PER_PROCESS) != Z_OK) {
zerror(zlogp, B_FALSE, "unable to set max-lwps alias");
goto out;
}
+ } else if (rlwp == Z_OK && rproc == Z_NO_ENTRY) {
+ /* no scaling for max-proc value */
+ if (zonecfg_set_aliased_rctl(snap_hndl, ALIAS_MAXPROCS,
+ maxlwps) != Z_OK) {
+ zerror(zlogp, B_FALSE,
+ "unable to set max-processes alias");
+ goto out;
}
+ }
if (zonecfg_setrctlent(handle) != Z_OK) {
zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent");
goto out;
}
*** 3379,3388 ****
--- 3443,3453 ----
}
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;
/* zoneadm should have already warned about unknown rctls. */
if (!zonecfg_is_rctl(name)) {
zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
rctltab.zone_rctl_valptr = NULL;
*** 3445,3454 ****
--- 3510,3539 ----
goto out;
}
}
zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
rctltab.zone_rctl_valptr = NULL;
+
+ /*
+ * With no action on our part we will start zsched with the
+ * project rctl values for our (zoneadmd) current project. For
+ * brands running a variant of Illumos, that's not a problem
+ * since they will setup their own projects, but for a
+ * non-native brand like lx, where there are no projects, we
+ * want to start things up with the same project rctls as the
+ * corresponding zone rctls, since nothing within the zone will
+ * ever change the project rctls.
+ */
+ if ((proj_nm = zone_proj_rctl(name)) != NULL) {
+ if (nvlist_add_nvlist_array(nvl, proj_nm, nvlv, count)
+ != 0) {
+ zerror(zlogp, B_FALSE,
+ "nvlist_add_nvlist_arrays failed");
+ goto out;
+ }
+ }
+
if (nvlist_add_nvlist_array(nvl, (char *)name, nvlv, count)
!= 0) {
zerror(zlogp, B_FALSE, "%s failed",
"nvlist_add_nvlist_array");
goto out;
*** 3706,3726 ****
{
int error = -1;
zfs_handle_t *zhp;
libzfs_handle_t *hdl;
m_label_t ds_sl;
- char zonepath[MAXPATHLEN];
char ds_hexsl[MAXNAMELEN];
if (!is_system_labeled())
return (0);
- if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
- zerror(zlogp, B_TRUE, "unable to determine zone path");
- return (-1);
- }
-
if (!is_zonepath_zfs(zonepath))
return (0);
if ((hdl = libzfs_init()) == NULL) {
zerror(zlogp, B_FALSE, "opening ZFS library");
--- 3791,3805 ----
*** 4387,4405 ****
}
return (B_FALSE);
}
/*
! * Set memory cap and pool info for the zone's resource management
! * configuration.
*/
static int
setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid)
{
int res;
uint64_t tmp;
- struct zone_mcaptab mcap;
char sched[MAXNAMELEN];
zone_dochandle_t handle = NULL;
char pool_err[128];
if ((handle = zonecfg_init_handle()) == NULL) {
--- 4466,4482 ----
}
return (B_FALSE);
}
/*
! * Set pool info for the zone's resource management configuration.
*/
static int
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) {
*** 4411,4452 ****
zerror(zlogp, B_FALSE, "invalid configuration");
zonecfg_fini_handle(handle);
return (res);
}
- /*
- * If a memory cap is configured, set the cap in the kernel using
- * zone_setattr() and make sure the rcapd SMF service is enabled.
- */
- if (zonecfg_getmcapent(handle, &mcap) == Z_OK) {
- uint64_t num;
- char smf_err[128];
-
- num = (uint64_t)strtoull(mcap.zone_physmem_cap, NULL, 10);
- if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) {
- zerror(zlogp, B_TRUE, "could not set zone memory cap");
- zonecfg_fini_handle(handle);
- return (Z_INVAL);
- }
-
- if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
- zerror(zlogp, B_FALSE, "enabling system/rcap service "
- "failed: %s", smf_err);
- zonecfg_fini_handle(handle);
- return (Z_INVAL);
- }
- }
-
/* Get the scheduling class set in the zone configuration. */
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");
! } else if (zonecfg_get_aliased_rctl(handle, ALIAS_SHARES, &tmp)
== Z_OK) {
/*
* If the zone has the zone.cpu-shares rctl set then we want to
* use the Fair Share Scheduler (FSS) for processes in the
* zone. Check what scheduling class the zone would be running
--- 4488,4533 ----
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(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");
! if (strcmp(sched, "FX") == 0) {
! /*
! * When FX is specified then by default all processes
! * will start at the lowest priority level (0) and
! * stay there. We support an optional attr which
! * indicates that all the processes should be "high
! * priority". We set this on the zone so that starting
! * init will set the priority high.
! */
! struct zone_attrtab a;
!
! bzero(&a, sizeof (a));
! (void) strlcpy(a.zone_attr_name, "fixed-hi-prio",
! sizeof (a.zone_attr_name));
!
! if (zonecfg_lookup_attr(snap_hndl, &a) == Z_OK &&
! strcmp(a.zone_attr_value, "true") == 0) {
! boolean_t hi = B_TRUE;
!
! if (zone_setattr(zoneid,
! ZONE_ATTR_SCHED_FIXEDHI, (void *)hi,
! sizeof (hi)) == -1)
! zerror(zlogp, B_TRUE, "WARNING: unable "
! "to set high priority");
! }
! }
!
! } else if (zonecfg_get_aliased_rctl(snap_hndl, ALIAS_SHARES, &tmp)
== Z_OK) {
/*
* If the zone has the zone.cpu-shares rctl set then we want to
* use the Fair Share Scheduler (FSS) for processes in the
* zone. Check what scheduling class the zone would be running
*** 4989,4999 ****
}
int
vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid)
{
! char zonepath[MAXPATHLEN];
if (mount_cmd == Z_MNT_BOOT && validate_datasets(zlogp) != 0) {
lofs_discard_mnttab();
return (-1);
}
--- 5070,5080 ----
}
int
vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid)
{
! char zpath[MAXPATHLEN];
if (mount_cmd == Z_MNT_BOOT && validate_datasets(zlogp) != 0) {
lofs_discard_mnttab();
return (-1);
}
*** 5000,5018 ****
/*
* Before we try to mount filesystems we need to create the
* attribute backing store for /dev
*/
! if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
! lofs_discard_mnttab();
! return (-1);
! }
! resolve_lofs(zlogp, zonepath, sizeof (zonepath));
/* Make /dev directory owned by root, grouped sys */
! if (make_one_dir(zlogp, zonepath, "/dev", DEFAULT_DIR_MODE,
! 0, 3) != 0) {
lofs_discard_mnttab();
return (-1);
}
if (mount_filesystems(zlogp, mount_cmd) != 0) {
--- 5081,5095 ----
/*
* Before we try to mount filesystems we need to create the
* attribute backing store for /dev
*/
! (void) strlcpy(zpath, zonepath, sizeof (zpath));
! resolve_lofs(zlogp, zpath, sizeof (zpath));
/* Make /dev directory owned by root, grouped sys */
! if (make_one_dir(zlogp, zpath, "/dev", DEFAULT_DIR_MODE, 0, 3) != 0) {
lofs_discard_mnttab();
return (-1);
}
if (mount_filesystems(zlogp, mount_cmd) != 0) {
*** 5124,5134 ****
{
char *kzone;
zoneid_t zoneid;
int res;
char pool_err[128];
- char zpath[MAXPATHLEN];
char cmdbuf[MAXPATHLEN];
brand_handle_t bh = NULL;
dladm_status_t status;
char errmsg[DLADM_STRSIZE];
ushort_t flags;
--- 5201,5210 ----
*** 5180,5195 ****
if (zone_shutdown(zoneid) != 0) {
zerror(zlogp, B_TRUE, "unable to shutdown zone");
goto error;
}
- /* Get the zonepath of this zone */
- if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
- zerror(zlogp, B_FALSE, "unable to determine zone path");
- goto error;
- }
-
/* Get a handle to the brand info for this zone */
if ((bh = brand_open(brand_name)) == NULL) {
zerror(zlogp, B_FALSE, "unable to determine zone brand");
return (-1);
}
--- 5256,5265 ----
*** 5196,5206 ****
/*
* If there is a brand 'halt' callback, execute it now to give the
* brand a chance to cleanup any custom configuration.
*/
(void) strcpy(cmdbuf, EXEC_PREFIX);
! if (brand_get_halt(bh, zone_name, zpath, cmdbuf + EXEC_LEN,
sizeof (cmdbuf) - EXEC_LEN) < 0) {
brand_close(bh);
zerror(zlogp, B_FALSE, "unable to determine branded zone's "
"halt callback.");
goto error;
--- 5266,5276 ----
/*
* If there is a brand 'halt' callback, execute it now to give the
* brand a chance to cleanup any custom configuration.
*/
(void) strcpy(cmdbuf, EXEC_PREFIX);
! if (brand_get_halt(bh, zone_name, zonepath, cmdbuf + EXEC_LEN,
sizeof (cmdbuf) - EXEC_LEN) < 0) {
brand_close(bh);
zerror(zlogp, B_FALSE, "unable to determine branded zone's "
"halt callback.");
goto error;