diff options
Diffstat (limited to 'usr/src/cmd/zoneadmd/vplat.c')
-rw-r--r-- | usr/src/cmd/zoneadmd/vplat.c | 521 |
1 files changed, 193 insertions, 328 deletions
diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c index b9954b81b3..7b36c6de5b 100644 --- a/usr/src/cmd/zoneadmd/vplat.c +++ b/usr/src/cmd/zoneadmd/vplat.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, Joyent Inc. All rights reserved. + * Copyright 2015, Joyent Inc. All rights reserved. */ /* @@ -137,6 +137,9 @@ #define ALT_MOUNT(mount_cmd) ((mount_cmd) != Z_MNT_BOOT) +/* 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 @@ -160,11 +163,25 @@ 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[]; +extern char post_statechg_hook[]; /* * For each "net" resource configured in zonecfg, we track a zone_addr_list_t @@ -201,7 +218,7 @@ autofs_cleanup(zoneid_t zoneid) /* * Ask autofs to unmount all trigger nodes in the given zone. */ - return (_autofssys(AUTOFS_UNMOUNTALL, (void *)zoneid)); + return (_autofssys(AUTOFS_UNMOUNTALL, (void *)((uintptr_t)zoneid))); } static void @@ -592,6 +609,24 @@ root_to_lu(zlog_t *zlogp, char *zroot, size_t zrootlen, boolean_t isresolved) } /* + * 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 @@ -624,6 +659,7 @@ 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; @@ -711,18 +747,39 @@ unmount_filesystems(zlog_t *zlogp, zoneid_t zoneid, boolean_t unmount_cmd) if (umount2(path, MS_FORCE) == 0) { unmounted = B_TRUE; stuck = B_FALSE; + fail = 0; } else { /* - * The first failure indicates a - * mount we won't be able to get - * rid of automatically, so we - * bail. + * 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. */ - error++; - zerror(zlogp, B_FALSE, - "unable to unmount '%s'", path); - free_mnttable(mnts, nmnt); - goto out; + 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); + free_mnttable(mnts, nmnt); + goto out; + } else { + /* Try the hook 2 times */ + brand_umount_cleanup(zlogp, + path); + } } } /* @@ -1060,23 +1117,10 @@ mount_one_dev_symlink_cb(void *arg, const char *source, const char *target) int vplat_get_iptype(zlog_t *zlogp, zone_iptype_t *iptypep) { - 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) { + if (zonecfg_get_iptype(snap_hndl, iptypep) != Z_OK) { zerror(zlogp, B_FALSE, "invalid ip-type configuration"); - zonecfg_fini_handle(handle); return (-1); } - zonecfg_fini_handle(handle); return (0); } @@ -1089,14 +1133,13 @@ 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; + const char *curr_iptype = NULL; if (di_prof_init(devpath, &prof)) { zerror(zlogp, B_TRUE, "failed to initialize profile"); @@ -1131,6 +1174,8 @@ mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd) 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) { @@ -1145,28 +1190,19 @@ mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd) } /* 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)) { + if ((err = zonecfg_setdevent(snap_hndl)) != 0) { zerror(zlogp, B_FALSE, "%s: %s", zone_name, zonecfg_strerror(err)); goto cleanup; } - while (zonecfg_getdevent(handle, &ztab) == Z_OK) { + while (zonecfg_getdevent(snap_hndl, &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(handle); + (void) zonecfg_enddevent(snap_hndl); /* Send profile to kernel */ if (di_prof_commit(prof)) { @@ -1179,8 +1215,6 @@ mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd) cleanup: if (bh != NULL) brand_close(bh); - if (handle != NULL) - zonecfg_fini_handle(handle); if (prof) di_prof_fini(prof); return (retval); @@ -1670,12 +1704,10 @@ 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; zone_state_t zstate; brand_handle_t bh; plat_gmount_cb_data_t cb; @@ -1689,22 +1721,12 @@ mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) 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; } - 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) { + if (zonecfg_setfsent(snap_hndl) != Z_OK) { zerror(zlogp, B_FALSE, "invalid configuration"); goto bad; } @@ -1722,7 +1744,6 @@ mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) /* 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); } @@ -1733,11 +1754,10 @@ mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) cb.pgcd_zlogp = zlogp; cb.pgcd_fs_tab = &fs_ptr; cb.pgcd_num_fs = &num_fs; - if (brand_platform_iter_gmounts(bh, zonepath, + 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); @@ -1748,13 +1768,10 @@ mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) * higher level directories (e.g., /usr) get mounted before * any beneath them (e.g., /usr/local). */ - if (mount_filesystems_fsent(handle, zlogp, &fs_ptr, &num_fs, + if (mount_filesystems_fsent(snap_hndl, 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 @@ -1833,8 +1850,6 @@ mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd) return (0); bad: - if (handle != NULL) - zonecfg_fini_handle(handle); free_fs_data(fs_ptr, num_fs); return (-1); } @@ -2190,13 +2205,7 @@ configure_one_interface(zlog_t *zlogp, zoneid_t zone_id, 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); } @@ -2409,7 +2418,6 @@ bad: static int configure_shared_network_interfaces(zlog_t *zlogp) { - zone_dochandle_t handle; struct zone_nwiftab nwiftab, loopback_iftab; zoneid_t zoneid; @@ -2418,29 +2426,19 @@ configure_shared_network_interfaces(zlog_t *zlogp) return (-1); } - 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) { + if (zonecfg_setnwifent(snap_hndl) == Z_OK) { for (;;) { - if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK) + if (zonecfg_getnwifent(snap_hndl, &nwiftab) != Z_OK) break; + nwifent_free_attrs(&nwiftab); if (configure_one_interface(zlogp, zoneid, &nwiftab) != Z_OK) { - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); + (void) zonecfg_endnwifent(snap_hndl); return (-1); } } - (void) zonecfg_endnwifent(handle); + (void) zonecfg_endnwifent(snap_hndl); } - zonecfg_fini_handle(handle); if (is_system_labeled()) { /* * Labeled zones share the loopback interface @@ -2894,7 +2892,6 @@ free_ip_interface(zone_addr_list_t *zalist) 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]; @@ -2903,30 +2900,18 @@ configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) boolean_t added = B_FALSE; zone_addr_list_t *zalist = NULL, *new; - 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); + if (zonecfg_setnwifent(snap_hndl) != Z_OK) return (0); - } for (;;) { - if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK) + if (zonecfg_getnwifent(snap_hndl, &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(handle); - zonecfg_fini_handle(handle); + (void) zonecfg_endnwifent(snap_hndl); zerror(zlogp, B_TRUE, "unable to determine dev root"); return (-1); @@ -2934,8 +2919,7 @@ configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) (void) snprintf(path, sizeof (path), "%s%s", rootpath, "/dev"); if (di_prof_init(path, &prof) != 0) { - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); + (void) zonecfg_endnwifent(snap_hndl); zerror(zlogp, B_TRUE, "failed to initialize profile"); return (-1); @@ -2959,17 +2943,17 @@ configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) nwiftab.zone_nwif_physical) == 0) { added = B_TRUE; } else { - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); - zerror(zlogp, B_TRUE, "failed to add network device"); - return (-1); + /* + * Failed to add network device, but the brand hook + * might be doing this for us, so keep silent. + */ + continue; } /* 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)); @@ -2979,16 +2963,14 @@ configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid) } if (zalist != NULL) { if ((errno = add_net(zlogp, zoneid, zalist)) != 0) { - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); + (void) zonecfg_endnwifent(snap_hndl); zerror(zlogp, B_TRUE, "failed to add address"); free_ip_interface(zalist); return (-1); } free_ip_interface(zalist); } - (void) zonecfg_endnwifent(handle); - zonecfg_fini_handle(handle); + (void) zonecfg_endnwifent(snap_hndl); if (prof != NULL && added) { if (di_prof_commit(prof) != 0) { @@ -3124,48 +3106,23 @@ remove_datalink_protect(zlog_t *zlogp, zoneid_t zoneid) /* 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) { @@ -3247,26 +3204,14 @@ 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; + const char *curr_iptype = NULL; - if (zonecfg_get_iptype(handle, &iptype) != Z_OK) { + if (zonecfg_get_iptype(snap_hndl, &iptype) != Z_OK) { zerror(zlogp, B_TRUE, "unable to determine ip-type"); - zonecfg_fini_handle(handle); return (-1); } @@ -3279,17 +3224,15 @@ get_privset(zlog_t *zlogp, priv_set_t *privs, zone_mnt_t mount_cmd) break; } - if (zonecfg_default_privset(privs, curr_iptype) == Z_OK) { - zonecfg_fini_handle(handle); + if (zonecfg_default_privset(privs, curr_iptype) == Z_OK) 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(handle, privs, &privname)) { + switch (zonecfg_get_privset(snap_hndl, privs, &privname)) { case Z_OK: error = 0; break; @@ -3312,10 +3255,22 @@ get_privset(zlog_t *zlogp, priv_set_t *privs, zone_mnt_t mount_cmd) } 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) { @@ -3325,7 +3280,6 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) 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; @@ -3334,16 +3288,6 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) *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"); @@ -3356,18 +3300,18 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) * 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) + if (zonecfg_get_aliased_rctl(snap_hndl, ALIAS_MAXPROCS, &maxprocs) == Z_OK && - zonecfg_get_aliased_rctl(handle, ALIAS_MAXLWPS, &maxlwps) + zonecfg_get_aliased_rctl(snap_hndl, ALIAS_MAXLWPS, &maxlwps) == Z_NO_ENTRY) { - if (zonecfg_set_aliased_rctl(handle, ALIAS_MAXLWPS, + 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; } } - if (zonecfg_setrctlent(handle) != Z_OK) { + if (zonecfg_setrctlent(snap_hndl) != Z_OK) { zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent"); goto out; } @@ -3376,10 +3320,11 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) zerror(zlogp, B_TRUE, "memory allocation failed"); goto out; } - while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) { + while (zonecfg_getrctlent(snap_hndl, &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)) { @@ -3446,6 +3391,26 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) } 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", @@ -3458,7 +3423,7 @@ get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep) nvlv = NULL; rctlcount++; } - (void) zonecfg_endrctlent(handle); + (void) zonecfg_endrctlent(snap_hndl); if (rctlcount == 0) { error = 0; @@ -3483,8 +3448,6 @@ out: nvlist_free(nvl); if (nvlv != NULL) free(nvlv); - if (handle != NULL) - zonecfg_fini_handle(handle); return (error); } @@ -3500,7 +3463,7 @@ get_implicit_datasets(zlog_t *zlogp, char **retstr) > sizeof (cmdbuf)) return (-1); - if (do_subproc(zlogp, cmdbuf, retstr) != 0) + if (do_subproc(zlogp, cmdbuf, retstr, B_FALSE) != 0) return (-1); return (0); @@ -3509,7 +3472,6 @@ get_implicit_datasets(zlog_t *zlogp, char **retstr) 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; @@ -3520,30 +3482,20 @@ get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep) *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(handle) != Z_OK) { + if (zonecfg_setdsent(snap_hndl) != Z_OK) { zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent"); goto out; } total = 0; - while (zonecfg_getdsent(handle, &dstab) == Z_OK) + while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) total += strlen(dstab.zone_dataset_name) + 1; - (void) zonecfg_enddsent(handle); + (void) zonecfg_enddsent(snap_hndl); if (implicit_datasets != NULL) implicit_len = strlen(implicit_datasets); @@ -3560,12 +3512,12 @@ get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep) goto out; } - if (zonecfg_setdsent(handle) != Z_OK) { + if (zonecfg_setdsent(snap_hndl) != Z_OK) { zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent"); goto out; } offset = 0; - while (zonecfg_getdsent(handle, &dstab) == Z_OK) { + while (zonecfg_getdsent(snap_hndl, &dstab) == Z_OK) { len = strlen(dstab.zone_dataset_name); (void) strlcpy(str + offset, dstab.zone_dataset_name, total - offset); @@ -3573,7 +3525,7 @@ get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep) if (offset < total - 1) str[offset++] = ','; } - (void) zonecfg_enddsent(handle); + (void) zonecfg_enddsent(snap_hndl); if (implicit_len > 0) (void) strlcpy(str + offset, implicit_datasets, total - offset); @@ -3585,8 +3537,6 @@ get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep) out: if (error != 0 && str != NULL) free(str); - if (handle != NULL) - zonecfg_fini_handle(handle); if (implicit_datasets != NULL) free(implicit_datasets); @@ -3596,40 +3546,26 @@ out: static int validate_datasets(zlog_t *zlogp) { - zone_dochandle_t handle; struct zone_dstab dstab; zfs_handle_t *zhp; libzfs_handle_t *hdl; - 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) { + if (zonecfg_setdsent(snap_hndl) != 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(handle, &dstab) == Z_OK) { + while (zonecfg_getdsent(snap_hndl, &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); } @@ -3644,7 +3580,6 @@ validate_datasets(zlog_t *zlogp) 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); @@ -3652,9 +3587,8 @@ validate_datasets(zlog_t *zlogp) zfs_close(zhp); } - (void) zonecfg_enddsent(handle); + (void) zonecfg_enddsent(snap_hndl); - zonecfg_fini_handle(handle); libzfs_fini(hdl); return (0); @@ -3708,17 +3642,11 @@ validate_rootds_label(zlog_t *zlogp, char *rootpath, m_label_t *zone_sl) 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); @@ -4388,62 +4316,25 @@ duplicate_reachable_path(zlog_t *zlogp, const char *rootpath) } /* - * Set memory cap and pool info for the zone's resource management - * configuration. + * 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; - struct zone_mcaptab mcap; 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); - } - - /* - * 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 && + if (zonecfg_get_sched_class(snap_hndl, 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) + } 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 @@ -4454,7 +4345,7 @@ setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) */ char class_name[PC_CLNMSZ]; - if (zonecfg_get_dflt_sched_class(handle, class_name, + if (zonecfg_get_dflt_sched_class(snap_hndl, class_name, sizeof (class_name)) != Z_OK) { zerror(zlogp, B_FALSE, "WARNING: unable to determine " "the zone's scheduling class"); @@ -4487,7 +4378,7 @@ setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) * right thing in all cases (reuse or create) based on the current * zonecfg. */ - if ((res = zonecfg_bind_tmp_pool(handle, zoneid, pool_err, + if ((res = zonecfg_bind_tmp_pool(snap_hndl, 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 " @@ -4496,14 +4387,13 @@ setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) 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(handle)) { + if (zonecfg_warn_poold(snap_hndl)) { 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" @@ -4513,7 +4403,7 @@ setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) } /* The following is a warning, not an error. */ - if ((res = zonecfg_bind_pool(handle, zoneid, pool_err, + if ((res = zonecfg_bind_pool(snap_hndl, zoneid, pool_err, sizeof (pool_err))) != Z_OK) { if (res == Z_POOL_BIND) zerror(zlogp, B_FALSE, "WARNING: unable to bind to " @@ -4527,10 +4417,9 @@ setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid) } /* Update saved pool name in case it has changed */ - (void) zonecfg_get_poolname(handle, zone_name, pool_name, + (void) zonecfg_get_poolname(snap_hndl, zone_name, pool_name, sizeof (pool_name)); - zonecfg_fini_handle(handle); return (Z_OK); } @@ -4631,33 +4520,28 @@ setup_zone_fs_allowed(zone_dochandle_t handle, zlog_t *zlogp, zoneid_t zoneid) } static int -setup_zone_attrs(zlog_t *zlogp, char *zone_namep, zoneid_t zoneid) +setup_zone_attrs(zlog_t *zlogp, zoneid_t zoneid) { - zone_dochandle_t handle; int res = 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_hostid(handle, zlogp, zoneid)) != Z_OK) + if ((res = setup_zone_hostid(snap_hndl, zlogp, zoneid)) != Z_OK) goto out; - if ((res = setup_zone_fs_allowed(handle, zlogp, zoneid)) != Z_OK) + if ((res = setup_zone_fs_allowed(snap_hndl, 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) +vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zone_did) { zoneid_t rval = -1; priv_set_t *privs; @@ -4673,7 +4557,7 @@ vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd) tsol_zcent_t *zcent = NULL; int match = 0; int doi = 0; - int flags; + int flags = -1; zone_iptype_t iptype; if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) { @@ -4695,6 +4579,8 @@ vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd) flags = ZCF_NET_EXCL; break; } + if (flags == -1) + abort(); if ((privs = priv_allocset()) == NULL) { zerror(zlogp, B_TRUE, "%s failed", "priv_allocset"); @@ -4798,7 +4684,7 @@ vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd) xerr = 0; if ((zoneid = zone_create(kzone, rootpath, privs, rctlbuf, rctlbufsz, zfsbuf, zfsbufsz, &xerr, match, doi, zlabel, - flags)) == -1) { + flags, zone_did)) == -1) { if (xerr == ZE_AREMOUNTS) { if (zonecfg_find_mounts(rootpath, NULL, NULL) < 1) { zerror(zlogp, B_FALSE, @@ -4844,7 +4730,7 @@ vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd) struct brand_attr attr; char modname[MAXPATHLEN]; - if (setup_zone_attrs(zlogp, zone_name, zoneid) != Z_OK) + if (setup_zone_attrs(zlogp, zoneid) != Z_OK) goto error; if ((bh = brand_open(brand_name)) == NULL) { @@ -4902,6 +4788,8 @@ error: } if (rctlbuf != NULL) free(rctlbuf); + if (zfsbuf != NULL) + free(zfsbuf); priv_freeset(privs); if (fp != NULL) zonecfg_close_scratch(fp); @@ -4990,7 +4878,7 @@ write_index_file(zoneid_t zoneid) int vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid) { - char zonepath[MAXPATHLEN]; + char zpath[MAXPATHLEN]; if (mount_cmd == Z_MNT_BOOT && validate_datasets(zlogp) != 0) { lofs_discard_mnttab(); @@ -5001,15 +4889,11 @@ vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid) * 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)); + (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, zonepath, "/dev", DEFAULT_DIR_MODE, - 0, 3) != 0) { + if (make_one_dir(zlogp, zpath, "/dev", DEFAULT_DIR_MODE, 0, 3) != 0) { lofs_discard_mnttab(); return (-1); } @@ -5044,6 +4928,8 @@ vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid) return (-1); } break; + default: + abort(); } } @@ -5119,13 +5005,13 @@ unmounted: } int -vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) +vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, + boolean_t debug) { 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; @@ -5158,16 +5044,12 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) 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 @@ -5181,12 +5063,6 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) 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"); @@ -5197,7 +5073,7 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) * brand a chance to cleanup any custom configuration. */ (void) strcpy(cmdbuf, EXEC_PREFIX); - if (brand_get_halt(bh, zone_name, zpath, cmdbuf + EXEC_LEN, + 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 " @@ -5207,7 +5083,7 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) brand_close(bh); if ((strlen(cmdbuf) > EXEC_LEN) && - (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) { + (do_subproc(zlogp, cmdbuf, NULL, debug) != Z_OK)) { zerror(zlogp, B_FALSE, "%s failed", cmdbuf); goto error; } @@ -5239,12 +5115,6 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) } 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 " @@ -5281,14 +5151,9 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting) if (rebooting) { struct zone_psettab pset_tab; - zone_dochandle_t handle; - if ((handle = zonecfg_init_handle()) != NULL && - zonecfg_get_handle(zone_name, handle) == Z_OK && - zonecfg_lookup_pset(handle, &pset_tab) == Z_OK) + if (zonecfg_lookup_pset(snap_hndl, &pset_tab) == Z_OK) destroy_tmp_pool = B_FALSE; - - zonecfg_fini_handle(handle); } if (destroy_tmp_pool) { |