diff options
| author | carlsonj <none@none> | 2005-10-27 04:35:13 -0700 |
|---|---|---|
| committer | carlsonj <none@none> | 2005-10-27 04:35:13 -0700 |
| commit | 108322fb1c3ed341aba9c80c9774df0ed9e35768 (patch) | |
| tree | 61abe7b187db6042e0a010756a82a6c7d9d9c5ad /usr/src | |
| parent | ed9df62ee8252b9df6f24409276deabf199dcd40 (diff) | |
| download | illumos-joyent-108322fb1c3ed341aba9c80c9774df0ed9e35768.tar.gz | |
PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
6328286 need scratch zone support for upgrade
6328296 need temporary NFS feature to support cross-zone traffic in miniroot environment (only)
6328310 zone_destroy shouldn't camp on the root vnode
6329667 zoneadm fails, but still exits with status zero
Diffstat (limited to 'usr/src')
40 files changed, 2358 insertions, 624 deletions
diff --git a/usr/src/cmd/zlogin/zlogin.c b/usr/src/cmd/zlogin/zlogin.c index 3332a5fa55..a48d10c310 100644 --- a/usr/src/cmd/zlogin/zlogin.c +++ b/usr/src/cmd/zlogin/zlogin.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1342,13 +1342,15 @@ main(int argc, char **argv) char *slavename, slaveshortname[MAXPATHLEN]; priv_set_t *privset; int tmpl_fd; + struct stat sb; + char kernzone[ZONENAME_MAX]; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); (void) getpname(argv[0]); - while ((arg = getopt(argc, argv, "ECSe:l:")) != EOF) { + while ((arg = getopt(argc, argv, "ECR:Se:l:")) != EOF) { switch (arg) { case 'C': console = 1; @@ -1356,6 +1358,18 @@ main(int argc, char **argv) case 'E': nocmdchar = 1; break; + case 'R': /* undocumented */ + if (*optarg != '/') { + zerror(gettext("root path must be absolute.")); + exit(2); + } + if (stat(optarg, &sb) == -1 || !S_ISDIR(sb.st_mode)) { + zerror( + gettext("root path must be a directory.")); + exit(2); + } + zonecfg_set_root(optarg); + break; case 'S': failsafe = 1; break; @@ -1381,6 +1395,11 @@ main(int argc, char **argv) usage(); } + if (console != 0 && zonecfg_in_alt_root()) { + zerror(gettext("-R may not be specified for console login")); + exit(2); + } + if (failsafe != 0 && lflag != 0) { zerror(gettext("-l may not be specified for failsafe login")); usage(); @@ -1503,22 +1522,36 @@ main(int argc, char **argv) return (0); } - if (st != ZONE_STATE_RUNNING) { + if (st != ZONE_STATE_RUNNING && st != ZONE_STATE_MOUNTED) { zerror(gettext("login allowed only to running zones " "(%s is '%s')."), zonename, zone_state_str(st)); return (1); } - /* - * We only need the zone root path and zoneid if we are setting up a - * pty. - */ - if ((zoneid = getzoneidbyname(zonename)) == -1) { + (void) strlcpy(kernzone, zonename, sizeof (kernzone)); + if (zonecfg_in_alt_root()) { + FILE *fp = zonecfg_open_scratch("", B_FALSE); + + if (fp == NULL || zonecfg_find_scratch(fp, zonename, + zonecfg_get_root(), kernzone, sizeof (kernzone)) == -1) { + zerror(gettext("cannot find scratch zone %s"), + zonename); + if (fp != NULL) + zonecfg_close_scratch(fp); + return (1); + } + zonecfg_close_scratch(fp); + } + + if ((zoneid = getzoneidbyname(kernzone)) == -1) { zerror(gettext("failed to get zoneid for zone '%s'"), zonename); return (1); } + /* + * We need the zone path only if we are setting up a pty. + */ if (zone_get_zonepath(zonename, zonepath, sizeof (zonepath)) == -1) { zerror(gettext("could not get root path for zone %s"), zonename); @@ -1539,6 +1572,12 @@ main(int argc, char **argv) return (noninteractive_login(zonename, zoneid, login, new_args, new_env)); + if (zonecfg_in_alt_root()) { + zerror(gettext("cannot use interactive login with scratch " + "zone")); + return (1); + } + /* * Things are more complex in interactive mode; we get the * master side of the pty, then place the user's terminal into diff --git a/usr/src/cmd/zoneadm/zoneadm.c b/usr/src/cmd/zoneadm/zoneadm.c index 4a0b9eae44..287aa4ca95 100644 --- a/usr/src/cmd/zoneadm/zoneadm.c +++ b/usr/src/cmd/zoneadm/zoneadm.c @@ -108,9 +108,11 @@ static size_t nzents; #define CMD_VERIFY 6 #define CMD_INSTALL 7 #define CMD_UNINSTALL 8 +#define CMD_MOUNT 9 +#define CMD_UNMOUNT 10 #define CMD_MIN CMD_HELP -#define CMD_MAX CMD_UNINSTALL +#define CMD_MAX CMD_UNMOUNT struct cmd { uint_t cmd_num; /* command number */ @@ -139,6 +141,8 @@ static int list_func(int argc, char *argv[]); static int verify_func(int argc, char *argv[]); static int install_func(int argc, char *argv[]); static int uninstall_func(int argc, char *argv[]); +static int mount_func(int argc, char *argv[]); +static int unmount_func(int argc, char *argv[]); static int sanity_check(char *zone, int cmd_num, boolean_t running, boolean_t unsafe_when_running); static int cmd_match(char *cmd); @@ -154,7 +158,10 @@ static struct cmd cmdtab[] = { { CMD_VERIFY, "verify", SHELP_VERIFY, verify_func }, { CMD_INSTALL, "install", SHELP_INSTALL, install_func }, { CMD_UNINSTALL, "uninstall", SHELP_UNINSTALL, - uninstall_func } + uninstall_func }, + /* Private commands for admin/install */ + { CMD_MOUNT, "mount", NULL, mount_func }, + { CMD_UNMOUNT, "unmount", NULL, unmount_func } }; /* global variables */ @@ -226,6 +233,8 @@ long_help(int cmd_num) return (gettext("Uninstall the configuration from the " "system. The -F flag can be used\n\tto force the " "action.")); + default: + return (""); } /* NOTREACHED */ return (NULL); @@ -248,6 +257,8 @@ usage(boolean_t explicit) gettext("subcommand")); (void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands")); for (i = CMD_MIN; i <= CMD_MAX; i++) { + if (cmdtab[i].short_usage == NULL) + continue; (void) fprintf(fd, "%s\n", cmdtab[i].short_usage); if (explicit) (void) fprintf(fd, "\t%s\n\n", long_help(i)); @@ -356,7 +367,7 @@ zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable) } static int -lookup_zone_info(char *zone_name, zone_entry_t *zent) +lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent) { char root[MAXPATHLEN]; int err; @@ -365,8 +376,7 @@ lookup_zone_info(char *zone_name, zone_entry_t *zent) (void) strlcpy(zent->zroot, "???", sizeof (zent->zroot)); zent->zstate_str = "???"; - if ((zent->zid = getzoneidbyname(zone_name)) == -1) - zent->zid = ZONE_ID_UNDEFINED; + zent->zid = zid; if ((err = zone_get_zonepath(zent->zname, root, sizeof (root))) != Z_OK) { @@ -395,11 +405,14 @@ lookup_zone_info(char *zone_name, zone_entry_t *zent) */ static int -fetch_zents() +fetch_zents(void) { zoneid_t *zids = NULL; uint_t nzents_saved; - int i; + int i, retv; + FILE *fp; + boolean_t inaltroot; + zone_entry_t *zentp; if (nzents > 0) return (Z_OK); @@ -429,20 +442,56 @@ again: zents = safe_calloc(nzents, sizeof (zone_entry_t)); + inaltroot = zonecfg_in_alt_root(); + if (inaltroot) + fp = zonecfg_open_scratch("", B_FALSE); + else + fp = NULL; + zentp = zents; + retv = Z_OK; for (i = 0; i < nzents; i++) { char name[ZONENAME_MAX]; + char altname[ZONENAME_MAX]; - if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) + if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) { zperror(gettext("failed to get zone name"), B_FALSE); - else if (lookup_zone_info(name, &zents[i]) != Z_OK) - zerror(gettext("failed to get zone list")); + retv = Z_ERR; + continue; + } + if (zonecfg_is_scratch(name)) { + /* Ignore scratch zones by default */ + if (!inaltroot) + continue; + if (fp == NULL || + zonecfg_reverse_scratch(fp, name, altname, + sizeof (altname), NULL, 0) == -1) { + zerror(gettext("cannot resolve scratch " + "zone %s"), name); + retv = Z_ERR; + continue; + } + (void) strcpy(name, altname); + } else { + /* Ignore non-scratch when in an alternate root */ + if (inaltroot && strcmp(name, GLOBAL_ZONENAME) != 0) + continue; + } + if (lookup_zone_info(name, zids[i], zentp) != Z_OK) { + zerror(gettext("failed to get zone data")); + retv = Z_ERR; + continue; + } + zentp++; } + nzents = zentp - zents; + if (fp != NULL) + zonecfg_close_scratch(fp); free(zids); - return (Z_OK); + return (retv); } -static void +static int zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable) { int i; @@ -454,22 +503,17 @@ zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable) * First get the list of running zones from the kernel and print them. * If that is all we need, then return. */ - if (fetch_zents() != Z_OK) { + if ((i = fetch_zents()) != Z_OK) { /* * No need for error messages; fetch_zents() has already taken * care of this. */ - return; + return (i); } - for (i = 0; i < nzents; i++) { - if (!verbose && !parsable) { - zone_print(&zents[i], verbose, parsable); - continue; - } + for (i = 0; i < nzents; i++) zone_print(&zents[i], verbose, parsable); - } if (min_state >= ZONE_STATE_RUNNING) - return; + return (Z_OK); /* * Next, get the full list of zones from the configuration, skipping * any we have already printed. @@ -484,7 +528,7 @@ zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable) free(name); continue; } - if (lookup_zone_info(name, &zent) != Z_OK) { + if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) { free(name); continue; } @@ -493,6 +537,7 @@ zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable) zone_print(&zent, verbose, parsable); } endzoneent(cookie); + return (Z_OK); } static zone_entry_t * @@ -635,16 +680,18 @@ crosscheck_zonepaths(char *path) continue; } } - res = resolvepath(ze->zone_path, rpath, sizeof (rpath)); + (void) snprintf(path_copy, sizeof (path_copy), "%s%s", + zonecfg_get_root(), ze->zone_path); + res = resolvepath(path_copy, rpath, sizeof (rpath)); if (res == -1) { if (errno != ENOENT) { - zperror(ze->zone_path, B_FALSE); + zperror(path_copy, B_FALSE); free(ze); return (Z_ERR); } (void) printf(gettext("WARNING: zone %s is installed, " "but its %s %s does not exist.\n"), ze->zone_name, - "zonepath", ze->zone_path); + "zonepath", path_copy); free(ze); continue; } @@ -848,12 +895,17 @@ grab_lock_file(const char *zone_name, int *lockfd) char pathbuf[PATH_MAX]; struct flock flock; - if (mkdir(ZONES_TMPDIR, S_IRWXU) < 0 && errno != EEXIST) { - zerror(gettext("could not mkdir %s: %s"), ZONES_TMPDIR, + if (snprintf(pathbuf, sizeof (pathbuf), "%s%s", zonecfg_get_root(), + ZONES_TMPDIR) >= sizeof (pathbuf)) { + zerror(gettext("alternate root path is too long")); + return (Z_ERR); + } + if (mkdir(pathbuf, S_IRWXU) < 0 && errno != EEXIST) { + zerror(gettext("could not mkdir %s: %s"), pathbuf, strerror(errno)); return (Z_ERR); } - (void) chmod(ZONES_TMPDIR, S_IRWXU); + (void) chmod(pathbuf, S_IRWXU); /* * One of these lock files is created for each zone (when needed). @@ -861,8 +913,11 @@ grab_lock_file(const char *zone_name, int *lockfd) * but since there is only one per zone, there is no resource * starvation issue. */ - (void) snprintf(pathbuf, sizeof (pathbuf), "%s/%s.zoneadm.lock", - ZONES_TMPDIR, zone_name); + if (snprintf(pathbuf, sizeof (pathbuf), "%s%s/%s.zoneadm.lock", + zonecfg_get_root(), ZONES_TMPDIR, zone_name) >= sizeof (pathbuf)) { + zerror(gettext("alternate root path is too long")); + return (Z_ERR); + } if ((*lockfd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { zerror(gettext("could not open %s: %s"), pathbuf, strerror(errno)); @@ -884,10 +939,11 @@ grab_lock_file(const char *zone_name, int *lockfd) return (Z_OK); } -static void +static boolean_t get_doorname(const char *zone_name, char *buffer) { - (void) snprintf(buffer, PATH_MAX, ZONE_DOOR_PATH, zone_name); + return (snprintf(buffer, PATH_MAX, "%s" ZONE_DOOR_PATH, + zonecfg_get_root(), zone_name) < PATH_MAX); } /* @@ -931,7 +987,8 @@ start_zoneadmd(const char *zone_name) int doorfd, lockfd; struct door_info info; - get_doorname(zone_name, doorpath); + if (!get_doorname(zone_name, doorpath)) + return (Z_ERR); if (grab_lock_file(zone_name, &lockfd) != Z_OK) return (Z_ERR); @@ -960,12 +1017,22 @@ start_zoneadmd(const char *zone_name) zperror(gettext("could not fork"), B_FALSE); goto out; } else if (child_pid == 0) { - /* child process */ + const char *argv[6], **ap; + /* child process */ prepare_audit_context(); - (void) execl("/usr/lib/zones/zoneadmd", "zoneadmd", "-z", - zone_name, NULL); + ap = argv; + *ap++ = "zoneadmd"; + *ap++ = "-z"; + *ap++ = zone_name; + if (zonecfg_in_alt_root()) { + *ap++ = "-R"; + *ap++ = zonecfg_get_root(); + } + *ap = NULL; + + (void) execv("/usr/lib/zones/zoneadmd", (char * const *)argv); zperror(gettext("could not exec zoneadmd"), B_FALSE); _exit(Z_ERR); } else { @@ -995,7 +1062,8 @@ ping_zoneadmd(const char *zone_name) int doorfd; struct door_info info; - get_doorname(zone_name, doorpath); + if (!get_doorname(zone_name, doorpath)) + return (Z_ERR); if ((doorfd = open(doorpath, O_RDONLY)) < 0) { return (Z_ERR); @@ -1036,7 +1104,11 @@ call_zoneadmd(const char *zone_name, zone_cmd_arg_t *arg) } arg->uniqid = uniqid; (void) strlcpy(arg->locale, locale, sizeof (arg->locale)); - get_doorname(zone_name, doorpath); + if (!get_doorname(zone_name, doorpath)) { + zerror(gettext("alternate root path is too long")); + free(rvalp); + return (-1); + } /* * Loop trying to start zoneadmd; if something goes seriously @@ -1104,6 +1176,11 @@ ready_func(int argc, char *argv[]) zone_cmd_arg_t zarg; int arg; + if (zonecfg_in_alt_root()) { + zerror(gettext("cannot ready zone in alternate root")); + return (Z_ERR); + } + optind = 0; if ((arg = getopt(argc, argv, "?")) != EOF) { switch (arg) { @@ -1138,6 +1215,11 @@ boot_func(int argc, char *argv[]) zone_cmd_arg_t zarg; int arg; + if (zonecfg_in_alt_root()) { + zerror(gettext("cannot boot zone in alternate root")); + return (Z_ERR); + } + zarg.bootbuf[0] = '\0'; /* @@ -1197,7 +1279,7 @@ static int list_func(int argc, char *argv[]) { zone_entry_t *zentp, zent; - int arg; + int arg, retv; boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE; zone_state_t min_state = ZONE_STATE_RUNNING; zoneid_t zone_id = getzoneid(); @@ -1233,12 +1315,13 @@ list_func(int argc, char *argv[]) return (Z_ERR); } if (zone_id == GLOBAL_ZONEID) { - zone_print_list(min_state, verbose, parsable); + retv = zone_print_list(min_state, verbose, parsable); } else { + retv = Z_OK; fake_up_local_zone(zone_id, &zent); zone_print(&zent, verbose, parsable); } - return (Z_OK); + return (retv); } /* @@ -1284,7 +1367,8 @@ list_func(int argc, char *argv[]) } else if ((zentp = lookup_running_zone(target_zone)) != NULL) { zone_print(zentp, verbose, parsable); output = B_TRUE; - } else if (lookup_zone_info(target_zone, &zent) == Z_OK) { + } else if (lookup_zone_info(target_zone, ZONE_ID_UNDEFINED, + &zent) == Z_OK) { zone_print(&zent, verbose, parsable); output = B_TRUE; } @@ -1380,6 +1464,8 @@ sanity_check(char *zone, int cmd_num, boolean_t running, zone_entry_t *zent; priv_set_t *privset; zone_state_t state; + char kernzone[ZONENAME_MAX]; + FILE *fp; if (getzoneid() != GLOBAL_ZONEID) { zerror(gettext("must be in the global zone to %s a zone."), @@ -1411,10 +1497,7 @@ sanity_check(char *zone, int cmd_num, boolean_t running, return (Z_ERR); } - zent = lookup_running_zone(zone); - if (strcmp(zone, GLOBAL_ZONENAME) == 0) { - assert((zent != NULL) && (zent->zid == GLOBAL_ZONEID)); zerror(gettext("%s operation is invalid for the global zone."), cmd_to_str(cmd_num)); return (Z_ERR); @@ -1426,6 +1509,19 @@ sanity_check(char *zone, int cmd_num, boolean_t running, return (Z_ERR); } + if (!zonecfg_in_alt_root()) { + zent = lookup_running_zone(zone); + } else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) { + zent = NULL; + } else { + if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(), + kernzone, sizeof (kernzone)) == 0) + zent = lookup_running_zone(kernzone); + else + zent = NULL; + zonecfg_close_scratch(fp); + } + /* * Look up from the kernel for 'running' zones. */ @@ -1481,6 +1577,7 @@ sanity_check(char *zone, int cmd_num, boolean_t running, break; case CMD_READY: case CMD_BOOT: + case CMD_MOUNT: if (state < ZONE_STATE_INSTALLED) { zerror(gettext("must be %s before %s."), zone_state_str(ZONE_STATE_INSTALLED), @@ -1496,6 +1593,14 @@ sanity_check(char *zone, int cmd_num, boolean_t running, return (Z_ERR); } break; + case CMD_UNMOUNT: + if (state != ZONE_STATE_MOUNTED) { + zerror(gettext("must be %s before %s."), + zone_state_str(ZONE_STATE_MOUNTED), + cmd_to_str(cmd_num)); + return (Z_ERR); + } + break; } } return (Z_OK); @@ -1507,6 +1612,11 @@ halt_func(int argc, char *argv[]) zone_cmd_arg_t zarg; int arg; + if (zonecfg_in_alt_root()) { + zerror(gettext("cannot halt zone in alternate root")); + return (Z_ERR); + } + optind = 0; if ((arg = getopt(argc, argv, "?")) != EOF) { switch (arg) { @@ -1540,6 +1650,11 @@ reboot_func(int argc, char *argv[]) zone_cmd_arg_t zarg; int arg; + if (zonecfg_in_alt_root()) { + zerror(gettext("cannot reboot zone in alternate root")); + return (Z_ERR); + } + optind = 0; if ((arg = getopt(argc, argv, "?")) != EOF) { switch (arg) { @@ -1792,6 +1907,7 @@ verify_details(int cmd_num) char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN]; int return_code = Z_OK; int err; + boolean_t in_alt_root; if ((handle = zonecfg_init_handle()) == NULL) { zperror(cmd_to_str(cmd_num), B_TRUE); @@ -1834,6 +1950,10 @@ verify_details(int cmd_num) return_code = Z_ERR; } + in_alt_root = zonecfg_in_alt_root(); + if (in_alt_root) + goto no_net; + if ((err = zonecfg_setnwifent(handle)) != Z_OK) { errno = err; zperror(cmd_to_str(cmd_num), B_TRUE); @@ -1881,12 +2001,13 @@ verify_details(int cmd_num) (void) close(so); } (void) zonecfg_endnwifent(handle); +no_net: if (verify_filesystems(handle) != Z_OK) return_code = Z_ERR; - if (verify_rctls(handle) != Z_OK) + if (!in_alt_root && verify_rctls(handle) != Z_OK) return_code = Z_ERR; - if (verify_pool(handle) != Z_OK) + if (!in_alt_root && verify_pool(handle) != Z_OK) return_code = Z_ERR; zonecfg_fini_handle(handle); if (return_code == Z_ERR) @@ -1933,6 +2054,11 @@ install_func(int argc, char *argv[]) char zonepath[MAXPATHLEN]; int status; + if (zonecfg_in_alt_root()) { + zerror(gettext("cannot install zone in alternate root")); + return (Z_ERR); + } + optind = 0; if ((arg = getopt(argc, argv, "?")) != EOF) { switch (arg) { @@ -2059,6 +2185,11 @@ uninstall_func(int argc, char *argv[]) int err, arg; int status; + if (zonecfg_in_alt_root()) { + zerror(gettext("cannot uninstall zone in alternate root")); + return (Z_ERR); + } + optind = 0; while ((arg = getopt(argc, argv, "?F")) != EOF) { switch (arg) { @@ -2167,6 +2298,46 @@ bad: return (err); } +/* ARGSUSED */ +static int +mount_func(int argc, char *argv[]) +{ + zone_cmd_arg_t zarg; + + if (argc > 0) + return (Z_USAGE); + if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE) != Z_OK) + return (Z_ERR); + if (verify_details(CMD_MOUNT) != Z_OK) + return (Z_ERR); + + zarg.cmd = Z_MOUNT; + if (call_zoneadmd(target_zone, &zarg) != 0) { + zerror(gettext("call to %s failed"), "zoneadmd"); + return (Z_ERR); + } + return (Z_OK); +} + +/* ARGSUSED */ +static int +unmount_func(int argc, char *argv[]) +{ + zone_cmd_arg_t zarg; + + if (argc > 0) + return (Z_USAGE); + if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE) != Z_OK) + return (Z_ERR); + + zarg.cmd = Z_UNMOUNT; + if (call_zoneadmd(target_zone, &zarg) != 0) { + zerror(gettext("call to %s failed"), "zoneadmd"); + return (Z_ERR); + } + return (Z_OK); +} + static int help_func(int argc, char *argv[]) { @@ -2253,6 +2424,7 @@ main(int argc, char **argv) { int arg; zoneid_t zid; + struct stat st; if ((locale = setlocale(LC_ALL, "")) == NULL) locale = "C"; @@ -2266,13 +2438,25 @@ main(int argc, char **argv) exit(Z_ERR); } - while ((arg = getopt(argc, argv, "?z:")) != EOF) { + while ((arg = getopt(argc, argv, "?z:R:")) != EOF) { switch (arg) { case '?': return (usage(B_TRUE)); case 'z': target_zone = optarg; break; + case 'R': /* private option for admin/install use */ + if (*optarg != '/') { + zerror(gettext("root path must be absolute.")); + exit(Z_ERR); + } + if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) { + zerror( + gettext("root path must be a directory.")); + exit(Z_ERR); + } + zonecfg_set_root(optarg); + break; default: return (usage(B_FALSE)); } diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c index 3b84bb82a0..75eca58961 100644 --- a/usr/src/cmd/zoneadmd/vplat.c +++ b/usr/src/cmd/zoneadmd/vplat.c @@ -34,6 +34,33 @@ * the way up, ready the zone; on the way down, they halt the zone. * See the much longer block comment at the beginning of zoneadmd.c * for a bigger picture of how the whole program functions. + * + * This module also has primary responsibility for the layout of "scratch + * zones." These are mounted, but inactive, zones that are used during + * operating system upgrade and potentially other administrative action. The + * scratch zone environment is similar to the miniroot environment. The zone's + * actual root is mounted read-write on /a, and the standard paths (/usr, + * /sbin, /lib) all lead to read-only copies of the running system's binaries. + * This allows the administrative tools to manipulate the zone using "-R /a" + * without relying on any binaries in the zone itself. + * + * If the scratch zone is on an alternate root (Live Upgrade [LU] boot + * environment), then we must resolve the lofs mounts used there to uncover + * writable (unshared) resources. Shared resources, though, are always + * read-only. In addition, if the "same" zone with a different root path is + * currently running, then "/b" inside the zone points to the running zone's + * root. This allows LU to synchronize configuration files during the upgrade + * process. + * + * To construct this environment, this module creates a tmpfs mount on + * $ZONEPATH/lu. Inside this scratch area, the miniroot-like environment as + * described above is constructed on the fly. The zone is then created using + * $ZONEPATH/lu as the root. + * + * Note that scratch zones are inactive. The zone's bits are not running and + * likely cannot be run correctly until upgrade is done. Init is not running + * there, nor is SMF. Because of this, the "mounted" state of a scratch zone + * is not a part of the usual halt/ready/boot state machine. */ #include <sys/param.h> @@ -141,10 +168,22 @@ static struct symlink_info dev_symlinks[] = { /* for routing socket */ static int rts_seqno = 0; +/* mangled zone name when mounting in an alternate root environment */ +static char kernzone[ZONENAME_MAX]; + +/* array of cached mount entries for resolve_lofs */ +static struct mnttab *resolve_lofs_mnts, *resolve_lofs_mnt_max; + /* from libsocket, not in any header file */ extern int getnetmaskbyaddr(struct in_addr, struct in_addr *); /* + * An optimization for build_mnttable: reallocate (and potentially copy the + * data) only once every N times through the loop. + */ +#define MNTTAB_HUNK 32 + +/* * Private autofs system call */ extern int _autofssys(int, void *); @@ -158,6 +197,244 @@ autofs_cleanup(zoneid_t zoneid) return (_autofssys(AUTOFS_UNMOUNTALL, (void *)zoneid)); } +static void +free_mnttable(struct mnttab *mnt_array, uint_t nelem) +{ + uint_t i; + + if (mnt_array == NULL) + return; + for (i = 0; i < nelem; i++) { + free(mnt_array[i].mnt_mountp); + free(mnt_array[i].mnt_fstype); + free(mnt_array[i].mnt_special); + free(mnt_array[i].mnt_mntopts); + assert(mnt_array[i].mnt_time == NULL); + } + free(mnt_array); +} + +/* + * Build the mount table for the zone rooted at "zroot", storing the resulting + * array of struct mnttabs in "mnt_arrayp" and the number of elements in the + * array in "nelemp". + */ +static int +build_mnttable(zlog_t *zlogp, const char *zroot, size_t zrootlen, FILE *mnttab, + struct mnttab **mnt_arrayp, uint_t *nelemp) +{ + struct mnttab mnt; + struct mnttab *mnts; + struct mnttab *mnp; + uint_t nmnt; + + rewind(mnttab); + resetmnttab(mnttab); + nmnt = 0; + mnts = NULL; + while (getmntent(mnttab, &mnt) == 0) { + struct mnttab *tmp_array; + + if (strncmp(mnt.mnt_mountp, zroot, zrootlen) != 0) + continue; + if (nmnt % MNTTAB_HUNK == 0) { + tmp_array = realloc(mnts, + (nmnt + MNTTAB_HUNK) * sizeof (*mnts)); + if (tmp_array == NULL) { + free_mnttable(mnts, nmnt); + return (-1); + } + mnts = tmp_array; + } + mnp = &mnts[nmnt++]; + + /* + * Zero out any fields we're not using. + */ + (void) memset(mnp, 0, sizeof (*mnp)); + + if (mnt.mnt_special != NULL) + mnp->mnt_special = strdup(mnt.mnt_special); + if (mnt.mnt_mntopts != NULL) + mnp->mnt_mntopts = strdup(mnt.mnt_mntopts); + mnp->mnt_mountp = strdup(mnt.mnt_mountp); + mnp->mnt_fstype = strdup(mnt.mnt_fstype); + if ((mnt.mnt_special != NULL && mnp->mnt_special == NULL) || + (mnt.mnt_mntopts != NULL && mnp->mnt_mntopts == NULL) || + mnp->mnt_mountp == NULL || mnp->mnt_fstype == NULL) { + zerror(zlogp, B_TRUE, "memory allocation failed"); + free_mnttable(mnts, nmnt); + return (-1); + } + } + *mnt_arrayp = mnts; + *nelemp = nmnt; + return (0); +} + +/* + * This is an optimization. The resolve_lofs function is used quite frequently + * to manipulate file paths, and on a machine with a large number of zones, + * there will be a huge number of mounted file systems. Thus, we trigger a + * reread of the list of mount points + */ +static void +lofs_discard_mnttab(void) +{ + free_mnttable(resolve_lofs_mnts, + resolve_lofs_mnt_max - resolve_lofs_mnts); + resolve_lofs_mnts = resolve_lofs_mnt_max = NULL; +} + +static int +lofs_read_mnttab(zlog_t *zlogp) +{ + FILE *mnttab; + uint_t nmnts; + + if ((mnttab = fopen(MNTTAB, "r")) == NULL) + return (-1); + if (build_mnttable(zlogp, "", 0, mnttab, &resolve_lofs_mnts, + &nmnts) == -1) { + (void) fclose(mnttab); + return (-1); + } + (void) fclose(mnttab); + resolve_lofs_mnt_max = resolve_lofs_mnts + nmnts; + return (0); +} + +/* + * This function loops over potential loopback mounts and symlinks in a given + * path and resolves them all down to an absolute path. + */ +static void +resolve_lofs(zlog_t *zlogp, char *path, size_t pathlen) +{ + int len, arlen; + const char *altroot; + char tmppath[MAXPATHLEN]; + boolean_t outside_altroot; + + if ((len = resolvepath(path, tmppath, sizeof (tmppath))) == -1) + return; + tmppath[len] = '\0'; + (void) strlcpy(path, tmppath, sizeof (tmppath)); + + /* This happens once per zoneadmd operation. */ + if (resolve_lofs_mnts == NULL && lofs_read_mnttab(zlogp) == -1) + return; + + altroot = zonecfg_get_root(); + arlen = strlen(altroot); + outside_altroot = B_FALSE; + for (;;) { + struct mnttab *mnp; + + for (mnp = resolve_lofs_mnts; mnp < resolve_lofs_mnt_max; + mnp++) { + if (mnp->mnt_fstype == NULL || + mnp->mnt_mountp == NULL || + mnp->mnt_special == NULL || + strcmp(mnp->mnt_fstype, MNTTYPE_LOFS) != 0) + continue; + len = strlen(mnp->mnt_mountp); + if (strncmp(mnp->mnt_mountp, path, len) == 0 && + (path[len] == '/' || path[len] == '\0')) + break; + } + if (mnp >= resolve_lofs_mnt_max) + break; + if (outside_altroot) { + char *cp; + int olen = sizeof (MNTOPT_RO) - 1; + + /* + * If we run into a read-only mount outside of the + * alternate root environment, then the user doesn't + * want this path to be made read-write. + */ + if (mnp->mnt_mntopts != NULL && + (cp = strstr(mnp->mnt_mntopts, MNTOPT_RO)) != + NULL && + (cp == mnp->mnt_mntopts || cp[-1] == ',') && + (cp[olen] == '\0' || cp[olen] == ',')) { + break; + } + } else if (arlen > 0 && + (strncmp(mnp->mnt_special, altroot, arlen) != 0 || + (mnp->mnt_special[arlen] != '\0' && + mnp->mnt_special[arlen] != '/'))) { + outside_altroot = B_TRUE; + } + /* use temporary buffer because new path might be longer */ + (void) snprintf(tmppath, sizeof (tmppath), "%s%s", + mnp->mnt_special, path + len); + if ((len = resolvepath(tmppath, path, pathlen)) == -1) + break; + path[len] = '\0'; + } +} + +/* + * For a regular mount, check if a replacement lofs mount is needed because the + * referenced device is already mounted somewhere. + */ +static int +check_lofs_needed(zlog_t *zlogp, struct zone_fstab *fsptr) +{ + struct mnttab *mnp; + zone_fsopt_t *optptr, *onext; + + /* This happens once per zoneadmd operation. */ + if (resolve_lofs_mnts == NULL && lofs_read_mnttab(zlogp) == -1) + return (-1); + + /* + * If this special node isn't already in use, then it's ours alone; + * no need to worry about conflicting mounts. + */ + for (mnp = resolve_lofs_mnts; mnp < resolve_lofs_mnt_max; + mnp++) { + if (strcmp(mnp->mnt_special, fsptr->zone_fs_special) == 0) + break; + } + if (mnp >= resolve_lofs_mnt_max) + return (0); + + /* + * Convert this duplicate mount into a lofs mount. + */ + (void) strlcpy(fsptr->zone_fs_special, mnp->mnt_mountp, + sizeof (fsptr->zone_fs_special)); + (void) strlcpy(fsptr->zone_fs_type, MNTTYPE_LOFS, + sizeof (fsptr->zone_fs_type)); + fsptr->zone_fs_raw[0] = '\0'; + + /* + * Discard all but one of the original options and set that to be the + * same set of options used for inherit package directory resources. + */ + optptr = fsptr->zone_fs_options; + if (optptr == NULL) { + optptr = malloc(sizeof (*optptr)); + if (optptr == NULL) { + zerror(zlogp, B_TRUE, "cannot mount %s", + fsptr->zone_fs_dir); + return (-1); + } + } else { + while ((onext = optptr->zone_fsopt_next) != NULL) { + optptr->zone_fsopt_next = onext->zone_fsopt_next; + free(onext); + } + } + (void) strcpy(optptr->zone_fsopt_opt, IPD_DEFAULT_OPTS); + optptr->zone_fsopt_next = NULL; + fsptr->zone_fs_options = optptr; + return (0); +} + static int make_one_dir(zlog_t *zlogp, const char *prefix, const char *subdir, mode_t mode) { @@ -237,8 +514,9 @@ make_dev_links(zlog_t *zlogp, char *zonepath) (void) unlink(dev); } if (symlink(dev_symlinks[i].sl_target, dev) != 0) { - zerror(zlogp, B_TRUE, "could not setup %s symlink", - dev_symlinks[i].sl_source); + zerror(zlogp, B_TRUE, "could not setup %s->%s symlink", + dev_symlinks[i].sl_source, + dev_symlinks[i].sl_target); return (-1); } } @@ -257,6 +535,8 @@ create_dev_files(zlog_t *zlogp) zerror(zlogp, B_TRUE, "unable to determine zone root"); return (-1); } + if (zonecfg_in_alt_root()) + resolve_lofs(zlogp, zonepath, sizeof (zonepath)); if (make_dev_dirs(zlogp, zonepath) != 0) return (-1); @@ -344,74 +624,16 @@ is_remote_fstype(const char *fstype, char *const *remote_fstypes) return (B_FALSE); } -static void -free_mnttable(struct mnttab *mnt_array, uint_t nelem) -{ - uint_t i; - - if (mnt_array == NULL) - return; - for (i = 0; i < nelem; i++) { - free(mnt_array[i].mnt_mountp); - free(mnt_array[i].mnt_fstype); - assert(mnt_array[i].mnt_special == NULL); - assert(mnt_array[i].mnt_mntopts == NULL); - assert(mnt_array[i].mnt_time == NULL); - } - free(mnt_array); -} - /* - * Build the mount table for the zone rooted at "zroot", storing the resulting - * array of struct mnttabs in "mnt_arrayp" and the number of elements in the - * array in "nelemp". + * This converts a zone root path (normally of the form .../root) to a Live + * Upgrade scratch zone root (of the form .../lu). */ -static int -build_mnttable(zlog_t *zlogp, const char *zroot, size_t zrootlen, FILE *mnttab, - struct mnttab **mnt_arrayp, uint_t *nelemp) +static void +root_to_lu(zlog_t *zlogp, char *zroot, size_t zrootlen, boolean_t isresolved) { - struct mnttab mnt; - struct mnttab *mnts; - struct mnttab *mnp; - uint_t nmnt; - - rewind(mnttab); - resetmnttab(mnttab); - nmnt = 0; - mnts = NULL; - while (getmntent(mnttab, &mnt) == 0) { - struct mnttab *tmp_array; - - if (strncmp(mnt.mnt_mountp, zroot, zrootlen) != 0) - continue; - nmnt++; - tmp_array = realloc(mnts, nmnt * sizeof (*mnts)); - if (tmp_array == NULL) { - nmnt--; - free_mnttable(mnts, nmnt); - return (-1); - } - mnts = tmp_array; - mnp = &mnts[nmnt - 1]; - /* - * Zero out the fields we won't be using. - */ - mnp->mnt_special = NULL; - mnp->mnt_mntopts = NULL; - mnp->mnt_time = NULL; - - mnp->mnt_mountp = strdup(mnt.mnt_mountp); - mnp->mnt_fstype = strdup(mnt.mnt_fstype); - if (mnp->mnt_mountp == NULL || - mnp->mnt_fstype == NULL) { - zerror(zlogp, B_TRUE, "memory allocation failed"); - free_mnttable(mnts, nmnt); - return (-1); - } - } - *mnt_arrayp = mnts; - *nelemp = nmnt; - return (0); + if (!isresolved && zonecfg_in_alt_root()) + resolve_lofs(zlogp, zroot, zrootlen); + (void) strcpy(strrchr(zroot, '/') + 1, "lu"); } /* @@ -444,9 +666,8 @@ build_mnttable(zlog_t *zlogp, const char *zroot, size_t zrootlen, FILE *mnttab, * Zone must be down (ie, no processes or threads active). */ static int -unmount_filesystems(zlog_t *zlogp) +unmount_filesystems(zlog_t *zlogp, zoneid_t zoneid, boolean_t unmount_cmd) { - zoneid_t zoneid; int error = 0; FILE *mnttab; struct mnttab *mnts; @@ -457,15 +678,12 @@ unmount_filesystems(zlog_t *zlogp) boolean_t stuck = B_FALSE; char **remote_fstypes = NULL; - if ((zoneid = getzoneidbyname(zone_name)) == -1) { - zerror(zlogp, B_TRUE, "unable to find zoneid"); - return (-1); - } - if (zone_get_rootpath(zone_name, zroot, sizeof (zroot)) != Z_OK) { zerror(zlogp, B_FALSE, "unable to determine zone root"); return (-1); } + if (unmount_cmd) + root_to_lu(zlogp, zroot, sizeof (zroot), B_FALSE); (void) strcat(zroot, "/"); zrootlen = strlen(zroot); @@ -796,6 +1014,7 @@ static int mount_one(zlog_t *zlogp, struct zone_fstab *fsptr, const char *rootpath) { char path[MAXPATHLEN]; + char specpath[MAXPATHLEN]; char optstr[MAX_MNTOPT_STR]; zone_fsopt_t *optptr; @@ -815,12 +1034,22 @@ mount_one(zlog_t *zlogp, struct zone_fstab *fsptr, const char *rootpath) if (strlen(fsptr->zone_fs_special) == 0) { /* * A zero-length special is how we distinguish IPDs from - * general-purpose FSs. + * general-purpose FSs. Make sure it mounts from a place that + * can be seen via the alternate zone's root. */ + if (snprintf(specpath, sizeof (specpath), "%s%s", + zonecfg_get_root(), fsptr->zone_fs_dir) >= + sizeof (specpath)) { + zerror(zlogp, B_FALSE, "cannot mount %s: path too " + "long in alternate root", fsptr->zone_fs_dir); + return (-1); + } + if (zonecfg_in_alt_root()) + resolve_lofs(zlogp, specpath, sizeof (specpath)); if (domount(zlogp, MNTTYPE_LOFS, IPD_DEFAULT_OPTS, - fsptr->zone_fs_dir, path) != 0) { + specpath, path) != 0) { zerror(zlogp, B_TRUE, "failed to loopback mount %s", - fsptr->zone_fs_dir); + specpath); return (-1); } return (0); @@ -843,6 +1072,36 @@ mount_one(zlog_t *zlogp, struct zone_fstab *fsptr, const char *rootpath) } /* + * If we're looking at an alternate root environment, then construct + * read-only loopback mounts as necessary. For all lofs mounts, make + * sure that the 'special' entry points inside the alternate root. (We + * don't do this with other mounts, as devfs isn't in the alternate + * root, and we need to assume the device environment is roughly the + * same.) + */ + if (zonecfg_in_alt_root()) { + struct stat64 st; + + if (stat64(fsptr->zone_fs_special, &st) != -1 && + S_ISBLK(st.st_mode) && + check_lofs_needed(zlogp, fsptr) == -1) + return (-1); + if (strcmp(fsptr->zone_fs_type, MNTTYPE_LOFS) == 0) { + if (snprintf(specpath, sizeof (specpath), "%s%s", + zonecfg_get_root(), fsptr->zone_fs_special) >= + sizeof (specpath)) { + zerror(zlogp, B_FALSE, "cannot mount %s: path " + "too long in alternate root", + fsptr->zone_fs_special); + return (-1); + } + resolve_lofs(zlogp, specpath, sizeof (specpath)); + (void) strlcpy(fsptr->zone_fs_special, specpath, + sizeof (fsptr->zone_fs_special)); + } + } + + /* * Run 'fsck -m' if there's a device to fsck. */ if (fsptr->zone_fs_raw[0] != '\0' && @@ -879,8 +1138,174 @@ free_fs_data(struct zone_fstab *fsarray, uint_t nelem) free(fsarray); } +/* + * This function constructs the miniroot-like "scratch zone" environment. If + * it returns B_FALSE, then the error has already been logged. + */ +static boolean_t +build_mounted(zlog_t *zlogp, char *rootpath, size_t rootlen, + const char *zonepath) +{ + char tmp[MAXPATHLEN], fromdir[MAXPATHLEN]; + char luroot[MAXPATHLEN]; + const char **cpp; + static const char *mkdirs[] = { + "/system", "/system/contract", "/proc", "/dev", "/tmp", + "/a", NULL + }; + static const char *localdirs[] = { + "/etc", "/var", NULL + }; + static const char *loopdirs[] = { + "/etc/lib", "/etc/fs", "/lib", "/sbin", "/platform", + "/usr", NULL + }; + static const char *tmpdirs[] = { + "/tmp", "/var/run", NULL + }; + FILE *fp; + struct stat st; + char *altstr; + uuid_t uuid; + + /* + * Construct a small Solaris environment, including the zone root + * mounted on '/a' inside that environment. + */ + resolve_lofs(zlogp, rootpath, rootlen); + (void) snprintf(luroot, sizeof (luroot), "%s/lu", zonepath); + resolve_lofs(zlogp, luroot, sizeof (luroot)); + (void) snprintf(tmp, sizeof (tmp), "%s/bin", luroot); + (void) symlink("./usr/bin", tmp); + + /* + * These are mostly special mount points; not handled here. (See + * zone_mount_early.) + */ + for (cpp = mkdirs; *cpp != NULL; cpp++) { + (void) snprintf(tmp, sizeof (tmp), "%s%s", luroot, *cpp); + if (mkdir(tmp, 0755) != 0) { + zerror(zlogp, B_TRUE, "cannot create %s", tmp); + return (B_FALSE); + } + } + + /* + * These are mounted read-write from the zone undergoing upgrade. We + * must be careful not to 'leak' things from the main system into the + * zone, and this accomplishes that goal. + */ + for (cpp = localdirs; *cpp != NULL; cpp++) { + (void) snprintf(tmp, sizeof (tmp), "%s%s", luroot, *cpp); + (void) snprintf(fromdir, sizeof (fromdir), "%s%s", rootpath, + *cpp); + if (mkdir(tmp, 0755) != 0) { + zerror(zlogp, B_TRUE, "cannot create %s", tmp); + return (B_FALSE); + } + if (domount(zlogp, MNTTYPE_LOFS, "", fromdir, tmp) != 0) { + zerror(zlogp, B_TRUE, "cannot mount %s on %s", tmp, + *cpp); + return (B_FALSE); + } + } + + /* + * These are things mounted read-only from the running system because + * they contain binaries that must match system. + */ + for (cpp = loopdirs; *cpp != NULL; cpp++) { + (void) snprintf(tmp, sizeof (tmp), "%s%s", luroot, *cpp); + if (mkdir(tmp, 0755) != 0) { + if (errno != EEXIST) { + zerror(zlogp, B_TRUE, "cannot create %s", tmp); + return (B_FALSE); + } + if (lstat(tmp, &st) != 0) { + zerror(zlogp, B_TRUE, "cannot stat %s", tmp); + return (B_FALSE); + } + /* + * Ignore any non-directories encountered. These are + * things that have been converted into symlinks + * (/etc/fs and /etc/lib) and no longer need a lofs + * fixup. + */ + if (!S_ISDIR(st.st_mode)) + continue; + } + if (domount(zlogp, MNTTYPE_LOFS, IPD_DEFAULT_OPTS, *cpp, + tmp) != 0) { + zerror(zlogp, B_TRUE, "cannot mount %s on %s", tmp, + *cpp); + return (B_FALSE); + } + } + + /* + * These are things with tmpfs mounted inside. + */ + for (cpp = tmpdirs; *cpp != NULL; cpp++) { + (void) snprintf(tmp, sizeof (tmp), "%s%s", luroot, *cpp); + if (mkdir(tmp, 0755) != 0 && errno != EEXIST) { + zerror(zlogp, B_TRUE, "cannot create %s", tmp); + return (B_FALSE); + } + if (domount(zlogp, MNTTYPE_TMPFS, "", "swap", tmp) != 0) { + zerror(zlogp, B_TRUE, "cannot mount swap on %s", *cpp); + return (B_FALSE); + } + } + + /* + * This is here to support lucopy. If there's an instance of this same + * zone on the current running system, then we mount its root up as + * read-only inside the scratch zone. + */ + (void) zonecfg_get_uuid(zone_name, uuid); + altstr = strdup(zonecfg_get_root()); + if (altstr == NULL) { + zerror(zlogp, B_TRUE, "out of memory"); + return (B_FALSE); + } + zonecfg_set_root(""); + (void) strlcpy(tmp, zone_name, sizeof (tmp)); + (void) zonecfg_get_name_by_uuid(uuid, tmp, sizeof (tmp)); + if (zone_get_rootpath(tmp, fromdir, sizeof (fromdir)) == Z_OK && + strcmp(fromdir, rootpath) != 0) { + (void) snprintf(tmp, sizeof (tmp), "%s/b", luroot); + if (mkdir(tmp, 0755) != 0) { + zerror(zlogp, B_TRUE, "cannot create %s", tmp); + return (B_FALSE); + } + if (domount(zlogp, MNTTYPE_LOFS, IPD_DEFAULT_OPTS, fromdir, + tmp) != 0) { + zerror(zlogp, B_TRUE, "cannot mount %s on %s", tmp, + fromdir); + return (B_FALSE); + } + } + zonecfg_set_root(altstr); + free(altstr); + + if ((fp = zonecfg_open_scratch(luroot, B_TRUE)) == NULL) { + zerror(zlogp, B_TRUE, "cannot open zone mapfile"); + return (B_FALSE); + } + (void) ftruncate(fileno(fp), 0); + if (zonecfg_add_scratch(fp, zone_name, kernzone, "/") == -1) { + zerror(zlogp, B_TRUE, "cannot add zone mapfile entry"); + } + zonecfg_close_scratch(fp); + (void) snprintf(tmp, sizeof (tmp), "%s/a", luroot); + if (domount(zlogp, MNTTYPE_LOFS, "", rootpath, tmp) != 0) + return (B_FALSE); + (void) strlcpy(rootpath, tmp, rootlen); + return (B_TRUE); +} + static int -mount_filesystems(zlog_t *zlogp) +mount_filesystems(zlog_t *zlogp, boolean_t mount_cmd) { char rootpath[MAXPATHLEN]; char zonepath[MAXPATHLEN]; @@ -891,10 +1316,11 @@ mount_filesystems(zlog_t *zlogp) zone_state_t zstate; if (zone_get_state(zone_name, &zstate) != Z_OK || - zstate != ZONE_STATE_READY) { + (zstate != ZONE_STATE_READY && zstate != ZONE_STATE_MOUNTED)) { zerror(zlogp, B_FALSE, - "zone must be in '%s' state to mount file-systems", - zone_state_str(ZONE_STATE_READY)); + "zone must be in '%s' or '%s' state to mount file-systems", + zone_state_str(ZONE_STATE_READY), + zone_state_str(ZONE_STATE_MOUNTED)); goto bad; } @@ -936,9 +1362,14 @@ mount_filesystems(zlog_t *zlogp) } fs_ptr = tmp_ptr; fsp = &fs_ptr[num_fs - 1]; + /* + * Note that mount_one will prepend the alternate root to + * zone_fs_special and do the necessary resolution, so all that is + * needed here is to strip the root added by zone_get_zonepath. + */ (void) strlcpy(fsp->zone_fs_dir, "/dev", sizeof (fsp->zone_fs_dir)); (void) snprintf(fsp->zone_fs_special, sizeof (fsp->zone_fs_special), - "%s/dev", zonepath); + "%s/dev", zonepath + strlen(zonecfg_get_root())); fsp->zone_fs_raw[0] = '\0'; (void) strlcpy(fsp->zone_fs_type, MNTTYPE_LOFS, sizeof (fsp->zone_fs_type)); @@ -1011,8 +1442,28 @@ mount_filesystems(zlog_t *zlogp) zonecfg_fini_handle(handle); handle = NULL; + /* + * If we're mounting a zone for administration, then we need to set up + * the "/a" environment inside the zone so that the commands that run + * in there have access to both the running system's utilities and the + * to-be-modified zone's files. + */ + if (mount_cmd && + !build_mounted(zlogp, rootpath, sizeof (rootpath), zonepath)) + goto bad; + qsort(fs_ptr, num_fs, sizeof (*fs_ptr), fs_compare); for (i = 0; i < num_fs; i++) { + if (mount_cmd && strcmp(fs_ptr[i].zone_fs_dir, "/dev") == 0) { + size_t slen = strlen(rootpath) - 2; + + /* /dev is special and always goes at the top */ + rootpath[slen] = '\0'; + if (mount_one(zlogp, &fs_ptr[i], rootpath) != 0) + goto bad; + rootpath[slen] = '/'; + continue; + } if (mount_one(zlogp, &fs_ptr[i], rootpath) != 0) goto bad; } @@ -1795,7 +2246,7 @@ devfsadm_call(zlog_t *zlogp, const char *arg) if (status == 0 || status == -1) return (status); zerror(zlogp, B_FALSE, "%s call (%s %s %s) unexpectedly returned %d", - DEVFSADM, DEVFSADM_PATH, arg, zone_name, status); + DEVFSADM, DEVFSADM_PATH, arg, zone_name, status); return (-1); } @@ -2062,21 +2513,115 @@ prtmount(const char *fs, void *x) { return (0); } -int -vplat_create(zlog_t *zlogp) +/* + * Look for zones running on the main system that are using this root (or any + * subdirectory of it). Return B_TRUE and print an error if a conflicting zone + * is found or if we can't tell. + */ +static boolean_t +duplicate_zone_root(zlog_t *zlogp, const char *rootpath) { - int rval = -1; + zoneid_t *zids = NULL; + uint_t nzids = 0; + boolean_t retv; + int rlen, zlen; + char zroot[MAXPATHLEN]; + char zonename[ZONENAME_MAX]; + + for (;;) { + nzids += 10; + zids = malloc(nzids * sizeof (*zids)); + if (zids == NULL) { + zerror(zlogp, B_TRUE, "unable to allocate memory"); + return (B_TRUE); + } + if (zone_list(zids, &nzids) == 0) + break; + free(zids); + } + retv = B_FALSE; + rlen = strlen(rootpath); + while (nzids > 0) { + /* + * Ignore errors; they just mean that the zone has disappeared + * while we were busy. + */ + if (zone_getattr(zids[--nzids], ZONE_ATTR_ROOT, zroot, + sizeof (zroot)) == -1) + continue; + zlen = strlen(zroot); + if (zlen > rlen) + zlen = rlen; + if (strncmp(rootpath, zroot, zlen) == 0 && + (zroot[zlen] == '\0' || zroot[zlen] == '/') && + (rootpath[zlen] == '\0' || rootpath[zlen] == '/')) { + if (getzonenamebyid(zids[nzids], zonename, + sizeof (zonename)) == -1) + (void) snprintf(zonename, sizeof (zonename), + "id %d", (int)zids[nzids]); + zerror(zlogp, B_FALSE, + "zone root %s already in use by zone %s", + rootpath, zonename); + retv = B_TRUE; + break; + } + } + free(zids); + return (retv); +} + +/* + * Search for loopback mounts that use this same source node (same device and + * inode). Return B_TRUE if there is one or if we can't tell. + */ +static boolean_t +duplicate_reachable_path(zlog_t *zlogp, const char *rootpath) +{ + struct stat64 rst, zst; + struct mnttab *mnp; + + if (stat64(rootpath, &rst) == -1) { + zerror(zlogp, B_TRUE, "can't stat %s", rootpath); + return (B_TRUE); + } + if (resolve_lofs_mnts == NULL && lofs_read_mnttab(zlogp) == -1) + return (B_TRUE); + for (mnp = resolve_lofs_mnts; mnp < resolve_lofs_mnt_max; mnp++) { + if (mnp->mnt_fstype == NULL || + strcmp(MNTTYPE_LOFS, mnp->mnt_fstype) != 0) + continue; + /* We're looking at a loopback mount. Stat it. */ + if (mnp->mnt_special != NULL && + stat64(mnp->mnt_special, &zst) != -1 && + rst.st_dev == zst.st_dev && rst.st_ino == zst.st_ino) { + zerror(zlogp, B_FALSE, + "zone root %s is reachable through %s", + rootpath, mnp->mnt_mountp); + return (B_TRUE); + } + } + return (B_FALSE); +} + +zoneid_t +vplat_create(zlog_t *zlogp, boolean_t mount_cmd) +{ + zoneid_t rval = -1; priv_set_t *privs; char rootpath[MAXPATHLEN]; char *rctlbuf = NULL; - size_t rctlbufsz; - zoneid_t zoneid; + size_t rctlbufsz = 0; + zoneid_t zoneid = -1; int xerr; + char *kzone; + FILE *fp = NULL; if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) { zerror(zlogp, B_TRUE, "unable to determine zone root"); return (-1); } + if (zonecfg_in_alt_root()) + resolve_lofs(zlogp, rootpath, sizeof (rootpath)); if ((privs = priv_allocset()) == NULL) { zerror(zlogp, B_TRUE, "%s failed", "priv_allocset"); @@ -2087,13 +2632,80 @@ vplat_create(zlog_t *zlogp) zerror(zlogp, B_TRUE, "Failed to initialize privileges"); goto error; } - if (get_rctls(zlogp, &rctlbuf, &rctlbufsz) != 0) { + if (!mount_cmd && get_rctls(zlogp, &rctlbuf, &rctlbufsz) != 0) { zerror(zlogp, B_FALSE, "Unable to get list of rctls"); goto error; } + kzone = zone_name; + + /* + * We must do this scan twice. First, we look for zones running on the + * main system that are using this root (or any subdirectory of it). + * Next, we reduce to the shortest path and search for loopback mounts + * that use this same source node (same device and inode). + */ + if (duplicate_zone_root(zlogp, rootpath)) + goto error; + if (duplicate_reachable_path(zlogp, rootpath)) + goto error; + + if (mount_cmd) { + root_to_lu(zlogp, rootpath, sizeof (rootpath), B_TRUE); + + /* + * Forge up a special root for this zone. When a zone is + * mounted, we can't let the zone have its own root because the + * tools that will be used in this "scratch zone" need access + * to both the zone's resources and the running machine's + * executables. + * + * Note that the mkdir here also catches read-only filesystems. + */ + if (mkdir(rootpath, 0755) != 0 && errno != EEXIST) { + zerror(zlogp, B_TRUE, "cannot create %s", rootpath); + goto error; + } + if (domount(zlogp, "tmpfs", "", "swap", rootpath) != 0) + goto error; + } + + if (zonecfg_in_alt_root()) { + /* + * If we are mounting up a zone in an alternate root partition, + * then we have some additional work to do before starting the + * zone. First, resolve the root path down so that we're not + * fooled by duplicates. Then forge up an internal name for + * the zone. + */ + if ((fp = zonecfg_open_scratch("", B_TRUE)) == NULL) { + zerror(zlogp, B_TRUE, "cannot open mapfile"); + goto error; + } + if (zonecfg_lock_scratch(fp) != 0) { + zerror(zlogp, B_TRUE, "cannot lock mapfile"); + goto error; + } + if (zonecfg_find_scratch(fp, zone_name, zonecfg_get_root(), + NULL, 0) == 0) { + zerror(zlogp, B_FALSE, "scratch zone already running"); + goto error; + } + /* This is the preferred name */ + (void) snprintf(kernzone, sizeof (kernzone), "SUNWlu-%s", + zone_name); + srandom(getpid()); + while (zonecfg_reverse_scratch(fp, kernzone, NULL, 0, NULL, + 0) == 0) { + /* This is just an arbitrary name; note "." usage */ + (void) snprintf(kernzone, sizeof (kernzone), + "SUNWlu.%08lX%08lX", random(), random()); + } + kzone = kernzone; + } + xerr = 0; - if ((zoneid = zone_create(zone_name, rootpath, privs, rctlbuf, + if ((zoneid = zone_create(kzone, rootpath, privs, rctlbuf, rctlbufsz, &xerr)) == -1) { if (xerr == ZE_AREMOUNTS) { if (zonecfg_find_mounts(rootpath, NULL, NULL) < 1) { @@ -2117,42 +2729,147 @@ vplat_create(zlog_t *zlogp) } goto error; } + + if (zonecfg_in_alt_root() && + zonecfg_add_scratch(fp, zone_name, kernzone, + zonecfg_get_root()) == -1) { + zerror(zlogp, B_TRUE, "cannot add mapfile entry"); + goto error; + } + /* - * The following is a warning, not an error. + * The following is a warning, not an error, and is not performed when + * merely mounting a zone for administrative use. */ - if (bind_to_pool(zlogp, zoneid) != 0) + if (!mount_cmd && bind_to_pool(zlogp, zoneid) != 0) zerror(zlogp, B_FALSE, "WARNING: unable to bind zone to " "requested pool; using default pool."); - rval = 0; + rval = zoneid; + zoneid = -1; + error: + if (zoneid != -1) + (void) zone_destroy(zoneid); if (rctlbuf != NULL) free(rctlbuf); priv_freeset(privs); + if (fp != NULL) + zonecfg_close_scratch(fp); + lofs_discard_mnttab(); return (rval); } int -vplat_bringup(zlog_t *zlogp) +vplat_bringup(zlog_t *zlogp, boolean_t mount_cmd) { - if (create_dev_files(zlogp) != 0) + if (create_dev_files(zlogp) != 0 || + mount_filesystems(zlogp, mount_cmd) != 0) { + lofs_discard_mnttab(); return (-1); - if (mount_filesystems(zlogp) != 0) + } + if (!mount_cmd && (devfsadm_register(zlogp) != 0 || + configure_network_interfaces(zlogp) != 0)) { + lofs_discard_mnttab(); return (-1); - if (devfsadm_register(zlogp) != 0) + } + lofs_discard_mnttab(); + return (0); +} + +static int +lu_root_teardown(zlog_t *zlogp) +{ + char zroot[MAXPATHLEN]; + + if (zone_get_rootpath(zone_name, zroot, sizeof (zroot)) != Z_OK) { + zerror(zlogp, B_FALSE, "unable to determine zone root"); return (-1); - if (configure_network_interfaces(zlogp) != 0) + } + root_to_lu(zlogp, zroot, sizeof (zroot), B_FALSE); + + /* + * At this point, the processes are gone, the filesystems (save the + * root) are unmounted, and the zone is on death row. But there may + * still be creds floating about in the system that reference the + * zone_t, and which pin down zone_rootvp causing this call to fail + * with EBUSY. Thus, we try for a little while before just giving up. + * (How I wish this were not true, and umount2 just did the right + * thing, or tmpfs supported MS_FORCE This is a gross hack.) + */ + if (umount2(zroot, MS_FORCE) != 0) { + if (errno == ENOTSUP && umount2(zroot, 0) == 0) + goto unmounted; + if (errno == EBUSY) { + int tries = 10; + + while (--tries >= 0) { + (void) sleep(1); + if (umount2(zroot, 0) == 0) + goto unmounted; + if (errno != EBUSY) + break; + } + } + zerror(zlogp, B_TRUE, "unable to unmount '%s'", zroot); return (-1); - return (0); + } +unmounted: + + /* + * Only zones in an alternate root environment have scratch zone + * entries. + */ + if (zonecfg_in_alt_root()) { + FILE *fp; + int retv; + + if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) { + zerror(zlogp, B_TRUE, "cannot open mapfile"); + return (-1); + } + retv = -1; + if (zonecfg_lock_scratch(fp) != 0) + zerror(zlogp, B_TRUE, "cannot lock mapfile"); + else if (zonecfg_delete_scratch(fp, kernzone) != 0) + zerror(zlogp, B_TRUE, "cannot delete map entry"); + else + retv = 0; + zonecfg_close_scratch(fp); + return (retv); + } else { + return (0); + } } int -vplat_teardown(zlog_t *zlogp) +vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd) { + char *kzone; zoneid_t zoneid; - if ((zoneid = getzoneidbyname(zone_name)) == ZONE_ID_UNDEFINED) { + kzone = zone_name; + if (zonecfg_in_alt_root()) { + FILE *fp; + + if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) { + zerror(zlogp, B_TRUE, "unable to open map file"); + goto error; + } + if (zonecfg_find_scratch(fp, zone_name, zonecfg_get_root(), + kernzone, sizeof (kernzone)) != 0) { + zerror(zlogp, B_FALSE, "unable to find scratch zone"); + zonecfg_close_scratch(fp); + goto error; + } + zonecfg_close_scratch(fp); + kzone = kernzone; + } + + if ((zoneid = getzoneidbyname(kzone)) == ZONE_ID_UNDEFINED) { if (!bringup_failure_recovery) zerror(zlogp, B_TRUE, "unable to get zoneid"); + if (unmount_cmd) + (void) lu_root_teardown(zlogp); goto error; } @@ -2161,21 +2878,22 @@ vplat_teardown(zlog_t *zlogp) goto error; } - if (devfsadm_unregister(zlogp) != 0) + if (!unmount_cmd && devfsadm_unregister(zlogp) != 0) goto error; - if (unconfigure_network_interfaces(zlogp, zoneid) != 0) { + if (!unmount_cmd && + unconfigure_network_interfaces(zlogp, zoneid) != 0) { zerror(zlogp, B_FALSE, "unable to unconfigure network interfaces in zone"); goto error; } - if (tcp_abort_connections(zlogp, zoneid) != 0) { + if (!unmount_cmd && tcp_abort_connections(zlogp, zoneid) != 0) { zerror(zlogp, B_TRUE, "unable to abort TCP connections"); goto error; } - if (unmount_filesystems(zlogp) != 0) { + if (unmount_filesystems(zlogp, zoneid, unmount_cmd) != 0) { zerror(zlogp, B_FALSE, "unable to unmount file systems in zone"); goto error; @@ -2185,10 +2903,21 @@ vplat_teardown(zlog_t *zlogp) zerror(zlogp, B_TRUE, "unable to destroy zone"); goto error; } - destroy_console_slave(); + /* + * Special teardown for alternate boot environments: remove the tmpfs + * root for the zone and then remove it from the map file. + */ + if (unmount_cmd && lu_root_teardown(zlogp) != 0) + goto error; + + if (!unmount_cmd) + destroy_console_slave(); + + lofs_discard_mnttab(); return (0); error: + lofs_discard_mnttab(); return (-1); } diff --git a/usr/src/cmd/zoneadmd/zoneadmd.c b/usr/src/cmd/zoneadmd/zoneadmd.c index 1cd6ac3945..9b2f346883 100644 --- a/usr/src/cmd/zoneadmd/zoneadmd.c +++ b/usr/src/cmd/zoneadmd/zoneadmd.c @@ -103,12 +103,15 @@ static char *progname; char *zone_name; /* zone which we are managing */ +static zoneid_t zone_id; static zlog_t logsys; mutex_t lock = DEFAULTMUTEX; /* to serialize stuff */ mutex_t msglock = DEFAULTMUTEX; /* for calling setlocale() */ +static sema_t scratch_sem; /* for scratch zones */ + static char zone_door_path[MAXPATHLEN]; static int zone_door = -1; @@ -123,6 +126,21 @@ boolean_t bringup_failure_recovery = B_FALSE; /* ignore certain failures */ #define DEFAULT_LOCALE "C" +static const char * +z_cmd_name(zone_cmd_t zcmd) +{ + /* This list needs to match the enum in sys/zone.h */ + static const char *zcmdstr[] = { + "ready", "boot", "reboot", "halt", "note_uninstalling", + "mount", "unmount" + }; + + if (zcmd >= sizeof (zcmdstr) / sizeof (*zcmdstr)) + return ("unknown"); + else + return (zcmdstr[(int)zcmd]); +} + static char * get_execbasename(char *execfullname) { @@ -244,8 +262,13 @@ mkzonedir(zlog_t *zlogp) return (0); } -static zoneid_t -zone_ready(zlog_t *zlogp) +/* + * Bring a zone up to the pre-boot "ready" stage. The mount_cmd argument is + * 'true' if this is being invoked as part of the processing for the "mount" + * subcommand. + */ +static int +zone_ready(zlog_t *zlogp, boolean_t mount_cmd) { int err; @@ -255,15 +278,15 @@ zone_ready(zlog_t *zlogp) return (-1); } - if (vplat_create(zlogp) != 0) { + if ((zone_id = vplat_create(zlogp, mount_cmd)) == -1) { if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK) zerror(zlogp, B_FALSE, "destroying snapshot: %s", zonecfg_strerror(err)); return (-1); } - if (vplat_bringup(zlogp) != 0) { + if (vplat_bringup(zlogp, mount_cmd) != 0) { bringup_failure_recovery = B_TRUE; - (void) vplat_teardown(NULL); + (void) vplat_teardown(NULL, mount_cmd); if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK) zerror(zlogp, B_FALSE, "destroying snapshot: %s", zonecfg_strerror(err)); @@ -356,6 +379,26 @@ mount_early_fs(zlog_t *zlogp, zoneid_t zoneid, const char *spec, } static int +zone_mount_early(zlog_t *zlogp, zoneid_t zoneid) +{ + if (mount_early_fs(zlogp, zoneid, "/proc", "/proc", "proc") != 0) + return (-1); + + if (mount_early_fs(zlogp, zoneid, "ctfs", CTFS_ROOT, "ctfs") != 0) + return (-1); + + if (mount_early_fs(zlogp, zoneid, "swap", "/etc/svc/volatile", + "tmpfs") != 0) + return (-1); + + if (mount_early_fs(zlogp, zoneid, "mnttab", "/etc/mnttab", + "mntfs") != 0) + return (-1); + + return (0); +} + +static int zone_bootup(zlog_t *zlogp, const char *bootargs) { zoneid_t zoneid; @@ -371,18 +414,7 @@ zone_bootup(zlog_t *zlogp, const char *bootargs) return (-1); } - if (mount_early_fs(zlogp, zoneid, "/proc", "/proc", "proc") != 0) - return (-1); - - if (mount_early_fs(zlogp, zoneid, "ctfs", CTFS_ROOT, "ctfs") != 0) - return (-1); - - if (mount_early_fs(zlogp, zoneid, "swap", "/etc/svc/volatile", - "tmpfs") != 0) - return (-1); - - if (mount_early_fs(zlogp, zoneid, "mnttab", "/etc/mnttab", - "mntfs") != 0) + if (zone_mount_early(zlogp, zoneid) != 0) return (-1); /* @@ -414,11 +446,11 @@ zone_bootup(zlog_t *zlogp, const char *bootargs) } static int -zone_halt(zlog_t *zlogp) +zone_halt(zlog_t *zlogp, boolean_t unmount_cmd) { int err; - if (vplat_teardown(zlogp) != 0) { + if (vplat_teardown(zlogp, unmount_cmd) != 0) { if (!bringup_failure_recovery) zerror(zlogp, B_FALSE, "unable to destroy zone"); return (-1); @@ -504,7 +536,6 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, zlog_t *zlogp; zone_cmd_rval_t *rvalp; size_t rlen = getpagesize(); /* conservative */ - char *cmd_str = NULL; /* LINTED E_BAD_PTR_CAST_ALIGN */ zargp = (zone_cmd_arg_t *)args; @@ -579,8 +610,9 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, * Check for validity of command. */ if (cmd != Z_READY && cmd != Z_BOOT && cmd != Z_REBOOT && - cmd != Z_HALT && cmd != Z_NOTE_UNINSTALLING) { - zerror(&logsys, B_FALSE, "invalid command"); + cmd != Z_HALT && cmd != Z_NOTE_UNINSTALLING && cmd != Z_MOUNT && + cmd != Z_UNMOUNT) { + zerror(&logsys, B_FALSE, "invalid command %d", (int)cmd); goto out; } @@ -629,41 +661,26 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, * Not our area of expertise; we just print a nice message * and die off. */ - switch (cmd) { - case Z_READY: - cmd_str = "ready"; - break; - case Z_BOOT: - cmd_str = "boot"; - break; - case Z_HALT: - cmd_str = "halt"; - break; - case Z_REBOOT: - cmd_str = "reboot"; - break; - } - assert(cmd_str != NULL); zerror(zlogp, B_FALSE, "%s operation is invalid for zones in state '%s'", - cmd_str, zone_state_str(zstate)); + z_cmd_name(cmd), zone_state_str(zstate)); break; case ZONE_STATE_INSTALLED: switch (cmd) { case Z_READY: - rval = zone_ready(zlogp); + rval = zone_ready(zlogp, B_FALSE); if (rval == 0) eventstream_write(Z_EVT_ZONE_READIED); break; case Z_BOOT: eventstream_write(Z_EVT_ZONE_BOOTING); - if ((rval = zone_ready(zlogp)) == 0) + if ((rval = zone_ready(zlogp, B_FALSE)) == 0) rval = zone_bootup(zlogp, zargp->bootbuf); audit_put_record(zlogp, uc, rval, "boot"); if (rval != 0) { bringup_failure_recovery = B_TRUE; - (void) zone_halt(zlogp); + (void) zone_halt(zlogp, B_FALSE); } break; case Z_HALT: @@ -682,7 +699,7 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, if (kernelcall) /* Invalid; can't happen */ abort(); zerror(zlogp, B_FALSE, "%s operation is invalid " - "for zones in state '%s'", "reboot", + "for zones in state '%s'", z_cmd_name(cmd), zone_state_str(zstate)); rval = -1; break; @@ -695,6 +712,28 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, */ eventstream_write(Z_EVT_ZONE_UNINSTALLING); break; + case Z_MOUNT: + if (kernelcall) /* Invalid; can't happen */ + abort(); + rval = zone_ready(zlogp, B_TRUE); + if (rval == 0) + rval = zone_mount_early(zlogp, zone_id); + /* + * Ordinarily, /dev/fd would be mounted inside the zone + * by svc:/system/filesystem/usr:default, but since + * we're not booting the zone, we need to do this + * manually. + */ + if (rval == 0) + rval = mount_early_fs(zlogp, zone_id, "fd", + "/dev/fd", "fd"); + break; + case Z_UNMOUNT: + if (kernelcall) /* Invalid; can't happen */ + abort(); + zerror(zlogp, B_FALSE, "zone is already unmounted"); + rval = 0; + break; } break; @@ -716,30 +755,45 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, audit_put_record(zlogp, uc, rval, "boot"); if (rval != 0) { bringup_failure_recovery = B_TRUE; - (void) zone_halt(zlogp); + (void) zone_halt(zlogp, B_FALSE); } break; case Z_HALT: if (kernelcall) /* Invalid; can't happen */ abort(); - if ((rval = zone_halt(zlogp)) != 0) + if ((rval = zone_halt(zlogp, B_FALSE)) != 0) break; eventstream_write(Z_EVT_ZONE_HALTED); break; case Z_REBOOT: + case Z_NOTE_UNINSTALLING: + case Z_MOUNT: + case Z_UNMOUNT: if (kernelcall) /* Invalid; can't happen */ abort(); zerror(zlogp, B_FALSE, "%s operation is invalid " - "for zones in state '%s'", "reboot", + "for zones in state '%s'", z_cmd_name(cmd), zone_state_str(zstate)); rval = -1; break; - case Z_NOTE_UNINSTALLING: + } + break; + + case ZONE_STATE_MOUNTED: + switch (cmd) { + case Z_UNMOUNT: + if (kernelcall) /* Invalid; can't happen */ + abort(); + rval = zone_halt(zlogp, B_TRUE); + if (rval == 0) + (void) sema_post(&scratch_sem); + break; + default: if (kernelcall) /* Invalid; can't happen */ abort(); - zerror(zlogp, B_FALSE, "%s operation is " - "invalid for zones in state '%s'", - "note_uninstall", zone_state_str(zstate)); + zerror(zlogp, B_FALSE, "%s operation is invalid " + "for zones in state '%s'", z_cmd_name(cmd), + zone_state_str(zstate)); rval = -1; break; } @@ -750,9 +804,9 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, case ZONE_STATE_DOWN: switch (cmd) { case Z_READY: - if ((rval = zone_halt(zlogp)) != 0) + if ((rval = zone_halt(zlogp, B_FALSE)) != 0) break; - if ((rval = zone_ready(zlogp)) == 0) + if ((rval = zone_ready(zlogp, B_FALSE)) == 0) eventstream_write(Z_EVT_ZONE_READIED); break; case Z_BOOT: @@ -766,25 +820,27 @@ server(void *cookie, char *args, size_t alen, door_desc_t *dp, rval = 0; break; case Z_HALT: - if ((rval = zone_halt(zlogp)) != 0) + if ((rval = zone_halt(zlogp, B_FALSE)) != 0) break; eventstream_write(Z_EVT_ZONE_HALTED); break; case Z_REBOOT: eventstream_write(Z_EVT_ZONE_REBOOTING); - if ((rval = zone_halt(zlogp)) != 0) + if ((rval = zone_halt(zlogp, B_FALSE)) != 0) break; - if ((rval = zone_ready(zlogp)) == 0) { + if ((rval = zone_ready(zlogp, B_FALSE)) == 0) { rval = zone_bootup(zlogp, ""); audit_put_record(zlogp, uc, rval, "reboot"); if (rval != 0) - (void) zone_halt(zlogp); + (void) zone_halt(zlogp, B_FALSE); } break; case Z_NOTE_UNINSTALLING: - zerror(zlogp, B_FALSE, "%s operation is " - "invalid for zones in state '%s'", - "note_uninstall", zone_state_str(zstate)); + case Z_MOUNT: + case Z_UNMOUNT: + zerror(zlogp, B_FALSE, "%s operation is invalid " + "for zones in state '%s'", z_cmd_name(cmd), + zone_state_str(zstate)); rval = -1; break; } @@ -1023,8 +1079,11 @@ main(int argc, char *argv[]) /* * Process options. */ - while ((opt = getopt(argc, argv, "z:")) != EOF) { + while ((opt = getopt(argc, argv, "R:z:")) != EOF) { switch (opt) { + case 'R': + zonecfg_set_root(optarg); + break; case 'z': zone_name = optarg; break; @@ -1206,7 +1265,7 @@ main(int argc, char *argv[]) } (void) snprintf(zone_door_path, sizeof (zone_door_path), - ZONE_DOOR_PATH, zone_name); + "%s" ZONE_DOOR_PATH, zonecfg_get_root(), zone_name); /* * See if another zoneadmd is running for this zone. If not, then we @@ -1237,7 +1296,7 @@ main(int argc, char *argv[]) * serve_console_sock() below gets called, and any pending * connection is accept()ed). */ - if (init_console(zlogp) == -1) + if (!zonecfg_in_alt_root() && init_console(zlogp) == -1) goto child_out; /* @@ -1248,6 +1307,13 @@ main(int argc, char *argv[]) */ (void) mutex_lock(&lock); + /* Init semaphore for scratch zones. */ + if (sema_init(&scratch_sem, 0, USYNC_THREAD, NULL) == -1) { + zerror(zlogp, B_TRUE, + "failed to initialize semaphore for scratch zone"); + goto child_out; + } + /* * Note: door setup must occur *after* the console is setup. * This is so that as zlogin tests the door to see if zoneadmd @@ -1286,8 +1352,17 @@ main(int argc, char *argv[]) * serve_console() has returned, we are past the point of no return * in the life of this zoneadmd. */ - serve_console(zlogp); - assert(in_death_throes); + if (zonecfg_in_alt_root()) { + /* + * This is just awful, but mounted scratch zones don't (and + * can't) have consoles. We just wait for unmount instead. + */ + while (sema_wait(&scratch_sem) == EINTR) + ; + } else { + serve_console(zlogp); + assert(in_death_throes); + } /* * This is the next-to-last part of the exit interlock. Upon calling diff --git a/usr/src/cmd/zoneadmd/zoneadmd.h b/usr/src/cmd/zoneadmd/zoneadmd.h index 6bf0034310..2afc12f456 100644 --- a/usr/src/cmd/zoneadmd/zoneadmd.h +++ b/usr/src/cmd/zoneadmd/zoneadmd.h @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -93,9 +93,9 @@ extern void eventstream_write(zone_evt_t evt); /* * Virtual platform interfaces. */ -extern int vplat_create(zlog_t *); -extern int vplat_bringup(zlog_t *); -extern int vplat_teardown(zlog_t *); +extern zoneid_t vplat_create(zlog_t *, boolean_t); +extern int vplat_bringup(zlog_t *, boolean_t); +extern int vplat_teardown(zlog_t *, boolean_t); /* diff --git a/usr/src/cmd/zonename/Makefile b/usr/src/cmd/zonename/Makefile index d32cac6386..ac42810786 100644 --- a/usr/src/cmd/zonename/Makefile +++ b/usr/src/cmd/zonename/Makefile @@ -22,7 +22,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # cmd/zonename/Makefile @@ -32,6 +32,10 @@ PROG= zonename include ../Makefile.cmd +LAZYLIBS = $(ZLAZYLOAD) -lzonecfg $(ZNOLAZYLOAD) +lint := LAZYLIBS = -lzonecfg +LDLIBS += $(LAZYLIBS) + .KEEP_STATE: all: $(PROG) diff --git a/usr/src/cmd/zonename/zonename.c b/usr/src/cmd/zonename/zonename.c index ef2beb6701..3a3a5df27d 100644 --- a/usr/src/cmd/zonename/zonename.c +++ b/usr/src/cmd/zonename/zonename.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,15 +31,18 @@ #include <locale.h> #include <libintl.h> #include <zone.h> +#include <libzonecfg.h> +#include <dlfcn.h> #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ #endif int -main() +main(void) { char zonename[ZONENAME_MAX]; + FILE *fp; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); @@ -49,6 +52,19 @@ main() stderr); return (1); } + + /* + * The use of dlopen here is a bit ugly, but it allows zonename to + * function properly before /usr is mounted. On such a system, scratch + * zones don't exist, so no translation is necessary. + */ + if (dlopen("libzonecfg.so.1", RTLD_NOW | RTLD_GLOBAL) != NULL && + zonecfg_is_scratch(zonename) && + (fp = zonecfg_open_scratch("", B_FALSE)) != NULL) { + (void) zonecfg_reverse_scratch(fp, zonename, zonename, + sizeof (zonename), NULL, 0); + zonecfg_close_scratch(fp); + } (void) puts(zonename); return (0); } diff --git a/usr/src/head/libzonecfg.h b/usr/src/head/libzonecfg.h index dd3c1d41ef..a82931928a 100644 --- a/usr/src/head/libzonecfg.h +++ b/usr/src/head/libzonecfg.h @@ -48,6 +48,7 @@ extern "C" { #include <stdio.h> #include <rctl.h> #include <zone.h> +#include <sys/uuid.h> #define ZONE_ID_UNDEFINED -1 @@ -89,9 +90,10 @@ extern "C" { #define ZONE_STATE_INCOMPLETE 1 #define ZONE_STATE_INSTALLED 2 #define ZONE_STATE_READY 3 -#define ZONE_STATE_RUNNING 4 -#define ZONE_STATE_SHUTTING_DOWN 5 -#define ZONE_STATE_DOWN 6 +#define ZONE_STATE_MOUNTED 4 +#define ZONE_STATE_RUNNING 5 +#define ZONE_STATE_SHUTTING_DOWN 6 +#define ZONE_STATE_DOWN 7 #define ZONE_STATE_MAXSTRLEN 14 @@ -107,7 +109,8 @@ extern "C" { struct zoneent { char zone_name[ZONENAME_MAX]; /* name of the zone */ int zone_state; /* configured | incomplete | installed */ - char zone_path[MAXPATHLEN]; + char zone_path[MAXPATHLEN]; /* path to zone storage */ + uuid_t zone_uuid; /* unique ID for zone */ char zone_newname[ZONENAME_MAX]; /* for doing renames */ }; @@ -159,22 +162,26 @@ struct zone_attrtab { * Basic configuration management routines. */ extern zone_dochandle_t zonecfg_init_handle(void); -extern int zonecfg_get_handle(char *, zone_dochandle_t); -extern int zonecfg_get_snapshot_handle(char *, zone_dochandle_t); -extern int zonecfg_get_template_handle(char *, char *, zone_dochandle_t); +extern int zonecfg_get_handle(const char *, zone_dochandle_t); +extern int zonecfg_get_snapshot_handle(const char *, zone_dochandle_t); +extern int zonecfg_get_template_handle(const char *, const char *, + zone_dochandle_t); extern int zonecfg_check_handle(zone_dochandle_t); extern void zonecfg_fini_handle(zone_dochandle_t); extern int zonecfg_destroy(const char *, boolean_t); -extern int zonecfg_destroy_snapshot(char *); +extern int zonecfg_destroy_snapshot(const char *); extern int zonecfg_save(zone_dochandle_t); -extern int zonecfg_create_snapshot(char *); +extern int zonecfg_create_snapshot(const char *); extern char *zonecfg_strerror(int); extern int zonecfg_access(const char *, int); +extern void zonecfg_set_root(const char *); +extern const char *zonecfg_get_root(void); +extern boolean_t zonecfg_in_alt_root(void); /* * Zone name, path to zone directory, autoboot setting and pool. */ -extern int zonecfg_validate_zonename(char *); +extern int zonecfg_validate_zonename(const char *); extern int zonecfg_get_name(zone_dochandle_t, char *, size_t); extern int zonecfg_set_name(zone_dochandle_t, char *); extern int zonecfg_get_zonepath(zone_dochandle_t, char *, size_t); @@ -289,6 +296,8 @@ extern int zone_get_zonepath(char *, char *, size_t); extern int zone_get_state(char *, zone_state_t *); extern int zone_set_state(char *, zone_state_t); extern char *zone_state_str(zone_state_t); +extern int zonecfg_get_name_by_uuid(const uuid_t, char *, size_t); +extern int zonecfg_get_uuid(const char *, uuid_t); /* * Iterator for configured zones. @@ -319,6 +328,23 @@ extern boolean_t zonecfg_valid_rctl(const char *, const rctlblk_t *); extern int zonecfg_construct_rctlblk(const struct zone_rctlvaltab *, rctlblk_t *); +/* + * Live Upgrade support functions. Shared between ON and install gate. + */ +extern FILE *zonecfg_open_scratch(const char *, boolean_t); +extern int zonecfg_lock_scratch(FILE *); +extern void zonecfg_close_scratch(FILE *); +extern int zonecfg_get_scratch(FILE *, char *, size_t, char *, size_t, char *, + size_t); +extern int zonecfg_find_scratch(FILE *, const char *, const char *, char *, + size_t); +extern int zonecfg_reverse_scratch(FILE *, const char *, char *, size_t, + char *, size_t); +extern int zonecfg_add_scratch(FILE *, const char *, const char *, + const char *); +extern int zonecfg_delete_scratch(FILE *, const char *); +extern boolean_t zonecfg_is_scratch(const char *); + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libzonecfg/Makefile.com b/usr/src/lib/libzonecfg/Makefile.com index e01f34e45f..d38aa2bdc0 100644 --- a/usr/src/lib/libzonecfg/Makefile.com +++ b/usr/src/lib/libzonecfg/Makefile.com @@ -20,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -28,12 +28,12 @@ LIBRARY= libzonecfg.a VERS= .1 -OBJECTS= libzonecfg.o getzoneent.o +OBJECTS= libzonecfg.o getzoneent.o scratchops.o include ../../Makefile.lib LIBS = $(DYNLIB) $(LINTLIB) -LDLIBS += -lc -lsocket -lnsl +LDLIBS += -lc -lsocket -lnsl -luuid $(DYNLIB) := LDLIBS += -lxml2 CPPFLAGS += -I/usr/include/libxml2 -I$(SRCDIR) -D_REENTRANT $(LINTLIB) := SRCS= $(SRCDIR)/$(LINTSRC) diff --git a/usr/src/lib/libzonecfg/common/getzoneent.c b/usr/src/lib/libzonecfg/common/getzoneent.c index 4a62bddaa9..2decb372a9 100644 --- a/usr/src/lib/libzonecfg/common/getzoneent.c +++ b/usr/src/lib/libzonecfg/common/getzoneent.c @@ -35,7 +35,6 @@ */ #include <stdlib.h> -#include <ctype.h> #include <string.h> #include <errno.h> #include <libzonecfg.h> @@ -43,6 +42,7 @@ #include <fcntl.h> #include <sys/stat.h> #include <assert.h> +#include <uuid/uuid.h> #include "zonecfg_impl.h" @@ -56,6 +56,8 @@ * Same with double-quotes themselves: they are not allowed in zone names, * and do not occur in zone states, and in theory should never occur in a * zonepath since zonecfg does not support a method for escaping them. + * + * It never returns NULL. */ static char * @@ -129,7 +131,7 @@ getzoneent_private(FILE *cookie) continue; } p = gettok(&cp); - if (p == NULL || *p == '\0' || strlen(p) > ZONENAME_MAX) { + if (*p == '\0' || strlen(p) >= ZONENAME_MAX) { /* * empty or very long zone names are not allowed */ @@ -138,7 +140,7 @@ getzoneent_private(FILE *cookie) (void) strlcpy(ze->zone_name, p, ZONENAME_MAX); p = gettok(&cp); - if (p == NULL || *p == '\0') { + if (*p == '\0') { /* state field should not be empty */ continue; } @@ -149,30 +151,44 @@ getzoneent_private(FILE *cookie) ze->zone_state = ZONE_STATE_INCOMPLETE; } else if (strcmp(p, ZONE_STATE_STR_INSTALLED) == 0) { ze->zone_state = ZONE_STATE_INSTALLED; - } else + } else { continue; + } p = gettok(&cp); - if (strlen(p) > MAXPATHLEN) { + if (strlen(p) >= MAXPATHLEN) { /* very long paths are not allowed */ continue; } - if (p == NULL) { - /* empty paths accepted for backwards compatibility */ - p = ""; - } (void) strlcpy(ze->zone_path, p, MAXPATHLEN); + p = gettok(&cp); + if (uuid_parse(p, ze->zone_uuid) == -1) + uuid_clear(ze->zone_uuid); + break; } return (ze); } +static boolean_t +get_index_path(char *path) +{ + return (snprintf(path, MAXPATHLEN, "%s%s", zonecfg_root, + ZONE_INDEX_FILE) < MAXPATHLEN); +} + FILE * setzoneent(void) { - return (fopen(ZONE_INDEX_FILE, "r")); + char path[MAXPATHLEN]; + + if (!get_index_path(path)) { + errno = EINVAL; + return (NULL); + } + return (fopen(path, "r")); } void @@ -183,25 +199,35 @@ endzoneent(FILE *cookie) } static int -lock_index_file(int *lock_fd) +lock_index_file(void) { + int lock_fd; struct flock lock; - - if ((mkdir(ZONE_SNAPSHOT_ROOT, S_IRWXU) == -1) && errno != EEXIST) - return (Z_LOCKING_FILE); - *lock_fd = open(ZONE_INDEX_LOCK_FILE, O_CREAT|O_RDWR, 0644); - if (*lock_fd < 0) - return (Z_LOCKING_FILE); + char path[MAXPATHLEN]; + + if (snprintf(path, sizeof (path), "%s%s", zonecfg_root, + ZONE_INDEX_LOCK_DIR) >= sizeof (path)) + return (-1); + if ((mkdir(path, S_IRWXU) == -1) && errno != EEXIST) + return (-1); + if (strlcat(path, ZONE_INDEX_LOCK_FILE, sizeof (path)) >= + sizeof (path)) + return (-1); + lock_fd = open(path, O_CREAT|O_RDWR, 0644); + if (lock_fd == -1) + return (-1); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; - if (fcntl(*lock_fd, F_SETLKW, &lock) == -1) - return (Z_LOCKING_FILE); + if (fcntl(lock_fd, F_SETLKW, &lock) == -1) { + (void) close(lock_fd); + return (-1); + } - return (Z_OK); + return (lock_fd); } static int @@ -247,11 +273,14 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) { FILE *index_file, *tmp_file; char *tmp_file_name, buf[MAX_INDEX_LEN], orig_buf[MAX_INDEX_LEN]; - char zone[ZONENAME_MAX + 1]; /* name plus newline */ + char zone[ZONENAME_MAX]; char line[MAX_INDEX_LEN]; int tmp_file_desc, lock_fd, err; boolean_t exists = B_FALSE, need_quotes; char *cp, *p; + char path[MAXPATHLEN]; + char uuidstr[37]; /* hard-coded because of CR 6305641 */ + size_t tlen; assert(ze != NULL); if (operation == PZE_ADD && @@ -261,13 +290,19 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) if (operation != PZE_MODIFY && strlen(ze->zone_newname) != 0) return (Z_INVAL); - if ((err = lock_index_file(&lock_fd)) != Z_OK) - return (err); - tmp_file_name = strdup(_PATH_TMPFILE); + if ((lock_fd = lock_index_file()) == -1) + return (Z_LOCKING_FILE); + + /* using sizeof gives us room for the terminating NUL byte as well */ + tlen = sizeof (_PATH_TMPFILE) + strlen(zonecfg_root); + tmp_file_name = malloc(tlen); if (tmp_file_name == NULL) { (void) unlock_index_file(lock_fd); return (Z_NOMEM); } + (void) snprintf(tmp_file_name, tlen, "%s%s", zonecfg_root, + _PATH_TMPFILE); + tmp_file_desc = mkstemp(tmp_file_name); if (tmp_file_desc == -1) { (void) unlink(tmp_file_name); @@ -277,17 +312,16 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) } if ((tmp_file = fdopen(tmp_file_desc, "w")) == NULL) { (void) close(tmp_file_desc); - (void) unlink(tmp_file_name); - free(tmp_file_name); - (void) unlock_index_file(lock_fd); - return (Z_MISC_FS); + err = Z_MISC_FS; + goto error; } - if ((index_file = fopen(ZONE_INDEX_FILE, "r")) == NULL) { - (void) fclose(tmp_file); - (void) unlink(tmp_file_name); - free(tmp_file_name); - (void) unlock_index_file(lock_fd); - return (Z_MISC_FS); + if (!get_index_path(path)) { + err = Z_MISC_FS; + goto error; + } + if ((index_file = fopen(path, "r")) == NULL) { + err = Z_MISC_FS; + goto error; } /* @@ -300,9 +334,17 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) */ need_quotes = (strchr(ze->zone_path, ':') != NULL); - (void) snprintf(line, sizeof (line), "%s:%s:%s%s%s\n", ze->zone_name, - zone_state_str(ze->zone_state), need_quotes ? "\"" : "", - ze->zone_path, need_quotes ? "\"" : ""); + /* + * If this zone doesn't yet have a unique identifier, then give it one. + */ + if (uuid_is_null(ze->zone_uuid)) + uuid_generate(ze->zone_uuid); + uuid_unparse(ze->zone_uuid, uuidstr); + + (void) snprintf(line, sizeof (line), "%s:%s:%s%s%s:%s\n", + ze->zone_name, zone_state_str(ze->zone_state), + need_quotes ? "\"" : "", ze->zone_path, need_quotes ? "\"" : "", + uuidstr); for (;;) { if (fgets(buf, sizeof (buf), index_file) == NULL) { if (operation == PZE_ADD && !exists) @@ -323,7 +365,7 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) continue; } p = gettok(&cp); - if (p == NULL || *p == '\0' || strlen(p) > ZONENAME_MAX) { + if (*p == '\0' || strlen(p) >= ZONENAME_MAX) { /* * empty or very long zone names are not allowed */ @@ -335,6 +377,7 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) exists = B_TRUE; /* already there */ if (operation == PZE_ADD) { /* can't add same zone */ + err = Z_UPDATING_INDEX; goto error; } else if (operation == PZE_MODIFY) { char tmp_state[ZONE_STATE_MAXSTRLEN + 1]; @@ -348,8 +391,9 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) } /* use existing value for state */ p = gettok(&cp); - if (p == NULL || *p == '\0') { + if (*p == '\0') { /* state field should not be empty */ + err = Z_UPDATING_INDEX; goto error; } (void) strlcpy(tmp_state, @@ -367,11 +411,12 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) else tmp_name = ze->zone_name; - (void) fprintf(tmp_file, "%s:%s:%s%s%s\n", + (void) fprintf(tmp_file, "%s:%s:%s%s%s:%s\n", tmp_name, tmp_state, need_quotes ? "\"" : "", (strlen(ze->zone_path) == 0) ? p : - ze->zone_path, need_quotes ? "\"" : ""); + ze->zone_path, need_quotes ? "\"" : "", + uuidstr); } /* else if (operation == PZE_REMOVE) { no-op } */ } else { @@ -380,31 +425,30 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) } (void) fclose(index_file); + index_file = NULL; if (fclose(tmp_file) != 0) { - (void) unlink(tmp_file_name); - free(tmp_file_name); - (void) unlock_index_file(lock_fd); - return (Z_MISC_FS); + tmp_file = NULL; + err = Z_MISC_FS; + goto error; } + tmp_file = NULL; (void) chmod(tmp_file_name, 0644); - if (rename(tmp_file_name, ZONE_INDEX_FILE) == -1) { - (void) unlink(tmp_file_name); - free(tmp_file_name); - (void) unlock_index_file(lock_fd); - if (errno == EACCES) - return (Z_ACCES); - return (Z_MISC_FS); + if (rename(tmp_file_name, path) == -1) { + err = errno == EACCES ? Z_ACCES : Z_MISC_FS; + goto error; } free(tmp_file_name); if (unlock_index_file(lock_fd) != Z_OK) return (Z_UNLOCKING_FILE); return (Z_OK); + error: - (void) fclose(index_file); - (void) fclose(tmp_file); + if (index_file != NULL) + (void) fclose(index_file); + if (tmp_file != NULL) + (void) fclose(tmp_file); (void) unlink(tmp_file_name); free(tmp_file_name); - if (unlock_index_file(lock_fd) != Z_OK) - return (Z_UNLOCKING_FILE); - return (Z_UPDATING_INDEX); + (void) unlock_index_file(lock_fd); + return (err); } diff --git a/usr/src/lib/libzonecfg/common/libzonecfg.c b/usr/src/lib/libzonecfg/common/libzonecfg.c index b9d80dbefa..b6a6a59cee 100644 --- a/usr/src/lib/libzonecfg/common/libzonecfg.c +++ b/usr/src/lib/libzonecfg/common/libzonecfg.c @@ -49,6 +49,7 @@ #include <libxml/parser.h> #include <libdevinfo.h> +#include <uuid/uuid.h> #include <libzonecfg.h> #include "zonecfg_impl.h" @@ -105,6 +106,8 @@ struct zone_dochandle { char zone_dh_delete_name[ZONENAME_MAX]; }; +char *zonecfg_root = ""; + /* * For functions which return int, which is most of the functions herein, * the return values should be from the Z_foo set defined in <libzonecfg.h>. @@ -113,22 +116,49 @@ struct zone_dochandle { */ /* + * Set the root (/) path for all zonecfg configuration files. This is a + * private interface used by Live Upgrade extensions to access zone + * configuration inside mounted alternate boot environments. + */ +void +zonecfg_set_root(const char *rootpath) +{ + if (*zonecfg_root != '\0') + free(zonecfg_root); + if (rootpath == NULL || rootpath[0] == '\0' || rootpath[1] == '\0' || + (zonecfg_root = strdup(rootpath)) == NULL) + zonecfg_root = ""; +} + +const char * +zonecfg_get_root(void) +{ + return (zonecfg_root); +} + +boolean_t +zonecfg_in_alt_root(void) +{ + return (*zonecfg_root != '\0'); +} + +/* * Callers of the _file_path() functions are expected to have the second * parameter be a (char foo[MAXPATHLEN]). */ -static void +static boolean_t config_file_path(const char *zonename, char *answer) { - (void) snprintf(answer, MAXPATHLEN, - "%s/%s.xml", ZONE_CONFIG_ROOT, zonename); + return (snprintf(answer, MAXPATHLEN, "%s%s/%s.xml", zonecfg_root, + ZONE_CONFIG_ROOT, zonename) < MAXPATHLEN); } -static void -snap_file_path(char *zonename, char *answer) +static boolean_t +snap_file_path(const char *zonename, char *answer) { - (void) snprintf(answer, MAXPATHLEN, - "%s/%s.snapshot.xml", ZONE_SNAPSHOT_ROOT, zonename); + return (snprintf(answer, MAXPATHLEN, "%s%s/%s.snapshot.xml", + zonecfg_root, ZONE_SNAPSHOT_ROOT, zonename) < MAXPATHLEN); } /*ARGSUSED*/ @@ -199,7 +229,8 @@ zonecfg_destroy(const char *zonename, boolean_t force) int err, state_err; zone_state_t state; - config_file_path(zonename, path); + if (!config_file_path(zonename, path)) + return (Z_MISC_FS); state_err = zone_get_state((char *)zonename, &state); err = access(path, W_OK); @@ -251,11 +282,12 @@ zonecfg_destroy(const char *zonename, boolean_t force) } int -zonecfg_destroy_snapshot(char *zonename) +zonecfg_destroy_snapshot(const char *zonename) { char path[MAXPATHLEN]; - snap_file_path(zonename, path); + if (!snap_file_path(zonename, path)) + return (Z_MISC_FS); return (zonecfg_destroy_impl(path)); } @@ -312,7 +344,8 @@ getrootattr(zone_dochandle_t handle, const xmlChar *propname, } static int -setrootattr(zone_dochandle_t handle, const xmlChar *propname, char *propval) +setrootattr(zone_dochandle_t handle, const xmlChar *propname, + const char *propval) { int err; xmlNodePtr root; @@ -358,7 +391,8 @@ stripcomments(zone_dochandle_t handle) } static int -zonecfg_get_handle_impl(char *zonename, char *filename, zone_dochandle_t handle) +zonecfg_get_handle_impl(const char *zonename, const char *filename, + zone_dochandle_t handle) { xmlValidCtxtPtr cvp; struct stat statbuf; @@ -387,34 +421,37 @@ zonecfg_get_handle_impl(char *zonename, char *filename, zone_dochandle_t handle) } int -zonecfg_get_handle(char *zonename, zone_dochandle_t handle) +zonecfg_get_handle(const char *zonename, zone_dochandle_t handle) { char path[MAXPATHLEN]; - config_file_path(zonename, path); + if (!config_file_path(zonename, path)) + return (Z_MISC_FS); handle->zone_dh_newzone = B_FALSE; return (zonecfg_get_handle_impl(zonename, path, handle)); } int -zonecfg_get_snapshot_handle(char *zonename, zone_dochandle_t handle) +zonecfg_get_snapshot_handle(const char *zonename, zone_dochandle_t handle) { char path[MAXPATHLEN]; - snap_file_path(zonename, path); + if (!snap_file_path(zonename, path)) + return (Z_MISC_FS); handle->zone_dh_newzone = B_FALSE; return (zonecfg_get_handle_impl(zonename, path, handle)); } int -zonecfg_get_template_handle(char *template, char *zonename, +zonecfg_get_template_handle(const char *template, const char *zonename, zone_dochandle_t handle) { char path[MAXPATHLEN]; int err; - config_file_path(template, path); + if (!config_file_path(template, path)) + return (Z_MISC_FS); if ((err = zonecfg_get_handle_impl(template, path, handle)) != Z_OK) return (err); @@ -450,7 +487,7 @@ is_snapshot(zone_dochandle_t handle) * safety if this routine had to change the app locale on the fly. */ int -zonecfg_validate_zonename(char *zone) +zonecfg_validate_zonename(const char *zone) { int i; @@ -573,7 +610,12 @@ zonecfg_set_name(zone_dochandle_t handle, char *name) int zonecfg_get_zonepath(zone_dochandle_t handle, char *path, size_t pathsize) { - return (getrootattr(handle, DTD_ATTR_ZONEPATH, path, pathsize)); + size_t len; + + if ((len = strlcpy(path, zonecfg_root, pathsize)) >= pathsize) + return (Z_TOO_BIG); + return (getrootattr(handle, DTD_ATTR_ZONEPATH, path + len, + pathsize - len)); } int @@ -841,7 +883,8 @@ zonecfg_save(zone_dochandle_t handle) if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK) return (err); - config_file_path(zname, path); + if (!config_file_path(zname, path)) + return (Z_MISC_FS); addcomment(handle, "\n DO NOT EDIT THIS " "FILE. Use zonecfg(1M) instead.\n"); @@ -856,8 +899,8 @@ zonecfg_save(zone_dochandle_t handle) handle->zone_dh_newzone = B_FALSE; if (is_renaming(handle)) { - config_file_path(handle->zone_dh_delete_name, delpath); - (void) unlink(delpath); + if (config_file_path(handle->zone_dh_delete_name, delpath)) + (void) unlink(delpath); handle->zone_dh_delete_name[0] = '\0'; } @@ -876,11 +919,17 @@ zonecfg_access(const char *zonename, int amode) { char path[MAXPATHLEN]; - config_file_path(zonename, path); + if (!config_file_path(zonename, path)) + return (Z_INVAL); if (access(path, amode) == 0) return (Z_OK); - if (errno == ENOENT && access(ZONE_CONFIG_ROOT, amode) == 0) - return (Z_OK); + if (errno == ENOENT) { + if (snprintf(path, sizeof (path), "%s%s", zonecfg_root, + ZONE_CONFIG_ROOT) >= sizeof (path)) + return (Z_INVAL); + if (access(path, amode) == 0) + return (Z_OK); + } if (errno == EACCES) return (Z_ACCES); if (errno == EINVAL) @@ -889,7 +938,7 @@ zonecfg_access(const char *zonename, int amode) } int -zonecfg_create_snapshot(char *zonename) +zonecfg_create_snapshot(const char *zonename) { zone_dochandle_t handle; char path[MAXPATHLEN], zonepath[MAXPATHLEN], rpath[MAXPATHLEN]; @@ -925,12 +974,20 @@ zonecfg_create_snapshot(char *zonename) if ((error = zonecfg_set_zonepath(handle, rpath)) != Z_OK) goto out; } - if ((mkdir(ZONE_SNAPSHOT_ROOT, S_IRWXU) == -1) && (errno != EEXIST)) { + if (snprintf(path, sizeof (path), "%s%s", zonecfg_root, + ZONE_SNAPSHOT_ROOT) >= sizeof (path)) { + error = Z_MISC_FS; + goto out; + } + if ((mkdir(path, S_IRWXU) == -1) && (errno != EEXIST)) { error = Z_MISC_FS; goto out; } - snap_file_path(zonename, path); + if (!snap_file_path(zonename, path)) { + error = Z_MISC_FS; + goto out; + } addcomment(handle, "\n DO NOT EDIT THIS FILE. " "It is a snapshot of running zone state.\n"); @@ -2974,12 +3031,19 @@ zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz) struct zoneent *ze; FILE *cookie; int err; + char *cp; if (zone_name == NULL) return (Z_INVAL); + (void) strlcpy(zonepath, zonecfg_root, rp_sz); + cp = zonepath + strlen(zonepath); + while (cp > zonepath && cp[-1] == '/') + *--cp = '\0'; + if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) { - (void) strlcpy(zonepath, "/", rp_sz); + if (zonepath[0] == '\0') + (void) strlcpy(zonepath, "/", rp_sz); return (Z_OK); } @@ -2988,20 +3052,20 @@ zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz) * a copy of the zone path, allow for it to be zero length, in which * case we ignore this result and fall back to the XML files. */ - (void) strlcpy(zonepath, "", rp_sz); cookie = setzoneent(); while ((ze = getzoneent_private(cookie)) != NULL) { if (strcmp(ze->zone_name, zone_name) == 0) { found = B_TRUE; - if (strlen(ze->zone_path) > 0) - (void) strlcpy(zonepath, ze->zone_path, rp_sz); + if (ze->zone_path[0] != '\0') + (void) strlcpy(cp, ze->zone_path, + rp_sz - (cp - zonepath)); } free(ze); if (found) break; } endzoneent(cookie); - if (found && strlen(zonepath) > 0) + if (found && *cp != '\0') return (Z_OK); /* Fall back to the XML files. */ @@ -3037,12 +3101,27 @@ zone_get_rootpath(char *zone_name, char *rootpath, size_t rp_sz) } static zone_state_t -kernel_state_to_user_state(zone_status_t kernel_state) +kernel_state_to_user_state(zoneid_t zoneid, zone_status_t kernel_state) { + char zoneroot[MAXPATHLEN]; + size_t zlen; + assert(kernel_state <= ZONE_MAX_STATE); switch (kernel_state) { case ZONE_IS_UNINITIALIZED: + return (ZONE_STATE_READY); case ZONE_IS_READY: + /* + * If the zone's root is mounted on $ZONEPATH/lu, then + * it's a mounted scratch zone. + */ + if (zone_getattr(zoneid, ZONE_ATTR_ROOT, zoneroot, + sizeof (zoneroot)) >= 0) { + zlen = strlen(zoneroot); + if (zlen > 3 && + strcmp(zoneroot + zlen - 3, "/lu") == 0) + return (ZONE_STATE_MOUNTED); + } return (ZONE_STATE_READY); case ZONE_IS_BOOTING: case ZONE_IS_RUNNING: @@ -3067,15 +3146,33 @@ zone_get_state(char *zone_name, zone_state_t *state_num) struct zoneent *ze; boolean_t found = B_FALSE; FILE *cookie; + char kernzone[ZONENAME_MAX]; + FILE *fp; if (zone_name == NULL) return (Z_INVAL); + /* + * If we're looking at an alternate root, then we need to query the + * kernel using the scratch zone name. + */ + zone_id = -1; + if (*zonecfg_root != '\0' && !zonecfg_is_scratch(zone_name)) { + if ((fp = zonecfg_open_scratch("", B_FALSE)) != NULL) { + if (zonecfg_find_scratch(fp, zone_name, zonecfg_root, + kernzone, sizeof (kernzone)) == 0) + zone_id = getzoneidbyname(kernzone); + zonecfg_close_scratch(fp); + } + } else { + zone_id = getzoneidbyname(zone_name); + } + /* check to see if zone is running */ - if ((zone_id = getzoneidbyname(zone_name)) != -1 && + if (zone_id != -1 && zone_getattr(zone_id, ZONE_ATTR_STATUS, &status, sizeof (status)) >= 0) { - *state_num = kernel_state_to_user_state(status); + *state_num = kernel_state_to_user_state(zone_id, status); return (Z_OK); } @@ -3152,7 +3249,7 @@ zone_get_id(const char *str, zoneid_t *zip) (hdl = zonecfg_init_handle()) == NULL) return (-1); - if (zonecfg_get_handle((char *)str, hdl) == Z_OK) { + if (zonecfg_get_handle(str, hdl) == Z_OK) { /* zone exists but isn't active */ *zip = ZONE_ID_UNDEFINED; err = 0; @@ -3176,6 +3273,8 @@ zone_state_str(zone_state_t state_num) return (ZONE_STATE_STR_INSTALLED); case ZONE_STATE_READY: return (ZONE_STATE_STR_READY); + case ZONE_STATE_MOUNTED: + return (ZONE_STATE_STR_MOUNTED); case ZONE_STATE_RUNNING: return (ZONE_STATE_STR_RUNNING); case ZONE_STATE_SHUTTING_DOWN: @@ -3188,6 +3287,70 @@ zone_state_str(zone_state_t state_num) } /* + * Given a UUID value, find an associated zone name. This is intended to be + * used by callers who set up some 'default' name (corresponding to the + * expected name for the zone) in the zonename buffer, and thus the function + * doesn't touch this buffer on failure. + */ +int +zonecfg_get_name_by_uuid(const uuid_t uuid, char *zonename, size_t namelen) +{ + FILE *fp; + struct zoneent *ze; + + /* + * A small amount of subterfuge via casts is necessary here because + * libuuid doesn't use const correctly, but we don't want to export + * this brokenness to our clients. + */ + if (uuid_is_null(*(uuid_t *)&uuid)) + return (Z_NO_ZONE); + if ((fp = setzoneent()) == NULL) + return (Z_NO_ZONE); + while ((ze = getzoneent_private(fp)) != NULL) { + if (uuid_compare(*(uuid_t *)&uuid, ze->zone_uuid) == 0) + break; + free(ze); + } + endzoneent(fp); + if (ze != NULL) { + (void) strlcpy(zonename, ze->zone_name, namelen); + free(ze); + return (Z_OK); + } else { + return (Z_NO_ZONE); + } +} + +/* + * Given a zone name, get its UUID. Returns a "NULL" UUID value if the zone + * exists but the file doesn't have a value set yet. Returns an error if the + * zone cannot be located. + */ +int +zonecfg_get_uuid(const char *zonename, uuid_t uuid) +{ + FILE *fp; + struct zoneent *ze; + + if ((fp = setzoneent()) == NULL) + return (Z_NO_ZONE); + while ((ze = getzoneent_private(fp)) != NULL) { + if (strcmp(ze->zone_name, zonename) == 0) + break; + free(ze); + } + endzoneent(fp); + if (ze != NULL) { + uuid_copy(uuid, ze->zone_uuid); + free(ze); + return (Z_OK); + } else { + return (Z_NO_ZONE); + } +} + +/* * File-system convenience functions. */ boolean_t diff --git a/usr/src/lib/libzonecfg/common/scratchops.c b/usr/src/lib/libzonecfg/common/scratchops.c new file mode 100644 index 0000000000..04e5724660 --- /dev/null +++ b/usr/src/lib/libzonecfg/common/scratchops.c @@ -0,0 +1,268 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This module contains functions used for reading and writing the scratch zone + * translation files. These files are used by Live Upgrade to keep track of + * mappings between actual kernel zone names and the zones in an alternate boot + * environment. + * + * The functions are MT-safe. + * + * The file format looks like this: + * + * <zonename> <kernel-zonename> <alt-root> + * + * The expected usage model is: + * + * fp = zonecfg_open_scratch("", B_TRUE); + * zonecfg_lock_scratch(fp); + * if (zonecfg_find_scratch(fp, zonename, altroot, NULL, 0) == 0) { + * handle error; zone already mounted + * } + * mount zone here + * zonecfg_add_scratch(fp, zonename, kernname, altroot); + * zonecfg_close_scratch(fp); + * fp = zonecfg_open_scratch(zoneroot, B_TRUE); + * ftruncate(fileno(fp), 0); + * zonecfg_add_scratch(fp, zonename, kernname, "/"); + * zonecfg_close_scratch(fp); + */ + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <libzonecfg.h> + +#define PATH_MAPFILE "tmp/.alt.lu-zone-map" + +static int +lock_op(int fd, int type) +{ + struct flock lock; + + lock.l_type = type; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + + return (fcntl(fd, F_SETLKW, &lock)); +} + +FILE * +zonecfg_open_scratch(const char *rootpath, boolean_t createfile) +{ + mode_t oldmask = umask(0); + struct stat lbuf, fbuf; + int fd, flags; + FILE *fp; + char mapfile[MAXPATHLEN]; + + (void) snprintf(mapfile, sizeof (mapfile), "%s/" PATH_MAPFILE, + rootpath); + + flags = O_RDWR | O_NOFOLLOW | O_NOLINKS; + if (createfile) + flags |= O_EXCL | O_CREAT; + if ((fd = open(mapfile, flags, 0644)) == -1) { + if (!createfile) { + errno = ENOENT; + goto failure; + } + if (lstat(mapfile, &lbuf) == -1) + goto failure; + if (!S_ISREG(lbuf.st_mode) || lbuf.st_nlink != 1 || + lbuf.st_uid != 0) { + errno = EINVAL; + goto failure; + } + fd = open(mapfile, O_RDWR); + if (fd == -1) + goto failure; + if (fstat(fd, &fbuf) == -1) + goto failure; + if (lbuf.st_ino != fbuf.st_ino || lbuf.st_dev != fbuf.st_dev) { + errno = EINVAL; + goto failure; + } + } + if (lock_op(fd, F_RDLCK) == -1) + goto failure; + (void) umask(oldmask); + if ((fp = fdopen(fd, "r+")) == NULL) + (void) close(fd); + return (fp); + +failure: + if (fd != -1) + (void) close(fd); + (void) umask(oldmask); + return (NULL); +} + +int +zonecfg_lock_scratch(FILE *fp) +{ + if (fflush(fp) != 0) + return (-1); + return (lock_op(fileno(fp), F_WRLCK)); +} + +void +zonecfg_close_scratch(FILE *fp) +{ + (void) fclose(fp); +} + +int +zonecfg_get_scratch(FILE *fp, char *zonename, size_t namelen, char *kernname, + size_t kernlen, char *altroot, size_t altlen) +{ + char line[2 * ZONENAME_MAX + MAXPATHLEN + 2]; + char *cp, *cp2; + + /* We always hold at least a read lock on the file */ + for (;;) { + if (fgets(line, sizeof (line), fp) == NULL) + return (-1); + if ((cp = strchr(line, '\n')) == NULL) + return (-1); + *cp = '\0'; + if ((cp = strchr(line, ' ')) == NULL) + cp = line + strlen(line); + else + *cp++ = '\0'; + if (zonename != NULL && + strlcpy(zonename, line, namelen) >= namelen) + continue; + if ((cp2 = strchr(cp, ' ')) == NULL) + cp2 = cp + strlen(cp); + else + *cp2++ = '\0'; + if (kernname != NULL && + strlcpy(kernname, cp, kernlen) >= kernlen) + continue; + if (altroot != NULL && strlcpy(altroot, cp2, altlen) >= altlen) + continue; + break; + } + return (0); +} + +int +zonecfg_find_scratch(FILE *fp, const char *zonename, const char *altroot, + char *kernzone, size_t kernlen) +{ + char zone[ZONENAME_MAX]; + char aroot[MAXPATHLEN]; + + rewind(fp); + while (zonecfg_get_scratch(fp, zone, sizeof (zone), kernzone, kernlen, + aroot, sizeof (aroot)) == 0) { + if (strcmp(zone, zonename) == 0 && strcmp(altroot, aroot) == 0) + return (0); + } + return (-1); +} + +int +zonecfg_reverse_scratch(FILE *fp, const char *kernzone, char *zonename, + size_t namelen, char *altroot, size_t altlen) +{ + char kzone[ZONENAME_MAX]; + + rewind(fp); + while (zonecfg_get_scratch(fp, zonename, namelen, kzone, + sizeof (kzone), altroot, altlen) == 0) { + if (strcmp(kzone, kernzone) == 0) + return (0); + } + return (-1); +} + +int +zonecfg_add_scratch(FILE *fp, const char *zonename, const char *kernzone, + const char *altroot) +{ + if (fseek(fp, 0, SEEK_END) == -1) + return (-1); + if (fprintf(fp, "%s %s %s\n", zonename, kernzone, altroot) == EOF) + return (-1); + if (fflush(fp) != 0) + return (-1); + return (0); +} + +int +zonecfg_delete_scratch(FILE *fp, const char *kernzone) +{ + char zone[ZONENAME_MAX]; + char kzone[ZONENAME_MAX]; + char aroot[MAXPATHLEN]; + long roffs, woffs; + + /* + * The implementation here is intentionally quite simple. We could + * allocate a buffer that's big enough to hold the data up to + * stat.st_size and then write back out the part we need to, but there + * seems to be little point. + */ + rewind(fp); + roffs = 0; + do { + woffs = roffs; + if (zonecfg_get_scratch(fp, NULL, 0, kzone, sizeof (kzone), + NULL, 0) != 0) + return (-1); + roffs = ftell(fp); + } while (strcmp(kzone, kernzone) != 0); + while (zonecfg_get_scratch(fp, zone, sizeof (zone), kzone, + sizeof (kzone), aroot, sizeof aroot) == 0) { + roffs = ftell(fp); + if (fseek(fp, woffs, SEEK_SET) == -1) + break; + if (fprintf(fp, "%s %s %s\n", zone, kzone, aroot) == EOF) + break; + woffs = ftell(fp); + if (fseek(fp, roffs, SEEK_SET) == -1) + break; + } + (void) ftruncate(fileno(fp), woffs); + return (0); +} + +boolean_t +zonecfg_is_scratch(const char *kernzone) +{ + return (strncmp(kernzone, "SUNWlu", 6) == 0); +} diff --git a/usr/src/lib/libzonecfg/common/zonecfg_impl.h b/usr/src/lib/libzonecfg/common/zonecfg_impl.h index 9700559820..b24f94ab1e 100644 --- a/usr/src/lib/libzonecfg/common/zonecfg_impl.h +++ b/usr/src/lib/libzonecfg/common/zonecfg_impl.h @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,18 +49,31 @@ typedef enum { #define ZONE_STATE_STR_INCOMPLETE "incomplete" #define ZONE_STATE_STR_INSTALLED "installed" #define ZONE_STATE_STR_READY "ready" +#define ZONE_STATE_STR_MOUNTED "mounted" #define ZONE_STATE_STR_RUNNING "running" #define ZONE_STATE_STR_SHUTTING_DOWN "shutting_down" #define ZONE_STATE_STR_DOWN "down" -/* "::\n" => 3, no need to count '\0' as ZONENAME_MAX covers that */ -#define MAX_INDEX_LEN (ZONENAME_MAX + ZONE_STATE_MAXSTRLEN + MAXPATHLEN + 3) +/* + * ":::\n" => 4, no need to count '\0' as ZONENAME_MAX covers that. + * + * Note that both ZONE_STATE_MAXSTRLEN and MAXPATHLEN include a NUL byte, and + * this extra count of 2 bytes covers the quotes that may be placed around the + * path. + * + * The swilly "36" constant here is to cover the fact that libuuid is broken; + * see CR 6305641. + */ +#define MAX_INDEX_LEN (ZONENAME_MAX + ZONE_STATE_MAXSTRLEN + MAXPATHLEN + \ + 36 + 4) -#define ZONE_INDEX_LOCK_FILE ZONE_SNAPSHOT_ROOT "/index.lock" +#define ZONE_INDEX_LOCK_DIR ZONE_SNAPSHOT_ROOT +#define ZONE_INDEX_LOCK_FILE "/index.lock" #define ZONE_SNAPSHOT_ROOT ZONES_TMPDIR extern int putzoneent(struct zoneent *, zoneent_op_t); +extern char *zonecfg_root; #ifdef __cplusplus } diff --git a/usr/src/lib/libzonecfg/spec/libzonecfg.spec b/usr/src/lib/libzonecfg/spec/libzonecfg.spec index 3d3a84a12f..dbc9f5da9a 100644 --- a/usr/src/lib/libzonecfg/spec/libzonecfg.spec +++ b/usr/src/lib/libzonecfg/spec/libzonecfg.spec @@ -26,6 +26,24 @@ # # lib/libzonecfg/spec/libzonecfg.spec +function zonecfg_set_root +include <libzonecfg.h> +declaration void zonecfg_set_root(const char *) +version SUNWprivate_1.1 +end + +function zonecfg_get_root +include <libzonecfg.h> +declaration const char *zonecfg_get_root(void) +version SUNWprivate_1.1 +end + +function zonecfg_in_alt_root +include <libzonecfg.h> +declaration boolean_t zonecfg_in_alt_root(void) +version SUNWprivate_1.1 +end + function zonecfg_init_handle include <libzonecfg.h> declaration zone_dochandle_t zonecfg_init_handle(void) @@ -34,19 +52,20 @@ end function zonecfg_get_handle include <libzonecfg.h> -declaration int zonecfg_get_handle(char *, zone_dochandle_t) +declaration int zonecfg_get_handle(const char *, zone_dochandle_t) version SUNWprivate_1.1 end function zonecfg_get_snapshot_handle include <libzonecfg.h> -declaration int zonecfg_get_snapshot_handle(char *, zone_dochandle_t) +declaration int zonecfg_get_snapshot_handle(const char *, zone_dochandle_t) version SUNWprivate_1.1 end function zonecfg_get_template_handle include <libzonecfg.h> -declaration int zonecfg_get_template_handle(char *, char *, zone_dochandle_t) +declaration int zonecfg_get_template_handle(const char *, const char *, \ + zone_dochandle_t) version SUNWprivate_1.1 end @@ -448,13 +467,13 @@ end function zonecfg_create_snapshot include <libzonecfg.h> -declaration int zonecfg_create_snapshot(char *) +declaration int zonecfg_create_snapshot(const char *) version SUNWprivate_1.1 end function zonecfg_destroy_snapshot include <libzonecfg.h> -declaration int zonecfg_destroy_snapshot(char *) +declaration int zonecfg_destroy_snapshot(const char *) version SUNWprivate_1.1 end @@ -543,6 +562,18 @@ declaration char *zone_state_str(zone_state_t); version SUNWprivate_1.1 end +function zonecfg_get_name_by_uuid +include <libzonecfg.h> +declaration int zonecfg_get_name_by_uuid(const uuid_t, char *, size_t) +version SUNWprivate_1.1 +end + +function zonecfg_get_uuid +include <libzonecfg.h> +declaration int zonecfg_get_uuid(const char *, uuid_t) +version SUNWprivate_1.1 +end + function zonecfg_same_net_address include <libzonecfg.h> declaration boolean_t zonecfg_same_net_address(char *, char *); @@ -591,6 +622,64 @@ declaration int zonecfg_construct_rctlblk(const struct zone_rctlvaltab *, rctlbl version SUNWprivate_1.1 end +function zonecfg_open_scratch +include <libzonecfg.h> +declaration FILE *zonecfg_open_scratch(const char *, boolean_t) +version SUNWprivate_1.1 +end + +function zonecfg_lock_scratch +include <libzonecfg.h> +declaration int zonecfg_lock_scratch(FILE *) +version SUNWprivate_1.1 +end + +function zonecfg_close_scratch +include <libzonecfg.h> +declaration void zonecfg_close_scratch(FILE *) +version SUNWprivate_1.1 +end + +function zonecfg_get_scratch +include <libzonecfg.h> +declaration int zonecfg_get_scratch(FILE *, char *, size_t, char *, \ + size_t, char *, size_t) +version SUNWprivate_1.1 +end + +function zonecfg_find_scratch +include <libzonecfg.h> +declaration int zonecfg_find_scratch(FILE *, const char *, const char *, \ + char *, size_t) +version SUNWprivate_1.1 +end + +function zonecfg_reverse_scratch +include <libzonecfg.h> +declaration int zonecfg_reverse_scratch(FILE *, const char *, char *, \ + size_t, char *, size_t) +version SUNWprivate_1.1 +end + +function zonecfg_add_scratch +include <libzonecfg.h> +declaration int zonecfg_add_scratch(FILE *, const char *, const char *, \ + const char *) +version SUNWprivate_1.1 +end + +function zonecfg_delete_scratch +include <libzonecfg.h> +declaration int zonecfg_delete_scratch(FILE *, const char *) +version SUNWprivate_1.1 +end + +function zonecfg_is_scratch +include <libzonecfg.h> +declaration boolean_t zonecfg_is_scratch(const char *) +version SUNWprivate_1.1 +end + function zonecfg_find_mounts include <libzonecfg.h> declaration int zonecfg_find_mounts(char * , int (*)(char *, void*), void*); diff --git a/usr/src/uts/common/fs/nfs/nfs3_vfsops.c b/usr/src/uts/common/fs/nfs/nfs3_vfsops.c index 6023abd955..a679103377 100644 --- a/usr/src/uts/common/fs/nfs/nfs3_vfsops.c +++ b/usr/src/uts/common/fs/nfs/nfs3_vfsops.c @@ -221,7 +221,7 @@ nfs3_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) STRUCT_DECL(netbuf, addr_tmp); int flags, addr_type; char *p, *pf; - zone_t *zone = curproc->p_zone; + zone_t *zone = nfs_zone(); if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) return (EPERM); @@ -695,7 +695,7 @@ more: /* * Stop the mount from going any further if the zone is going away. */ - if (zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN) { + if (zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN) { error = EBUSY; goto errout; } @@ -772,10 +772,10 @@ nfs3rootvp(vnode_t **rtvpp, vfs_t *vfsp, struct servinfo *svp, struct nfs_stats *nfsstatsp; cred_t *lcr = NULL, *tcr = cr; - nfsstatsp = zone_getspecific(nfsstat_zone_key, curproc->p_zone); + nfsstatsp = zone_getspecific(nfsstat_zone_key, nfs_zone()); ASSERT(nfsstatsp != NULL); - ASSERT(curproc->p_zone == zone); + ASSERT(nfs_zone() == zone); /* * Create a mount record and link it to the vfs struct. */ @@ -1178,7 +1178,7 @@ nfs3_root(vfs_t *vfsp, vnode_t **vpp) mi = VFTOMI(vfsp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EPERM); svp = mi->mi_curr_serv; @@ -1223,7 +1223,7 @@ nfs3_statvfs(vfs_t *vfsp, struct statvfs64 *sbp) hrtime_t t; mi = VFTOMI(vfsp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EPERM); error = nfs3_root(vfsp, &vp); if (error) @@ -1332,7 +1332,7 @@ nfs3_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp) return (ESTALE); } - if (curproc->p_zone != VFTOMI(vfsp)->mi_zone) + if (nfs_zone() != VFTOMI(vfsp)->mi_zone) return (EPERM); fh.fh3_length = fidp->fid_len; bcopy(fidp->fid_data, fh.fh3_u.data, fh.fh3_length); diff --git a/usr/src/uts/common/fs/nfs/nfs3_vnops.c b/usr/src/uts/common/fs/nfs/nfs3_vnops.c index f93c4f80af..a53d2270b5 100644 --- a/usr/src/uts/common/fs/nfs/nfs3_vnops.c +++ b/usr/src/uts/common/fs/nfs/nfs3_vnops.c @@ -278,7 +278,7 @@ nfs3_open(vnode_t **vpp, int flag, cred_t *cr) vnode_t *vp; vp = *vpp; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); rp = VTOR(vp); mutex_enter(&rp->r_statelock); @@ -331,7 +331,7 @@ nfs3_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr) * open; if we happen to get here from the wrong zone we can't do * anything over the wire. */ - if (VTOMI(vp)->mi_zone != curproc->p_zone) { + if (VTOMI(vp)->mi_zone != nfs_zone()) { /* * We could attempt to clean up locks, except we're sure * that the current process didn't acquire any locks on @@ -440,7 +440,7 @@ nfs3_directio_read(vnode_t *vp, struct uio *uiop, cred_t *cr) char *sv_hostname; mi = VTOMI(vp); - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); sv_hostname = VTOR(vp)->r_server->sv_hostname; douprintf = 1; @@ -527,7 +527,7 @@ nfs3_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr, ASSERT(nfs_rw_lock_held(&rp->r_rwlock, RW_READER)); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (vp->v_type != VREG) @@ -616,7 +616,7 @@ nfs3_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr, return (EISDIR); mi = VTOMI(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (uiop->uio_resid == 0) return (0); @@ -828,7 +828,7 @@ nfs3_rdwrlbn(vnode_t *vp, page_t *pp, u_offset_t off, size_t len, uchar_t fsdata; stable_how stab_comm; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); bp = pageio_setup(pp, len, vp, flags); ASSERT(bp != NULL); @@ -905,7 +905,7 @@ nfs3write(vnode_t *vp, caddr_t base, u_offset_t offset, int count, cred_t *cr, rp = VTOR(vp); mi = VTOMI(vp); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); args.file = *VTOFH3(vp); args.stable = *stab_comm; @@ -1033,7 +1033,7 @@ nfs3read(vnode_t *vp, caddr_t base, offset_t offset, int count, rp = VTOR(vp); mi = VTOMI(vp); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); douprintf = 1; args.file = *VTOFH3(vp); @@ -1125,7 +1125,7 @@ static int nfs3_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) { - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); switch (cmd) { case _FIODIRECTIO: @@ -1141,7 +1141,7 @@ nfs3_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr) int error; rnode_t *rp; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* * If it has been specified that the return value will @@ -1204,7 +1204,7 @@ nfs3_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, if (vap->va_mask & AT_NOSET) return (EINVAL); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); va.va_mask = AT_UID | AT_MODE; @@ -1234,7 +1234,7 @@ nfs3setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr) vsecattr_t *vsp; hrtime_t t; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); mask = vap->va_mask; rp = VTOR(vp); @@ -1407,7 +1407,7 @@ tryagain: static int nfs3_accessx(void *vp, int mode, cred_t *cr) { - ASSERT(curproc->p_zone == VTOMI((vnode_t *)vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI((vnode_t *)vp)->mi_zone); return (nfs3_access(vp, mode, 0, cr)); } @@ -1427,7 +1427,7 @@ nfs3_access(vnode_t *vp, int mode, int flags, cred_t *cr) hrtime_t t; acc = 0; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); if (mode & VREAD) acc |= ACCESS3_READ; @@ -1564,7 +1564,7 @@ nfs3_readlink(vnode_t *vp, struct uio *uiop, cred_t *cr) */ if (vp->v_type != VLNK) return (EINVAL); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); rp = VTOR(vp); @@ -1662,7 +1662,7 @@ nfs3_fsync(vnode_t *vp, int syncflag, cred_t *cr) if ((syncflag & FNODSYNC) || IS_SWAPVP(vp)) return (0); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); error = nfs3_putpage_commit(vp, (offset_t)0, 0, cr); @@ -1690,7 +1690,7 @@ nfs3_inactive(vnode_t *vp, cred_t *cr) * potentially turn into an expensive no-op if, for instance, v_count * gets incremented in the meantime, but it's still correct. */ - if (curproc->p_zone != VTOMI(vp)->mi_zone) { + if (nfs_zone() != VTOMI(vp)->mi_zone) { nfs_async_inactive(vp, cr, nfs3_inactive); return; } @@ -1803,7 +1803,7 @@ nfs3_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp, vnode_t *avp = NULL; rnode_t *drp; - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); drp = VTOR(dvp); @@ -1885,7 +1885,7 @@ nfs3lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp, int error; rnode_t *drp; - ASSERT(curproc->p_zone == VTOMI(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(dvp)->mi_zone); /* * If lookup is for "", just return dvp. Don't need * to send it over the wire, look it up in the dnlc, @@ -1955,7 +1955,7 @@ nfs3lookup_dnlc(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr) vnode_t *vp; ASSERT(*nm != '\0'); - ASSERT(curproc->p_zone == VTOMI(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(dvp)->mi_zone); /* * Lookup this name in the DNLC. If successful, then validate * the caches and then recheck the DNLC. The DNLC is rechecked @@ -2028,7 +2028,7 @@ nfs3lookup_otw(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, ASSERT(*nm != '\0'); ASSERT(dvp->v_type == VDIR); - ASSERT(curproc->p_zone == VTOMI(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(dvp)->mi_zone); setdiropargs3(&args.what, nm, dvp); @@ -2106,7 +2106,7 @@ nfs3_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive, vnode_t *tempvp; drp = VTOR(dvp); - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); if (nfs_rw_enter_sig(&drp->r_rwlock, RW_WRITER, INTR(dvp))) return (EINTR); @@ -2274,7 +2274,7 @@ nfs3create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive, timestruc_t now; hrtime_t t; - ASSERT(curproc->p_zone == VTOMI(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(dvp)->mi_zone); setdiropargs3(&args.where, nm, dvp); if (exclusive == EXCL) { args.how.mode = EXCLUSIVE; @@ -2522,7 +2522,7 @@ nfs3excl_create_settimes(vnode_t *vp, struct vattr *vap, cred_t *cr) rnode_t *rp; hrtime_t t; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); /* save the caller's mask so that it can be reset later */ mask = vap->va_mask; @@ -2589,7 +2589,7 @@ nfs3mknod(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive, struct vattr vattr; hrtime_t t; - ASSERT(curproc->p_zone == VTOMI(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(dvp)->mi_zone); switch (va->va_type) { case VCHR: case VBLK: @@ -2707,7 +2707,7 @@ nfs3_remove(vnode_t *dvp, char *nm, cred_t *cr) rnode_t *drp; hrtime_t t; - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); drp = VTOR(dvp); if (nfs_rw_enter_sig(&drp->r_rwlock, RW_WRITER, INTR(dvp))) @@ -2843,7 +2843,7 @@ nfs3_link(vnode_t *tdvp, vnode_t *svp, char *tnm, cred_t *cr) rnode_t *tdrp; hrtime_t t; - if (curproc->p_zone != VTOMI(tdvp)->mi_zone) + if (nfs_zone() != VTOMI(tdvp)->mi_zone) return (EPERM); if (VOP_REALVP(svp, &realvp) == 0) svp = realvp; @@ -2907,7 +2907,7 @@ nfs3_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr) { vnode_t *realvp; - if (curproc->p_zone != VTOMI(odvp)->mi_zone) + if (nfs_zone() != VTOMI(odvp)->mi_zone) return (EPERM); if (VOP_REALVP(ndvp, &realvp) == 0) ndvp = realvp; @@ -2933,7 +2933,7 @@ nfs3rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr) rnode_t *ndrp; hrtime_t t; - ASSERT(curproc->p_zone == VTOMI(odvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(odvp)->mi_zone); if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 || strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0) @@ -3215,7 +3215,7 @@ nfs3_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp, cred_t *cr) rnode_t *drp; hrtime_t t; - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); setdiropargs3(&args.where, nm, dvp); @@ -3317,7 +3317,7 @@ nfs3_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr) rnode_t *drp; hrtime_t t; - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); drp = VTOR(dvp); if (nfs_rw_enter_sig(&drp->r_rwlock, RW_WRITER, INTR(dvp))) @@ -3422,7 +3422,7 @@ nfs3_symlink(vnode_t *dvp, char *lnm, struct vattr *tva, char *tnm, cred_t *cr) mi = VTOMI(dvp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EPERM); if (!(mi->mi_flags & MI_SYMLINK)) return (EOPNOTSUPP); @@ -3551,7 +3551,7 @@ nfs3_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp) rddir_cache srdc; avl_index_t where; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); rp = VTOR(vp); @@ -3841,7 +3841,7 @@ do_nfs3readdir(vnode_t *vp, rddir_cache *rdc, cred_t *cr) rp = VTOR(vp); mi = VTOMI(vp); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); /* * Issue the proper request. * @@ -3897,7 +3897,7 @@ nfs3readdir(vnode_t *vp, rddir_cache *rdc, cred_t *cr) rp = VTOR(vp); mi = VTOMI(vp); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); args.dir = *RTOFH3(rp); args.cookie = (cookie3)rdc->nfs3_cookie; @@ -4006,7 +4006,7 @@ nfs3readdirplus(vnode_t *vp, rddir_cache *rdc, cred_t *cr) rp = VTOR(vp); mi = VTOMI(vp); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); args.dir = *RTOFH3(rp); args.cookie = (cookie3)rdc->nfs3_cookie; @@ -4113,7 +4113,7 @@ nfs3_bio(struct buf *bp, stable_how *stab_comm, cred_t *cr) cred_t *cred; offset_t offset; - ASSERT(curproc->p_zone == VTOMI(bp->b_vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(bp->b_vp)->mi_zone); offset = ldbtob(bp->b_lblkno); DTRACE_IO1(start, struct buf *, bp); @@ -4268,7 +4268,7 @@ nfs3_fid(vnode_t *vp, fid_t *fidp) { rnode_t *rp; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); rp = VTOR(vp); @@ -4353,7 +4353,7 @@ nfs3_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp, if (vp->v_flag & VNOMAP) return (ENOSYS); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); if (protp != NULL) *protp = PROT_ALL; @@ -4444,7 +4444,7 @@ nfs3_getapage(vnode_t *vp, u_offset_t off, size_t len, uint_t *protp, page_t *pagefound; page_t *savepp; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); rp = VTOR(vp); bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE); @@ -4704,7 +4704,7 @@ nfs3_readahead(vnode_t *vp, u_offset_t blkoff, caddr_t addr, struct seg *seg, rnode_t *rp = VTOR(vp); page_t *savepp; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE); mutex_enter(&rp->r_statelock); @@ -4822,7 +4822,7 @@ nfs3_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr) return (ENOSYS); if (len == 0 && !(flags & B_INVAL) && vn_is_readonly(vp)) return (0); - if (!(flags & B_ASYNC) && curproc->p_zone != VTOMI(vp)->mi_zone) + if (!(flags & B_ASYNC) && nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); rp = VTOR(vp); @@ -4856,7 +4856,7 @@ nfs3_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, ASSERT(!vn_is_readonly(vp)); ASSERT(pp != NULL); ASSERT(cr != NULL); - ASSERT((flags & B_ASYNC) || curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT((flags & B_ASYNC) || nfs_zone() == VTOMI(vp)->mi_zone); rp = VTOR(vp); ASSERT(rp->r_count > 0); @@ -4969,7 +4969,7 @@ nfs3_sync_putapage(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len, int error; rnode_t *rp; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); flags |= B_WRITE; @@ -5033,7 +5033,7 @@ nfs3_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp, rnode_t *rp; struct vattr va; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); if (vp->v_flag & VNOMAP) @@ -5131,7 +5131,7 @@ nfs3_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, if (vp->v_flag & VNOMAP) return (ENOSYS); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* @@ -5158,7 +5158,7 @@ nfs3_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, rnode_t *rp; int error = 0, intr = INTR(vp); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* check for valid cmd parameter */ if (cmd != F_GETLK && cmd != F_SETLK && cmd != F_SETLKW) @@ -5305,7 +5305,7 @@ nfs3_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, ASSERT(vp->v_type == VREG); if (cmd != F_FREESP) return (EINVAL); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); error = convoff(vp, bfp, 0, offset); @@ -5368,7 +5368,7 @@ nfs3_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, * A process may not change zones if it has NFS pages mmap'ed * in, so we can't legitimately get here from the wrong zone. */ - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); rp = VTOR(vp); @@ -5482,7 +5482,7 @@ nfs3_delmap_callback(struct as *as, void *arg, uint_t event) * dirty pages. */ if ((mi->mi_flags & MI_NOCTO) || - curproc->p_zone != mi->mi_zone) + nfs_zone() != mi->mi_zone) error = nfs3_putpage(dmapp->vp, dmapp->off, dmapp->len, B_ASYNC, dmapp->cr); else @@ -5524,7 +5524,7 @@ nfs3_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr) rnode_t *rp; hrtime_t t; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* * Large file spec - need to base answer on info stored @@ -5714,7 +5714,7 @@ nfs3_sync_pageio(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len, { int error; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); error = nfs3_rdwrlbn(vp, pp, io_off, io_len, flags, cr); if (flags & B_READ) pvn_read_done(pp, (error ? B_ERROR : 0) | flags); @@ -5732,7 +5732,7 @@ nfs3_pageio(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len, if (pp == NULL) return (EINVAL); - if (!(flags & B_ASYNC) && curproc->p_zone != VTOMI(vp)->mi_zone) + if (!(flags & B_ASYNC) && nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); rp = VTOR(vp); @@ -5892,7 +5892,7 @@ nfs3_dispose(vnode_t *vp, page_t *pp, int fl, int dn, cred_t *cr) mutex_exit(&rp->r_statelock); if (curproc == proc_pageout || curproc == proc_fsflush || - curproc->p_zone != VTOMI(vp)->mi_zone) { + nfs_zone() != VTOMI(vp)->mi_zone) { nfs_async_commit(vp, plist, offset, len, cr, nfs3_async_commit); return; } @@ -5966,7 +5966,7 @@ nfs3_commit(vnode_t *vp, offset3 offset, count3 count, cred_t *cr) cred_t *cred; rp = VTOR(vp); - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); mutex_enter(&rp->r_statelock); if (rp->r_cred != NULL) { @@ -6054,7 +6054,7 @@ nfs3_set_mod(vnode_t *vp) page_t *pp; kmutex_t *vphm; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); vphm = page_vnode_mutex(vp); mutex_enter(vphm); if ((pp = vp->v_pages) != NULL) { @@ -6184,7 +6184,7 @@ nfs3_get_commit_range(vnode_t *vp, u_offset_t soff, size_t len) rp = VTOR(vp); ASSERT(rp->r_flags & RCOMMIT); - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); /* * If there are no pages associated with this vnode, then @@ -6264,7 +6264,7 @@ nfs3_putpage_commit(vnode_t *vp, offset_t poff, size_t plen, cred_t *cr) writeverf3 write_verf; rnode_t *rp = VTOR(vp); - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); /* * Flush the data portion of the file and then commit any * portions which need to be committed. This may need to @@ -6338,7 +6338,7 @@ nfs3_commit_vp(vnode_t *vp, u_offset_t poff, size_t plen, cred_t *cr) rp = VTOR(vp); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* * Set the `commit inprogress' state bit. We must @@ -6400,7 +6400,7 @@ nfs3_sync_commit(vnode_t *vp, page_t *plist, offset3 offset, count3 count, int error; page_t *pp; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); error = nfs3_commit(vp, offset, count, cr); /* @@ -6434,7 +6434,7 @@ static void nfs3_async_commit(vnode_t *vp, page_t *plist, offset3 offset, count3 count, cred_t *cr) { - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); (void) nfs3_sync_commit(vp, plist, offset, count, cr); } @@ -6446,7 +6446,7 @@ nfs3_setsecattr(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr) mi = VTOMI(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (mi->mi_flags & MI_ACL) { @@ -6466,7 +6466,7 @@ nfs3_getsecattr(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr) mi = VTOMI(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (mi->mi_flags & MI_ACL) { @@ -6486,7 +6486,7 @@ nfs3_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr) struct nfs_owner nfs_owner; netobj lm_fh3; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* diff --git a/usr/src/uts/common/fs/nfs/nfs4_callback.c b/usr/src/uts/common/fs/nfs/nfs4_callback.c index e586e33ed3..d80cde3182 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_callback.c +++ b/usr/src/uts/common/fs/nfs/nfs4_callback.c @@ -721,7 +721,7 @@ cb_dispatch(struct svc_req *req, SVCXPRT *xprt) struct nfs4_callback_globals *); void (*freeproc)(CB_COMPOUND4res *); - ncg = zone_getspecific(nfs4_callback_zone_key, curproc->p_zone); + ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone()); ASSERT(ncg != NULL); ncg->nfs4_callback_stats.cb_dispatch.value.ui64++; @@ -1058,7 +1058,7 @@ nfs4_svc(struct nfs4_svc_args *arg, model_t model) return (error); } - ncg = zone_getspecific(nfs4_callback_zone_key, curproc->p_zone); + ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone()); ASSERT(ncg != NULL); mutex_enter(&ncg->nfs4_cb_lock); @@ -1083,7 +1083,7 @@ nfs4_svc(struct nfs4_svc_args *arg, model_t model) struct nfs4_callback_globals * nfs4_get_callback_globals(void) { - return (zone_getspecific(nfs4_callback_zone_key, curproc->p_zone)); + return (zone_getspecific(nfs4_callback_zone_key, nfs_zone())); } static void * @@ -1376,8 +1376,8 @@ nfs4delegreturn_cleanup(rnode4_t *rp, nfs4_server_t *np) if (np != NULL) { ncg = np->zone_globals; - } else if (curproc->p_zone == VTOMI4(RTOV4(rp))->mi_zone) { - ncg = zone_getspecific(nfs4_callback_zone_key, curproc->p_zone); + } else if (nfs_zone() == VTOMI4(RTOV4(rp))->mi_zone) { + ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone()); ASSERT(ncg != NULL); } else { /* @@ -1722,7 +1722,7 @@ nfs4delegreturn(rnode4_t *rp, int flags) { struct nfs4_callback_globals *ncg; - ncg = zone_getspecific(nfs4_callback_zone_key, curproc->p_zone); + ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone()); ASSERT(ncg != NULL); return (nfs4delegreturn_impl(rp, flags, ncg)); @@ -2060,7 +2060,7 @@ nfs4delegreturn_thread(struct cb_recall_pass *args) callb_cpr_t cpr_info; struct nfs4_callback_globals *ncg; - ncg = zone_getspecific(nfs4_callback_zone_key, curproc->p_zone); + ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone()); ASSERT(ncg != NULL); mutex_init(&cpr_lock, NULL, MUTEX_DEFAULT, NULL); @@ -2183,7 +2183,7 @@ nfs4_delegation_accept(rnode4_t *rp, open_claim_type4 claim, OPEN4res *res, struct nfs4_callback_globals *ncg; open_delegation_type4 odt; - ncg = zone_getspecific(nfs4_callback_zone_key, curproc->p_zone); + ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone()); ASSERT(ncg != NULL); mutex_enter(&rp->r_statev4_lock); @@ -2598,7 +2598,7 @@ nfs4_dlistclean(void) { struct nfs4_callback_globals *ncg; - ncg = zone_getspecific(nfs4_callback_zone_key, curproc->p_zone); + ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone()); ASSERT(ncg != NULL); nfs4_dlistclean_impl(ncg, 0); diff --git a/usr/src/uts/common/fs/nfs/nfs4_client.c b/usr/src/uts/common/fs/nfs/nfs4_client.c index 3a2bd2f846..df575206b7 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_client.c +++ b/usr/src/uts/common/fs/nfs/nfs4_client.c @@ -1727,7 +1727,7 @@ nfs4_async_putapage(vnode_t *vp, page_t *pp, u_offset_t off, size_t len, noasync: if (curproc == proc_pageout || curproc == proc_fsflush || - curproc->p_zone == mi->mi_zone) { + nfs_zone() == mi->mi_zone) { /* * If we get here in the context of the pageout/fsflush, * or we have run out of memory or we're attempting to @@ -1748,7 +1748,7 @@ noasync: } /* - * We'll get here only if (curproc->p_zone != mi->mi_zone) + * We'll get here only if (nfs_zone() != mi->mi_zone) * which means that this was a cross-zone sync putpage. * * We pass in B_ERROR to pvn_write_done() to re-mark the pages @@ -1877,7 +1877,7 @@ noasync: return (0); } - if (curproc->p_zone != mi->mi_zone) { + if (nfs_zone() != mi->mi_zone) { /* * So this was a cross-zone sync pageio. We pass in B_ERROR * to pvn_write_done() to re-mark the pages as dirty and unlock @@ -2061,7 +2061,7 @@ nfs4_async_commit(vnode_t *vp, page_t *plist, offset3 offset, count3 count, noasync: if (curproc == proc_pageout || curproc == proc_fsflush || - curproc->p_zone != mi->mi_zone) { + nfs_zone() != mi->mi_zone) { while (plist != NULL) { pp = plist; page_sub(&plist, pp); diff --git a/usr/src/uts/common/fs/nfs/nfs4_idmap.c b/usr/src/uts/common/fs/nfs/nfs4_idmap.c index 6691416ac2..3af5d9689f 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_idmap.c +++ b/usr/src/uts/common/fs/nfs/nfs4_idmap.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -339,7 +339,7 @@ nfs_idmap_str_uid(utf8string *u8s, uid_t *uid, bool_t isserver) door_arg_t door_args; door_handle_t dh; - nig = zone_getspecific(nfsidmap_zone_key, curproc->p_zone); + nig = zone_getspecific(nfsidmap_zone_key, nfs_zone()); ASSERT(nig != NULL); if (!u8s || !u8s->utf8string_val || u8s->utf8string_len == 0 || @@ -552,7 +552,7 @@ nfs_idmap_uid_str(uid_t uid, utf8string *u8s, bool_t isserver) door_arg_t door_args; door_handle_t dh; - nig = zone_getspecific(nfsidmap_zone_key, curproc->p_zone); + nig = zone_getspecific(nfsidmap_zone_key, nfs_zone()); ASSERT(nig != NULL); /* @@ -718,7 +718,7 @@ nfs_idmap_str_gid(utf8string *u8s, gid_t *gid, bool_t isserver) door_arg_t door_args; door_handle_t dh; - nig = zone_getspecific(nfsidmap_zone_key, curproc->p_zone); + nig = zone_getspecific(nfsidmap_zone_key, nfs_zone()); ASSERT(nig != NULL); if (!u8s || !u8s->utf8string_val || u8s->utf8string_len == 0 || @@ -932,7 +932,7 @@ nfs_idmap_gid_str(gid_t gid, utf8string *u8s, bool_t isserver) door_arg_t door_args; door_handle_t dh; - nig = zone_getspecific(nfsidmap_zone_key, curproc->p_zone); + nig = zone_getspecific(nfsidmap_zone_key, nfs_zone()); ASSERT(nig != NULL); /* @@ -1138,7 +1138,7 @@ nfs_idmap_args(struct nfsidmap_args *idmp) { struct nfsidmap_globals *nig; - nig = zone_getspecific(nfsidmap_zone_key, curproc->p_zone); + nig = zone_getspecific(nfsidmap_zone_key, nfs_zone()); ASSERT(nig != NULL); nfs_idmap_cache_flush(&nig->u2s_ci); diff --git a/usr/src/uts/common/fs/nfs/nfs4_recovery.c b/usr/src/uts/common/fs/nfs/nfs4_recovery.c index 7db8b999e8..45862d6eae 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_recovery.c +++ b/usr/src/uts/common/fs/nfs/nfs4_recovery.c @@ -341,7 +341,7 @@ nfs4_start_recovery(nfs4_error_t *ep, mntinfo4_t *mi, vnode_t *vp1, bool_t abort = FALSE; bool_t gone = FALSE; - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); mutex_enter(&mi->mi_lock); /* * If there is lost state, we need to kick off recovery even if the @@ -393,7 +393,7 @@ start_recovery_action(nfs4_recov_t what, bool_t reboot, mntinfo4_t *mi, { recov_info_t *recovp; - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); mutex_enter(&mi->mi_lock); mi->mi_in_recovery++; mutex_exit(&mi->mi_lock); diff --git a/usr/src/uts/common/fs/nfs/nfs4_rnode.c b/usr/src/uts/common/fs/nfs/nfs4_rnode.c index 21a94a4a44..a105b0ba6c 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_rnode.c +++ b/usr/src/uts/common/fs/nfs/nfs4_rnode.c @@ -815,7 +815,7 @@ again: if (list_head(&rp->r_open_streams) != NULL) { mutex_exit(&rp->r_os_lock); rw_exit(&rp->r_hashq->r_lock); - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) nfs4_clear_open_streams(rp); else (void) nfs4close_all(vp, cr); diff --git a/usr/src/uts/common/fs/nfs/nfs4_subr.c b/usr/src/uts/common/fs/nfs/nfs4_subr.c index 4cc714e3ea..5c6dd2d146 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_subr.c +++ b/usr/src/uts/common/fs/nfs/nfs4_subr.c @@ -1548,8 +1548,8 @@ rfs4call(mntinfo4_t *mi, COMPOUND4args_clnt *argsp, COMPOUND4res_clnt *resp, int num_resops; struct nfs4_clnt *nfscl; - ASSERT(curproc->p_zone == mi->mi_zone); - nfscl = zone_getspecific(nfs4clnt_zone_key, curproc->p_zone); + ASSERT(nfs_zone() == mi->mi_zone); + nfscl = zone_getspecific(nfs4clnt_zone_key, nfs_zone()); ASSERT(nfscl != NULL); nfscl->nfscl_stat.calls.value.ui64++; @@ -2017,7 +2017,7 @@ nfs4_make_dotdot(nfs4_sharedfh_t *fhp, hrtime_t t, vnode_t *dvp, ((! need_start_op) && (no_need_start_op))); } #endif - ASSERT(VTOMI4(dvp)->mi_zone == curproc->p_zone); + ASSERT(VTOMI4(dvp)->mi_zone == nfs_zone()); NFS4_DEBUG(nfs4_client_shadow_debug, (CE_NOTE, "nfs4_make_dotdot: called with fhp %p, dvp %s", (void *)fhp, diff --git a/usr/src/uts/common/fs/nfs/nfs4_vfsops.c b/usr/src/uts/common/fs/nfs/nfs4_vfsops.c index 8475aaefd8..4c8be34d5d 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_vfsops.c +++ b/usr/src/uts/common/fs/nfs/nfs4_vfsops.c @@ -331,7 +331,7 @@ nfs4_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) char *p, *pf; struct pathname pn; char *userbufptr; - zone_t *zone = curproc->p_zone; + zone_t *zone = nfs_zone(); nfs4_error_t n4e; if (secpolicy_fs_mount(cr, mvp, vfsp) != 0) @@ -741,7 +741,7 @@ more: /* * Stop the mount from going any further if the zone is going away. */ - if (zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN) { + if (zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN) { error = EBUSY; goto errout; } @@ -1579,10 +1579,10 @@ nfs4rootvp(vnode_t **rtvpp, vfs_t *vfsp, struct servinfo4 *svp_head, int orig_sv_pathlen, num_retry; cred_t *lcr = NULL, *tcr = cr; - nfsstatsp = zone_getspecific(nfsstat_zone_key, curproc->p_zone); + nfsstatsp = zone_getspecific(nfsstat_zone_key, nfs_zone()); ASSERT(nfsstatsp != NULL); - ASSERT(curproc->p_zone == zone); + ASSERT(nfs_zone() == zone); ASSERT(crgetref(cr)); /* @@ -1955,7 +1955,7 @@ nfs4_unmount(vfs_t *vfsp, int flag, cred_t *cr) if (flag & MS_FORCE) { vfsp->vfs_flag |= VFS_UNMOUNTED; - if (curproc->p_zone != mi->mi_zone) { + if (nfs_zone() != mi->mi_zone) { /* * If the request is coming from the wrong zone, * we don't want to create any new threads, and @@ -2038,7 +2038,7 @@ nfs4_root(vfs_t *vfsp, vnode_t **vpp) mi = VFTOMI4(vfsp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EPERM); svp = mi->mi_curr_serv; @@ -3220,9 +3220,9 @@ nfs4_move_mi(mntinfo4_t *mi, servinfo4_t *old, servinfo4_t *new) { nfs4_server_t *p, *op = NULL, *np = NULL; int num_open; - zoneid_t zoneid = getzoneid(); + zoneid_t zoneid = nfs_zoneid(); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); mutex_enter(&nfs4_server_lst_lock); #ifdef DEBUG @@ -3310,7 +3310,7 @@ nfs4_server_t * servinfo4_to_nfs4_server(servinfo4_t *srv_p) { nfs4_server_t *np; - zoneid_t zoneid = getzoneid(); + zoneid_t zoneid = nfs_zoneid(); mutex_enter(&nfs4_server_lst_lock); for (np = nfs4_server_lst.forw; np != &nfs4_server_lst; np = np->forw) { @@ -3371,7 +3371,8 @@ find_nfs4_server_all(mntinfo4_t *mi, int all) * another zone's server list, as long as it doesn't try to contact * them. */ - ASSERT(zoneid == getzoneid() || getzoneid() == GLOBAL_ZONEID); + ASSERT(zoneid == getzoneid() || getzoneid() == GLOBAL_ZONEID || + nfs_global_client_only != 0); /* * The nfs4_server_lst_lock global lock is held when we get a new @@ -3539,7 +3540,7 @@ nfs4_free_mount(vfs_t *vfsp, cred_t *cr) * We need to participate in the CPR framework if this is a kernel * thread. */ - async_thread = (curproc == curproc->p_zone->zone_zsched); + async_thread = (curproc == nfs_zone()->zone_zsched); if (async_thread) { mutex_init(&cpr_lock, NULL, MUTEX_DEFAULT, NULL); CALLB_CPR_INIT(&cpr_info, &cpr_lock, callb_generic_cpr, diff --git a/usr/src/uts/common/fs/nfs/nfs4_vnops.c b/usr/src/uts/common/fs/nfs/nfs4_vnops.c index 0a6ad81bf4..d07cedb514 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_vnops.c +++ b/usr/src/uts/common/fs/nfs/nfs4_vnops.c @@ -586,7 +586,7 @@ nfs4_open(vnode_t **vpp, int flag, cred_t *cr) char fn[MAXNAMELEN]; NFS4_DEBUG(nfs4_client_state_debug, (CE_NOTE, "nfs4_open: ")); - if (curproc->p_zone != VTOMI4(*vpp)->mi_zone) + if (nfs_zone() != VTOMI4(*vpp)->mi_zone) return (EIO); rp = VTOR4(*vpp); @@ -820,7 +820,7 @@ nfs4open_otw(vnode_t *dvp, char *file_name, struct vattr *in_va, "open %s open flag 0x%x cred %p", file_name, open_flag, (void *)cr)); - ASSERT(curproc->p_zone == VTOMI4(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(dvp)->mi_zone); if (create_flag) { /* * We are to create a file. Initialize the passed in vnode @@ -1663,7 +1663,7 @@ nfs4_reopen(vnode_t *vp, nfs4_open_stream_t *osp, nfs4_error_t *ep, nfs4_bseqid_entry_t *bsep = NULL; ASSERT(nfs4_consistent_type(vp)); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); nfs4_error_zinit(ep); @@ -2184,7 +2184,7 @@ nfs4_open_non_reg_file(vnode_t **vpp, int flag, cred_t *cr) rnode4_t *rp; nfs4_ga_res_t gar; - ASSERT(curproc->p_zone == VTOMI4(*vpp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(*vpp)->mi_zone); /* * If close-to-open consistency checking is turned off or @@ -2225,7 +2225,7 @@ nfs4_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr) * open; if we happen to get here from the wrong zone we can't do * anything over the wire. */ - if (VTOMI4(vp)->mi_zone != curproc->p_zone) { + if (VTOMI4(vp)->mi_zone != nfs_zone()) { /* * We could attempt to clean up locks, except we're sure * that the current process didn't acquire any locks on @@ -2368,7 +2368,7 @@ nfs4close_otw(rnode4_t *rp, cred_t *cred_otw, nfs4_open_owner_t *oop, nfs4_lost_rqst_t lost_rqst; hrtime_t t; - ASSERT(curproc->p_zone == VTOMI4(RTOV4(rp))->mi_zone); + ASSERT(nfs_zone() == VTOMI4(RTOV4(rp))->mi_zone); ASSERT(MUTEX_HELD(&osp->os_sync_lock)); @@ -2552,7 +2552,7 @@ nfs4_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr, mi = VTOMI4(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (uiop->uio_resid == 0) @@ -2655,7 +2655,7 @@ nfs4_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr, mi = VTOMI4(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (uiop->uio_resid == 0) @@ -2898,7 +2898,7 @@ nfs4_rdwrlbn(vnode_t *vp, page_t *pp, u_offset_t off, size_t len, uchar_t fsdata; stable_how4 stab_comm; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); bp = pageio_setup(pp, len, vp, flags); ASSERT(bp != NULL); @@ -2953,7 +2953,7 @@ nfs4rdwr_check_osid(vnode_t *vp, nfs4_error_t *ep, cred_t *cr) mntinfo4_t *mi = VTOMI4(vp); int reopen_needed; - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); oop = find_open_owner(cr, NFS4_PERM_CREATED, mi); @@ -3028,7 +3028,7 @@ nfs4write(vnode_t *vp, caddr_t base, u_offset_t offset, int count, cred_t *cr, rp = VTOR4(vp); mi = VTOMI4(vp); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); stable = *stab_comm; *stab_comm = FILE_SYNC4; @@ -3248,7 +3248,7 @@ nfs4read(vnode_t *vp, caddr_t base, offset_t offset, int count, mi = VTOMI4(vp); doqueue = 1; - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); args.ctag = async ? TAG_READAHEAD : TAG_READ; @@ -3458,7 +3458,7 @@ recov_retry: static int nfs4_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) { - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); switch (cmd) { case _FIODIRECTIO: @@ -3474,7 +3474,7 @@ nfs4_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr) int error; rnode4_t *rp = VTOR4(vp); - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); /* * If it has been specified that the return value will @@ -3560,7 +3560,7 @@ nfs4_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, if (vap->va_mask & AT_NOSET) return (EINVAL); - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); /* @@ -3619,7 +3619,7 @@ nfs4setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, servinfo4_t *svp; bitmap4 supp_attrs; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); rp = VTOR4(vp); nfs4_init_stateid_types(&sid_types); @@ -4106,7 +4106,7 @@ nfs4_access(vnode_t *vp, int mode, int flags, cred_t *cr) nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; mntinfo4_t *mi = VTOMI4(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); acc = 0; @@ -4320,7 +4320,7 @@ nfs4_readlink(vnode_t *vp, struct uio *uiop, cred_t *cr) hrtime_t t; nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); /* * Can't readlink anything other than a symbolic link. @@ -4472,7 +4472,7 @@ nfs4_fsync(vnode_t *vp, int syncflag, cred_t *cr) if ((syncflag & FNODSYNC) || IS_SWAPVP(vp)) return (0); - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); error = nfs4_putpage_commit(vp, (offset_t)0, 0, cr); if (!error) @@ -4506,7 +4506,7 @@ nfs4_inactive(vnode_t *vp, cred_t *cr) * potentially turn into an expensive no-op if, for instance, v_count * gets incremented in the meantime, but it's still correct. */ - if (curproc->p_zone != VTOMI4(vp)->mi_zone) { + if (nfs_zone() != VTOMI4(vp)->mi_zone) { nfs4_async_inactive(vp, cr); return; } @@ -4578,7 +4578,7 @@ nfs4_inactive_otw(vnode_t *vp, cred_t *cr) char *name; #endif - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); ASSERT(!IS_SHADOW(vp, rp)); #ifdef DEBUG @@ -4778,7 +4778,7 @@ nfs4_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp, rnode4_t *drp; *vpp = NULL; - if (curproc->p_zone != VTOMI4(dvp)->mi_zone) + if (nfs_zone() != VTOMI4(dvp)->mi_zone) return (EPERM); /* * if LOOKUP_XATTR, must replace dvp (object) with @@ -4902,7 +4902,7 @@ nfs4lookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, int skipdnlc) int error; rnode4_t *drp; - ASSERT(curproc->p_zone == VTOMI4(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(dvp)->mi_zone); /* * If lookup is for "", just return dvp. Don't need @@ -5069,7 +5069,7 @@ nfs4lookupvalidate_otw(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr) nfs4_ga_res_t *garp = NULL; nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; - ASSERT(curproc->p_zone == VTOMI4(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(dvp)->mi_zone); ASSERT(nm != NULL); ASSERT(nm[0] != '\0'); ASSERT(dvp->v_type == VDIR); @@ -5498,7 +5498,7 @@ nfs4lookupnew_otw(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr) rnode4_t *drp = VTOR4(dvp); nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; - ASSERT(curproc->p_zone == VTOMI4(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(dvp)->mi_zone); ASSERT(nm != NULL); ASSERT(nm[0] != '\0'); ASSERT(dvp->v_type == VDIR); @@ -6176,7 +6176,7 @@ nfs4openattr(vnode_t *dvp, vnode_t **avp, int cflag, cred_t *cr) int needrecov = 0; nfs4_recov_state_t recov_state; - ASSERT(curproc->p_zone == VTOMI4(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(dvp)->mi_zone); *avp = NULL; recov_state.rs_flags = 0; @@ -6339,7 +6339,7 @@ nfs4_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive, enum createmode4 createmode; bool_t must_trunc = FALSE; - if (curproc->p_zone != VTOMI4(dvp)->mi_zone) + if (nfs_zone() != VTOMI4(dvp)->mi_zone) return (EPERM); if (exclusive == EXCL && (dvp->v_flag & V_XATTRDIR)) { return (EINVAL); @@ -6662,7 +6662,7 @@ call_nfs4_create_req(vnode_t *dvp, char *nm, void *data, struct vattr *va, idx_fattr = 4; } - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); if (nfs_rw_enter_sig(&drp->r_rwlock, RW_WRITER, INTR4(dvp))) { return (EINTR); } @@ -6941,7 +6941,7 @@ nfs4mknod(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive, nfs_ftype4 type; specdata4 spec, *specp = NULL; - ASSERT(curproc->p_zone == VTOMI4(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(dvp)->mi_zone); switch (va->va_type) { case VCHR: @@ -7020,7 +7020,7 @@ nfs4_remove(vnode_t *dvp, char *nm, cred_t *cr) nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; dirattr_info_t dinfo; - if (curproc->p_zone != VTOMI4(dvp)->mi_zone) + if (nfs_zone() != VTOMI4(dvp)->mi_zone) return (EPERM); drp = VTOR4(dvp); if (nfs_rw_enter_sig(&drp->r_rwlock, RW_WRITER, INTR4(dvp))) @@ -7248,7 +7248,7 @@ nfs4_link(vnode_t *tdvp, vnode_t *svp, char *tnm, cred_t *cr) ASSERT(nfs4_consistent_type(tdvp)); ASSERT(nfs4_consistent_type(svp)); - if (curproc->p_zone != VTOMI4(tdvp)->mi_zone) + if (nfs_zone() != VTOMI4(tdvp)->mi_zone) return (EPERM); if (VOP_REALVP(svp, &realvp) == 0) { svp = realvp; @@ -7438,7 +7438,7 @@ nfs4_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr) { vnode_t *realvp; - if (curproc->p_zone != VTOMI4(odvp)->mi_zone) + if (nfs_zone() != VTOMI4(odvp)->mi_zone) return (EPERM); if (VOP_REALVP(ndvp, &realvp) == 0) ndvp = realvp; @@ -7468,7 +7468,7 @@ nfs4rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr) int do_link = 1; nfsstat4 stat = NFS4_OK; - ASSERT(curproc->p_zone == VTOMI4(odvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(odvp)->mi_zone); ASSERT(nfs4_consistent_type(odvp)); ASSERT(nfs4_consistent_type(ndvp)); @@ -7842,7 +7842,7 @@ nfs4rename_persistent_fh(vnode_t *odvp, char *onm, vnode_t *renvp, nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; dirattr_info_t dinfo, *dinfop; - ASSERT(curproc->p_zone == VTOMI4(odvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(odvp)->mi_zone); recov_state.rs_flags = 0; recov_state.rs_num_retry_despite_err = 0; @@ -8034,7 +8034,7 @@ nfs4rename_volatile_fh(vnode_t *odvp, char *onm, vnode_t *ovp, nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; dirattr_info_t dinfo, *dinfop = &dinfo; - ASSERT(curproc->p_zone == VTOMI4(odvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(odvp)->mi_zone); recov_state.rs_flags = 0; recov_state.rs_num_retry_despite_err = 0; @@ -8293,7 +8293,7 @@ nfs4_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp, cred_t *cr) int error; vnode_t *vp; - if (curproc->p_zone != VTOMI4(dvp)->mi_zone) + if (nfs_zone() != VTOMI4(dvp)->mi_zone) return (EPERM); /* * As ".." has special meaning and rather than send a mkdir @@ -8342,7 +8342,7 @@ nfs4_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr) nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; dirattr_info_t dinfo, *dinfop; - if (curproc->p_zone != VTOMI4(dvp)->mi_zone) + if (nfs_zone() != VTOMI4(dvp)->mi_zone) return (EPERM); /* * As ".." has special meaning and rather than send a rmdir @@ -8526,7 +8526,7 @@ nfs4_symlink(vnode_t *dvp, char *lnm, struct vattr *tva, char *tnm, cred_t *cr) char *contents; mntinfo4_t *mi = VTOMI4(dvp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EPERM); if (!(mi->mi_flags & MI4_SYMLINK)) return (EOPNOTSUPP); @@ -8581,7 +8581,7 @@ nfs4_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp) rddir4_cache *rdc; rddir4_cache *rrdc; - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); rp = VTOR4(vp); @@ -8771,7 +8771,7 @@ do_nfs4readdir(vnode_t *vp, rddir4_cache *rdc, cred_t *cr) int error; rnode4_t *rp; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); rp = VTOR4(vp); @@ -8887,7 +8887,7 @@ nfs4readdir(vnode_t *vp, rddir4_cache *rdc, cred_t *cr) hrtime_t t; nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); ASSERT(rdc->flags & RDDIR); ASSERT(rdc->entries == NULL); @@ -9246,7 +9246,7 @@ nfs4_bio(struct buf *bp, stable_how4 *stab_comm, cred_t *cr, bool_t readahead) bool_t first_time = TRUE; /* first time getting otw cred */ bool_t last_time = FALSE; /* last time getting otw cred */ - ASSERT(curproc->p_zone == VTOMI4(bp->b_vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(bp->b_vp)->mi_zone); DTRACE_IO1(start, struct buf *, bp); offset = ldbtob(bp->b_lblkno); @@ -9421,7 +9421,7 @@ nfs4_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp) static int nfs4_seek(vnode_t *vp, offset_t ooff, offset_t *noffp) { - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); /* @@ -9449,7 +9449,7 @@ nfs4_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp, int error; mntinfo4_t *mi; - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); rp = VTOR4(vp); if (IS_SHADOW(vp, rp)) @@ -9555,7 +9555,7 @@ nfs4_getapage(vnode_t *vp, u_offset_t off, size_t len, uint_t *protp, page_t *pagefound; page_t *savepp; - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); rp = VTOR4(vp); @@ -9815,7 +9815,7 @@ nfs4_readahead(vnode_t *vp, u_offset_t blkoff, caddr_t addr, struct seg *seg, rnode4_t *rp = VTOR4(vp); page_t *savepp; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE); @@ -9927,7 +9927,7 @@ nfs4_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr) ASSERT(cr != NULL); - if (!(flags & B_ASYNC) && curproc->p_zone != VTOMI4(vp)->mi_zone) + if (!(flags & B_ASYNC) && nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); rp = VTOR4(vp); @@ -9974,7 +9974,7 @@ nfs4_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, ASSERT(!(vp->v_vfsp->vfs_flag & VFS_RDONLY)); ASSERT(pp != NULL); ASSERT(cr != NULL); - ASSERT((flags & B_ASYNC) || curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT((flags & B_ASYNC) || nfs_zone() == VTOMI4(vp)->mi_zone); rp = VTOR4(vp); ASSERT(rp->r_count > 0); @@ -10088,7 +10088,7 @@ nfs4_sync_putapage(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len, int error; rnode4_t *rp; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); flags |= B_WRITE; @@ -10157,7 +10157,7 @@ nfs4_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp, rnode4_t *rp = VTOR4(vp); mntinfo4_t *mi = VTOMI4(vp); - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); if (vp->v_flag & VNOMAP) @@ -10426,7 +10426,7 @@ nfs4_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, mi = VTOMI4(vp); rp = VTOR4(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (vp->v_flag & VNOMAP) return (ENOSYS); @@ -10538,7 +10538,7 @@ nfs4_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, int error = 0, intr = INTR4(vp); nfs4_error_t e; - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); /* check for valid cmd parameter */ @@ -10684,7 +10684,7 @@ nfs4_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, { int error; - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); ASSERT(vp->v_type == VREG); if (cmd != F_FREESP) @@ -10741,7 +10741,7 @@ nfs4_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, * A process may not change zones if it has NFS pages mmap'ed * in, so we can't legitimately get here from the wrong zone. */ - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); rp = VTOR4(vp); @@ -11003,7 +11003,7 @@ nfs4_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr) gar.n4g_ext_res = &ger; - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); if (cmd == _PC_PATH_MAX || cmd == _PC_SYMLINK_MAX) { *valp = MAXPATHLEN; @@ -11133,7 +11133,7 @@ nfs4_sync_pageio(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len, { int error; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); error = nfs4_rdwrlbn(vp, pp, io_off, io_len, flags, cr); if (flags & B_READ) @@ -11150,7 +11150,7 @@ nfs4_pageio(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len, int error; rnode4_t *rp; - if (!(flags & B_ASYNC) && curproc->p_zone != VTOMI4(vp)->mi_zone) + if (!(flags & B_ASYNC) && nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); if (pp == NULL) @@ -11314,7 +11314,7 @@ nfs4_dispose(vnode_t *vp, page_t *pp, int fl, int dn, cred_t *cr) mutex_exit(&rp->r_statelock); if (curproc == proc_pageout || curproc == proc_fsflush || - curproc->p_zone != VTOMI4(vp)->mi_zone) { + nfs_zone() != VTOMI4(vp)->mi_zone) { nfs4_async_commit(vp, plist, offset, len, cr, do_nfs4_async_commit); return; @@ -11402,7 +11402,7 @@ nfs4_commit(vnode_t *vp, offset4 offset, count4 count, cred_t *cr) bool_t last_time = FALSE; /* last time getting OTW cred */ nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); rp = VTOR4(vp); @@ -11544,7 +11544,7 @@ nfs4_set_mod(vnode_t *vp) kmutex_t *vphm; rnode4_t *rp; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); /* make sure we're looking at the master vnode, not a shadow */ @@ -11693,7 +11693,7 @@ nfs4_get_commit_range(vnode_t *vp, u_offset_t soff, size_t len) rp = VTOR4(vp); ASSERT(rp->r_flags & R4COMMIT); - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); /* make sure we're looking at the master vnode, not a shadow */ @@ -11753,7 +11753,7 @@ nfs4_putpage_commit(vnode_t *vp, offset_t poff, size_t plen, cred_t *cr) verifier4 write_verf; rnode4_t *rp = VTOR4(vp); - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); /* * Flush the data portion of the file and then commit any @@ -11831,7 +11831,7 @@ nfs4_commit_vp(vnode_t *vp, u_offset_t poff, size_t plen, offset3 offset; count3 len; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); rp = VTOR4(vp); @@ -11907,7 +11907,7 @@ nfs4_sync_commit(vnode_t *vp, page_t *plist, offset3 offset, count3 count, int error; page_t *pp; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); error = nfs4_commit(vp, (offset4)offset, (count3)count, cr); @@ -11956,7 +11956,7 @@ nfs4_setsecattr(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr) vsecattr_t nfsace4_vsap; mi = VTOMI4(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (mi->mi_flags & MI4_ACL) { /* if we have a delegation, return it */ @@ -12003,7 +12003,7 @@ nfs4_getsecattr(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr) rnode4_t *rp = VTOR4(vp); mi = VTOMI4(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); bzero(&gar, sizeof (gar)); @@ -12208,7 +12208,7 @@ nfs4_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr) { int error; - if (curproc->p_zone != VTOMI4(vp)->mi_zone) + if (nfs_zone() != VTOMI4(vp)->mi_zone) return (EIO); /* * check for valid cmd parameter @@ -12266,7 +12266,7 @@ nfs4_update_attrcache(nfsstat4 status, nfs4_ga_res_t *garp, { int error = 0; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); if (status != NFS4_OK) { /* getattr not done or failed */ @@ -12292,7 +12292,7 @@ nfs4_update_dircaches(change_info4 *cinfo, vnode_t *dvp, vnode_t *vp, char *nm, { rnode4_t *drp = VTOR4(dvp); - ASSERT(curproc->p_zone == VTOMI4(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(dvp)->mi_zone); /* Purge rddir cache for dir since it changed */ if (drp->r_dir != NULL) @@ -12397,7 +12397,7 @@ nfs4open_confirm(vnode_t *vp, seqid4 *seqid, stateid4 *stateid, cred_t *cr, OPEN_CONFIRM4args *open_confirm_args; int needrecov; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); #if DEBUG mutex_enter(&oop->oo_lock); ASSERT(oop->oo_seqid_inuse); @@ -12520,7 +12520,7 @@ state_to_cred(nfs4_open_stream_t *osp) static struct lm_sysid * nfs4_find_sysid(mntinfo4_t *mi) { - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); /* * Switch from RDMA knconf to original mount knconf @@ -12622,7 +12622,7 @@ nfs4frlock_validate_args(int cmd, flock64_t *flk, int flag, vnode_t *vp, static int nfs4frlock_get_sysid(struct lm_sysid **lspp, vnode_t *vp, flock64_t *flk) { - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); /* Find the lm_sysid */ *lspp = nfs4_find_sysid(VTOMI4(vp)); @@ -12718,7 +12718,7 @@ nfs4frlock_start_call(nfs4_lock_call_type_t ctype, vnode_t *vp, int error = 0; rnode4_t *rp; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); if (ctype == NFS4_LCK_CTYPE_NORM) { error = nfs4_start_fop(VTOMI4(vp), vp, NULL, op_hint, @@ -12853,7 +12853,7 @@ nfs4frlock_setup_lockt_args(nfs4_lock_call_type_t ctype, nfs_argop4 *argop, { LOCKT4args *lockt_args; - ASSERT(curproc->p_zone == VTOMI4(RTOV4(rp))->mi_zone); + ASSERT(nfs_zone() == VTOMI4(RTOV4(rp))->mi_zone); ASSERT(ctype == NFS4_LCK_CTYPE_NORM); argop->argop = OP_LOCKT; argsp->ctag = TAG_LOCKT; @@ -12901,7 +12901,7 @@ nfs4frlock_check_deleg(vnode_t *vp, nfs4_error_t *ep, cred_t *cr, int lt) rnode4_t *rp = VTOR4(vp); mntinfo4_t *mi = VTOMI4(vp); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); nfs4_error_zinit(ep); @@ -13005,7 +13005,7 @@ nfs4frlock_setup_locku_args(nfs4_lock_call_type_t ctype, nfs_argop4 *argop, bool_t is_spec = FALSE; rnode4_t *rp = VTOR4(vp); - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); ASSERT(ctype == NFS4_LCK_CTYPE_NORM); nfs4frlock_check_deleg(vp, ep, cr, F_UNLCK); @@ -13116,7 +13116,7 @@ nfs4frlock_setup_lock_args(nfs4_lock_call_type_t ctype, LOCK4args **lock_argsp, pid_t pid; rnode4_t *rp = VTOR4(vp); - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); nfs4frlock_check_deleg(vp, ep, cr, flk->l_type); if (ep->error || ep->stat != NFS4_OK) @@ -13174,7 +13174,7 @@ nfs4frlock_save_lost_rqst(nfs4_lock_call_type_t ctype, int error, { bool_t unlock = (flk->l_type == F_UNLCK); - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); ASSERT(ctype == NFS4_LCK_CTYPE_NORM || ctype == NFS4_LCK_CTYPE_REINSTATE); @@ -13344,7 +13344,7 @@ nfs4frlock_recovery(int needrecov, nfs4_error_t *ep, bool_t abort, retry; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); ASSERT((*argspp) != NULL); ASSERT((*respp) != NULL); if (lock_args || locku_args) @@ -13456,7 +13456,7 @@ nfs4frlock_results_ok(nfs4_lock_call_type_t ctype, int cmd, flock64_t *flk, vnode_t *vp, int flag, u_offset_t offset, nfs4_lost_rqst_t *resend_rqstp) { - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); if ((cmd == F_SETLK || cmd == F_SETLKW) && (flk->l_type == F_RDLCK || flk->l_type == F_WRLCK)) { if (ctype == NFS4_LCK_CTYPE_NORM) { @@ -13491,7 +13491,7 @@ nfs4frlock_results_denied(nfs4_lock_call_type_t ctype, LOCK4args *lock_args, nfs_resop4 *resop, cred_t *cr, bool_t *did_start_fop, bool_t *skip_get_err) { - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); if (lock_args) { nfs4_open_owner_t *oop = *oopp; @@ -13641,7 +13641,7 @@ nfs4frlock_update_state(LOCK4args *lock_args, LOCKU4args *locku_args, vnode_t *vp, flock64_t *flk, cred_t *cr, nfs4_lost_rqst_t *resend_rqstp) { - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); if (lock_args) { LOCK4res *lock_res; @@ -13708,7 +13708,7 @@ nfs4frlock_final_cleanup(nfs4_lock_call_type_t ctype, COMPOUND4args_clnt *argsp, int error = *errorp; nfs_argop4 *argop; - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); /* * The client recovery code wants the raw status information, * so don't map the NFS status code to an errno value for @@ -13867,7 +13867,7 @@ nfs4frlock(nfs4_lock_call_type_t ctype, vnode_t *vp, int cmd, flock64_t *flk, char *name; #endif - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); #ifdef DEBUG name = fn_name(VTOSV(vp)->sv_name); @@ -14185,7 +14185,7 @@ nfs4_safelock(vnode_t *vp, const struct flock64 *bfp, cred_t *cr) struct vattr va; int error; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); ASSERT(rp->r_mapcnt >= 0); NFS4_DEBUG(nfs4_client_lock_debug, (CE_NOTE, "nfs4_safelock %s: " "(%"PRIx64", %"PRIx64"); mapcnt = %ld", bfp->l_type == F_WRLCK ? @@ -14246,7 +14246,7 @@ nfs4_register_lock_locally(vnode_t *vp, struct flock64 *flk, int flag, char *name; #endif - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); #ifdef DEBUG name = fn_name(VTOSV(vp)->sv_name); @@ -14304,7 +14304,7 @@ nfs4_lockrelease(vnode_t *vp, int flag, offset_t offset, cred_t *cr) bool_t recovonly; ASSERT((uintptr_t)vp > KERNELBASE); - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); rp = VTOR4(vp); mi = VTOMI4(vp); @@ -14474,7 +14474,7 @@ vtodv(vnode_t *vp, vnode_t **dvpp, cred_t *cr, bool_t need_start_op) nfs4_fname_t *mfname; int error; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); if (vp->v_flag & VROOT) { nfs4_sharedfh_t *sfh; @@ -14639,7 +14639,7 @@ nfs4close_notw(vnode_t *vp, nfs4_open_stream_t *osp, int *have_lockp) NFS4_DEBUG(nfs4close_notw_debug, (CE_NOTE, "nfs4close_notw: " "rp=%p osp=%p", (void *)rp, (void *)osp)); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); ASSERT(mutex_owned(&osp->os_sync_lock)); ASSERT(*have_lockp); @@ -14681,7 +14681,7 @@ nfs4close_all(vnode_t *vp, cred_t *cr) nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS }; rnode4_t *rp; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); error = 0; rp = VTOR4(vp); @@ -14823,7 +14823,7 @@ nfs4close_one(vnode_t *vp, nfs4_open_stream_t *provided_osp, cred_t *cr, int did_start_seqid_sync = 0; int have_sync_lock = 0; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); NFS4_DEBUG(nfs4close_one_debug, (CE_NOTE, "closing vp %p osp %p, " "lrp %p, close type %d len %ld prot %x mmap flags %x bits %x", @@ -15567,7 +15567,7 @@ nfs4_reinstitute_local_lock_state(vnode_t *vp, flock64_t *lost_flp, cred_t *cr, * as that found in the active lock list, "list". The intersecting * region locks are added to ri_llp in increasing l_start order. */ - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); locks = flk_active_locks_for_vp(vp); ri_llp = NULL; @@ -15696,7 +15696,7 @@ push_reinstate(vnode_t *vp, int cmd, flock64_t *flk, cred_t *cr, nfs_lock_type4 locktype; nfs4_error_t e = { EINTR, NFS4_OK, RPC_SUCCESS }; - ASSERT(curproc->p_zone == VTOMI4(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI4(vp)->mi_zone); locktype = flk_to_locktype(cmd, flk->l_type); nfs4frlock_save_lost_rqst(NFS4_LCK_CTYPE_REINSTATE, EINTR, locktype, diff --git a/usr/src/uts/common/fs/nfs/nfs_client.c b/usr/src/uts/common/fs/nfs/nfs_client.c index ebc430d4c4..5bc488a65c 100644 --- a/usr/src/uts/common/fs/nfs/nfs_client.c +++ b/usr/src/uts/common/fs/nfs/nfs_client.c @@ -1461,7 +1461,7 @@ noasync: pvn_write_done(pp, flags | B_ERROR); return (0); } - if (curproc->p_zone != mi->mi_zone) { + if (nfs_zone() != mi->mi_zone) { /* * So this was a cross-zone sync putpage. We pass in B_ERROR * to pvn_write_done() to re-mark the pages as dirty and unlock @@ -1594,7 +1594,7 @@ noasync: return (0); } - if (curproc->p_zone != mi->mi_zone) { + if (nfs_zone() != mi->mi_zone) { /* * So this was a cross-zone sync pageio. We pass in B_ERROR * to pvn_write_done() to re-mark the pages as dirty and unlock @@ -1790,7 +1790,7 @@ noasync: } if (curproc == proc_pageout || curproc == proc_fsflush || - curproc->p_zone != mi->mi_zone) { + nfs_zone() != mi->mi_zone) { while (plist != NULL) { pp = plist; page_sub(&plist, pp); diff --git a/usr/src/uts/common/fs/nfs/nfs_subr.c b/usr/src/uts/common/fs/nfs/nfs_subr.c index bef0e6bb16..1451e791c9 100644 --- a/usr/src/uts/common/fs/nfs/nfs_subr.c +++ b/usr/src/uts/common/fs/nfs/nfs_subr.c @@ -454,7 +454,7 @@ clget(clinfo_t *ci, servinfo_t *svp, cred_t *cr, CLIENT **newcl, { struct nfs_clnt *nfscl; - nfscl = zone_getspecific(nfsclnt_zone_key, curproc->p_zone); + nfscl = zone_getspecific(nfsclnt_zone_key, nfs_zone()); ASSERT(nfscl != NULL); return (clget_impl(ci, svp, cr, newcl, chp, nfscl)); @@ -612,7 +612,7 @@ clfree(CLIENT *cl, struct chtab *cp) { struct nfs_clnt *nfscl; - nfscl = zone_getspecific(nfsclnt_zone_key, curproc->p_zone); + nfscl = zone_getspecific(nfsclnt_zone_key, nfs_zone()); ASSERT(nfscl != NULL); clfree_impl(cl, cp, nfscl); @@ -937,7 +937,7 @@ rfscall(mntinfo_t *mi, rpcproc_t which, xdrproc_t xdrargs, caddr_t argsp, TRACE_2(TR_FAC_NFS, TR_RFSCALL_START, "rfscall_start:which %d mi %p", which, mi); - nfscl = zone_getspecific(nfsclnt_zone_key, curproc->p_zone); + nfscl = zone_getspecific(nfsclnt_zone_key, nfs_zone()); ASSERT(nfscl != NULL); nfscl->nfscl_stat.calls.value.ui64++; @@ -1475,7 +1475,7 @@ aclcall(mntinfo_t *mi, rpcproc_t which, xdrproc_t xdrargs, caddr_t argsp, "rfscall_start:which %d mi %p", which, mi); #endif - nfscl = zone_getspecific(nfsclnt_zone_key, curproc->p_zone); + nfscl = zone_getspecific(nfsclnt_zone_key, nfs_zone()); ASSERT(nfscl != NULL); nfscl->nfscl_stat.calls.value.ui64++; @@ -4208,7 +4208,7 @@ failover_thread(mntinfo_t *mi) * DEBUG kernels, hence we don't want to pay the penalty of the lookup * on non-DEBUG kernels. */ - nfscl = zone_getspecific(nfsclnt_zone_key, curproc->p_zone); + nfscl = zone_getspecific(nfsclnt_zone_key, nfs_zone()); ASSERT(nfscl != NULL); #endif @@ -4431,7 +4431,7 @@ failover_remap(failinfo_t *fi) #ifdef DEBUG struct nfs_clnt *nfscl; - nfscl = zone_getspecific(nfsclnt_zone_key, curproc->p_zone); + nfscl = zone_getspecific(nfsclnt_zone_key, nfs_zone()); ASSERT(nfscl != NULL); #endif /* @@ -4934,3 +4934,28 @@ nfs_getsrvnames(mntinfo_t *mi, size_t *len) return (srvnames); } + +/* + * These two functions are temporary and designed for the upgrade-workaround + * only. They cannot be used for general zone-crossing NFS client support, and + * will be removed shortly. + * + * When the workaround is enabled, all NFS traffic is forced into the global + * zone. These functions are called when the code needs to refer to the state + * of the underlying network connection. They're not called when the function + * needs to refer to the state of the process that invoked the system call. + * (E.g., when checking whether the zone is shutting down during the mount() + * call.) + */ + +struct zone * +nfs_zone(void) +{ + return (nfs_global_client_only != 0 ? global_zone : curproc->p_zone); +} + +zoneid_t +nfs_zoneid(void) +{ + return (nfs_global_client_only != 0 ? GLOBAL_ZONEID : getzoneid()); +} diff --git a/usr/src/uts/common/fs/nfs/nfs_vfsops.c b/usr/src/uts/common/fs/nfs/nfs_vfsops.c index 5d5a65008b..ff4b5ecd6f 100644 --- a/usr/src/uts/common/fs/nfs/nfs_vfsops.c +++ b/usr/src/uts/common/fs/nfs/nfs_vfsops.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. @@ -222,7 +222,7 @@ nfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) STRUCT_DECL(netbuf, addr_tmp); int flags, addr_type; char *p, *pf; - zone_t *zone = curproc->p_zone; + zone_t *zone = nfs_zone(); if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) return (error); @@ -685,7 +685,7 @@ more: /* * Stop the mount from going any further if the zone is going away. */ - if (zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN) { + if (zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN) { error = EBUSY; goto errout; } @@ -856,7 +856,7 @@ nfsrootvp(vnode_t **rtvpp, vfs_t *vfsp, struct servinfo *svp, struct nfs_stats *nfsstatsp; cred_t *lcr = NULL, *tcr = cr; - nfsstatsp = zone_getspecific(nfsstat_zone_key, curproc->p_zone); + nfsstatsp = zone_getspecific(nfsstat_zone_key, nfs_zone()); ASSERT(nfsstatsp != NULL); /* @@ -1130,7 +1130,7 @@ nfs_root(vfs_t *vfsp, vnode_t **vpp) mi = VFTOMI(vfsp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EPERM); svp = mi->mi_curr_serv; @@ -1287,7 +1287,7 @@ nfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp) struct nfs_fid *nfsfidp = (struct nfs_fid *)fidp; zoneid_t zoneid = VFTOMI(vfsp)->mi_zone->zone_id; - if (curproc->p_zone != VFTOMI(vfsp)->mi_zone) + if (nfs_zone() != VFTOMI(vfsp)->mi_zone) return (EPERM); if (fidp->fid_len != (sizeof (*nfsfidp) - sizeof (short))) { #ifdef DEBUG diff --git a/usr/src/uts/common/fs/nfs/nfs_vnops.c b/usr/src/uts/common/fs/nfs/nfs_vnops.c index 99baf1312f..b98b3d280e 100644 --- a/usr/src/uts/common/fs/nfs/nfs_vnops.c +++ b/usr/src/uts/common/fs/nfs/nfs_vnops.c @@ -241,7 +241,7 @@ nfs_open(vnode_t **vpp, int flag, cred_t *cr) vp = *vpp; rp = VTOR(vp); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); mutex_enter(&rp->r_statelock); if (rp->r_cred == NULL) { @@ -293,7 +293,7 @@ nfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr) * open; if we happen to get here from the wrong zone we can't do * anything over the wire. */ - if (VTOMI(vp)->mi_zone != curproc->p_zone) { + if (VTOMI(vp)->mi_zone != nfs_zone()) { /* * We could attempt to clean up locks, except we're sure * that the current process didn't acquire any locks on @@ -404,7 +404,7 @@ nfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr, rp = VTOR(vp); mi = VTOMI(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); ASSERT(nfs_rw_lock_held(&rp->r_rwlock, RW_READER)); @@ -517,7 +517,7 @@ nfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr, rp = VTOR(vp); mi = VTOMI(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (vp->v_type != VREG) return (EISDIR); @@ -726,7 +726,7 @@ nfs_rdwrlbn(vnode_t *vp, page_t *pp, u_offset_t off, size_t len, struct buf *bp; int error; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); bp = pageio_setup(pp, len, vp, flags); ASSERT(bp != NULL); @@ -774,7 +774,7 @@ nfswrite(vnode_t *vp, caddr_t base, uint_t offset, int count, cred_t *cr) rp = VTOR(vp); mi = VTOMI(vp); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); wa.wa_args = &wa.wa_args_buf; wa.wa_fhandle = *VTOFH(vp); @@ -858,7 +858,7 @@ nfsread(vnode_t *vp, caddr_t base, uint_t offset, int count, size_t *residp, rp = VTOR(vp); mi = VTOMI(vp); - ASSERT(curproc->p_zone == mi->mi_zone); + ASSERT(nfs_zone() == mi->mi_zone); douprintf = 1; @@ -962,7 +962,7 @@ static int nfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) { - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); switch (cmd) { case _FIODIRECTIO: @@ -978,7 +978,7 @@ nfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr) int error; rnode_t *rp; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* * If it has been specified that the return value will @@ -1050,7 +1050,7 @@ nfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, vap->va_size > MAXOFF32_T) return (EFBIG); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); va.va_mask = AT_UID | AT_MODE; @@ -1085,7 +1085,7 @@ nfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr) mask = vap->va_mask; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); rp = VTOR(vp); @@ -1287,7 +1287,7 @@ nfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr) static int nfs_accessx(void *vp, int mode, cred_t *cr) { - ASSERT(curproc->p_zone == VTOMI((vnode_t *)vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI((vnode_t *)vp)->mi_zone); return (nfs_access(vp, mode, 0, cr)); } @@ -1301,7 +1301,7 @@ nfs_access(vnode_t *vp, int mode, int flags, cred_t *cr) mi = VTOMI(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (mi->mi_flags & MI_ACL) { error = acl_access2(vp, mode, flags, cr); @@ -1368,7 +1368,7 @@ nfs_readlink(vnode_t *vp, struct uio *uiop, cred_t *cr) if (vp->v_type != VLNK) return (EINVAL); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); rp = VTOR(vp); @@ -1455,7 +1455,7 @@ nfs_fsync(vnode_t *vp, int syncflag, cred_t *cr) if ((syncflag & FNODSYNC) || IS_SWAPVP(vp)) return (0); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); error = nfs_putpage(vp, (offset_t)0, 0, 0, cr); @@ -1484,7 +1484,7 @@ nfs_inactive(vnode_t *vp, cred_t *cr) * potentially turn into an expensive no-op if, for instance, v_count * gets incremented in the meantime, but it's still correct. */ - if (curproc->p_zone != VTOMI(vp)->mi_zone) { + if (nfs_zone() != VTOMI(vp)->mi_zone) { nfs_async_inactive(vp, cr, nfs_inactive); return; } @@ -1582,7 +1582,7 @@ nfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp, vnode_t *avp = NULL; rnode_t *drp; - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); drp = VTOR(dvp); @@ -1663,7 +1663,7 @@ nfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp, { int error; - ASSERT(curproc->p_zone == VTOMI(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(dvp)->mi_zone); /* * If lookup is for "", just return dvp. Don't need @@ -1727,7 +1727,7 @@ nfslookup_dnlc(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr) vnode_t *vp; ASSERT(*nm != '\0'); - ASSERT(curproc->p_zone == VTOMI(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(dvp)->mi_zone); /* * Lookup this name in the DNLC. If successful, then validate @@ -1798,7 +1798,7 @@ nfslookup_otw(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, ASSERT(*nm != '\0'); ASSERT(dvp->v_type == VDIR); - ASSERT(curproc->p_zone == VTOMI(dvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(dvp)->mi_zone); setdiropargs(&da, nm, dvp); @@ -1863,7 +1863,7 @@ nfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive, drp = VTOR(dvp); - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); if (nfs_rw_enter_sig(&drp->r_rwlock, RW_WRITER, INTR(dvp))) return (EINTR); @@ -2101,7 +2101,7 @@ nfs_remove(vnode_t *dvp, char *nm, cred_t *cr) rnode_t *rp; rnode_t *drp; - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); drp = VTOR(dvp); if (nfs_rw_enter_sig(&drp->r_rwlock, RW_WRITER, INTR(dvp))) @@ -2228,7 +2228,7 @@ nfs_link(vnode_t *tdvp, vnode_t *svp, char *tnm, cred_t *cr) int douprintf; rnode_t *tdrp; - if (curproc->p_zone != VTOMI(tdvp)->mi_zone) + if (nfs_zone() != VTOMI(tdvp)->mi_zone) return (EPERM); if (VOP_REALVP(svp, &realvp) == 0) svp = realvp; @@ -2270,7 +2270,7 @@ nfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr) { vnode_t *realvp; - if (curproc->p_zone != VTOMI(odvp)->mi_zone) + if (nfs_zone() != VTOMI(odvp)->mi_zone) return (EPERM); if (VOP_REALVP(ndvp, &realvp) == 0) ndvp = realvp; @@ -2295,7 +2295,7 @@ nfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr) rnode_t *odrp; rnode_t *ndrp; - ASSERT(curproc->p_zone == VTOMI(odvp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(odvp)->mi_zone); if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 || strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0) return (EINVAL); @@ -2560,7 +2560,7 @@ nfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp, cred_t *cr) rnode_t *drp; hrtime_t t; - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); setdiropargs(&args.ca_da, nm, dvp); @@ -2646,7 +2646,7 @@ nfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr) int douprintf; rnode_t *drp; - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); drp = VTOR(dvp); if (nfs_rw_enter_sig(&drp->r_rwlock, RW_WRITER, INTR(dvp))) @@ -2739,7 +2739,7 @@ nfs_symlink(vnode_t *dvp, char *lnm, struct vattr *tva, char *tnm, cred_t *cr) int douprintf; rnode_t *drp; - if (curproc->p_zone != VTOMI(dvp)->mi_zone) + if (nfs_zone() != VTOMI(dvp)->mi_zone) return (EPERM); setdiropargs(&args.sla_from, lnm, dvp); args.sla_sa = &args.sla_sa_buf; @@ -2818,7 +2818,7 @@ nfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp) rp = VTOR(vp); ASSERT(nfs_rw_lock_held(&rp->r_rwlock, RW_READER)); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* * Make sure that the directory cache is valid. @@ -3095,7 +3095,7 @@ nfsreaddir(vnode_t *vp, rddir_cache *rdc, cred_t *cr) int douprintf; failinfo_t fi, *fip; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); count = rdc->buflen; rp = VTOR(vp); @@ -3218,7 +3218,7 @@ nfs_bio(struct buf *bp, cred_t *cr) DTRACE_IO1(start, struct buf *, bp); - ASSERT(curproc->p_zone == VTOMI(bp->b_vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(bp->b_vp)->mi_zone); offset = dbtob(bp->b_blkno); if (bp->b_flags & B_READ) { @@ -3459,7 +3459,7 @@ nfs_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp, return (ENOSYS); ASSERT(off <= MAXOFF32_T); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); if (protp != NULL) *protp = PROT_ALL; @@ -3549,7 +3549,7 @@ nfs_getapage(vnode_t *vp, u_offset_t off, size_t len, uint_t *protp, int ra_window; /* readahead window */ page_t *pagefound; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); rp = VTOR(vp); bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE); @@ -3803,7 +3803,7 @@ nfs_readahead(vnode_t *vp, u_offset_t blkoff, caddr_t addr, struct seg *seg, uint_t bsize, blksize; rnode_t *rp = VTOR(vp); - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE); @@ -3919,7 +3919,7 @@ nfs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr) if (len == 0 && !(flags & B_INVAL) && vn_is_readonly(vp)) return (0); - if (!(flags & B_ASYNC) && curproc->p_zone != VTOMI(vp)->mi_zone) + if (!(flags & B_ASYNC) && nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); ASSERT(off <= MAXOFF32_T); @@ -3954,7 +3954,7 @@ nfs_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, ASSERT(!vn_is_readonly(vp)); ASSERT(pp != NULL); ASSERT(cr != NULL); - ASSERT((flags & B_ASYNC) || curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT((flags & B_ASYNC) || nfs_zone() == VTOMI(vp)->mi_zone); rp = VTOR(vp); ASSERT(rp->r_count > 0); @@ -4071,7 +4071,7 @@ nfs_sync_putapage(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len, flags |= B_WRITE; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); error = nfs_rdwrlbn(vp, pp, io_off, io_len, flags, cr); rp = VTOR(vp); @@ -4129,7 +4129,7 @@ nfs_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp, rnode_t *rp; struct vattr va; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); if (vp->v_flag & VNOMAP) @@ -4230,7 +4230,7 @@ nfs_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, if (vp->v_flag & VNOMAP) return (ENOSYS); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* @@ -4260,7 +4260,7 @@ nfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, /* check for valid cmd parameter */ if (cmd != F_GETLK && cmd != F_SETLK && cmd != F_SETLKW) return (EINVAL); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* Verify l_type. */ @@ -4414,7 +4414,7 @@ nfs_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, (bfp->l_len > MAXOFF32_T)) return (EFBIG); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); error = convoff(vp, bfp, 0, offset); @@ -4477,7 +4477,7 @@ nfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, * A process may not change zones if it has NFS pages mmap'ed * in, so we can't legitimately get here from the wrong zone. */ - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); rp = VTOR(vp); @@ -4591,7 +4591,7 @@ nfs_delmap_callback(struct as *as, void *arg, uint_t event) * dirty pages. */ if ((mi->mi_flags & MI_NOCTO) || - curproc->p_zone != mi->mi_zone) + nfs_zone() != mi->mi_zone) error = nfs_putpage(dmapp->vp, dmapp->off, dmapp->len, B_ASYNC, dmapp->cr); else @@ -4621,7 +4621,7 @@ nfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr) { int error = 0; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* * This looks a little weird because it's written in a general @@ -4729,7 +4729,7 @@ nfs_sync_pageio(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len, { int error; - ASSERT(curproc->p_zone == VTOMI(vp)->mi_zone); + ASSERT(nfs_zone() == VTOMI(vp)->mi_zone); error = nfs_rdwrlbn(vp, pp, io_off, io_len, flags, cr); if (flags & B_READ) pvn_read_done(pp, (error ? B_ERROR : 0) | flags); @@ -4750,7 +4750,7 @@ nfs_pageio(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len, if (io_off > MAXOFF32_T) return (EFBIG); - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); rp = VTOR(vp); mutex_enter(&rp->r_statelock); @@ -4777,7 +4777,7 @@ nfs_setsecattr(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr) mi = VTOMI(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (mi->mi_flags & MI_ACL) { error = acl_setacl2(vp, vsecattr, flag, cr); @@ -4796,7 +4796,7 @@ nfs_getsecattr(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr) mi = VTOMI(vp); - if (curproc->p_zone != mi->mi_zone) + if (nfs_zone() != mi->mi_zone) return (EIO); if (mi->mi_flags & MI_ACL) { error = acl_getacl2(vp, vsecattr, flag, cr); @@ -4815,7 +4815,7 @@ nfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr) struct nfs_owner nfs_owner; netobj lm_fh; - if (curproc->p_zone != VTOMI(vp)->mi_zone) + if (nfs_zone() != VTOMI(vp)->mi_zone) return (EIO); /* diff --git a/usr/src/uts/common/fs/vnode.c b/usr/src/uts/common/fs/vnode.c index 74dfbc8205..1e7793ba39 100644 --- a/usr/src/uts/common/fs/vnode.c +++ b/usr/src/uts/common/fs/vnode.c @@ -72,6 +72,9 @@ ((vp)->v_type != VCHR && (vp)->v_type != VBLK && \ (vp)->v_type != VFIFO && vn_is_readonly(vp)) +/* Tunable via /etc/system; used only by admin/install */ +int nfs_global_client_only; + /* * Convert stat(2) formats to vnode types and vice versa. (Knows about * numerical order of S_IFMT and vnode types.) @@ -1843,6 +1846,9 @@ vn_can_change_zones(vnode_t *vp) int allow = 1; vnode_t *rvp; + if (nfs_global_client_only != 0) + return (1); + /* * We always want to look at the underlying vnode if there is one. */ diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c index 9b995cd7df..e89068125f 100644 --- a/usr/src/uts/common/inet/tcp/tcp.c +++ b/usr/src/uts/common/inet/tcp/tcp.c @@ -8912,6 +8912,13 @@ tcp_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) dev_t conn_dev; zoneid_t zoneid = getzoneid(); + /* + * Special case for install: miniroot needs to be able to access files + * via NFS as though it were always in the global zone. + */ + if (credp == kcred && nfs_global_client_only != 0) + zoneid = GLOBAL_ZONEID; + if (q->q_ptr != NULL) return (0); diff --git a/usr/src/uts/common/ktli/t_kopen.c b/usr/src/uts/common/ktli/t_kopen.c index f05a9cbdb5..c49b03b610 100644 --- a/usr/src/uts/common/ktli/t_kopen.c +++ b/usr/src/uts/common/ktli/t_kopen.c @@ -80,6 +80,13 @@ t_kopen(file_t *fp, dev_t rdev, int flags, TIUSER **tiptr, cred_t *cr) TIUSER *ntiptr; int rtries = 0; + /* + * Special case for install: miniroot needs to be able to access files + * via NFS as though it were always in the global zone. + */ + if (nfs_global_client_only != 0) + cr = kcred; + KTLILOG(2, "t_kopen: fp %x, ", fp); KTLILOG(2, "rdev %x, ", rdev); KTLILOG(2, "flags %x\n", flags); diff --git a/usr/src/uts/common/nfs/rnode.h b/usr/src/uts/common/nfs/rnode.h index ef1aa644c4..11520dd356 100644 --- a/usr/src/uts/common/nfs/rnode.h +++ b/usr/src/uts/common/nfs/rnode.h @@ -382,6 +382,8 @@ extern void nfs_rw_destroy(nfs_rwlock_t *); extern int nfs_directio(vnode_t *, int, cred_t *); extern int nfs3_rddir_compar(const void *, const void *); extern int nfs_rddir_compar(const void *, const void *); +extern struct zone *nfs_zone(void); +extern zoneid_t nfs_zoneid(void); #endif diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c index e7b929c406..b4abecaadf 100644 --- a/usr/src/uts/common/os/zone.c +++ b/usr/src/uts/common/os/zone.c @@ -3090,6 +3090,15 @@ zone_destroy(zoneid_t zoneid) (mod_hash_key_t)(uintptr_t)zone->zone_id); mutex_exit(&zonehash_lock); + /* + * Release the root vnode; we're not using it anymore. Nor should any + * other thread that might access it exist. + */ + if (zone->zone_rootvp != NULL) { + VN_RELE(zone->zone_rootvp); + zone->zone_rootvp = NULL; + } + /* add to deathrow list */ mutex_enter(&zone_deathrow_lock); list_insert_tail(&zone_deathrow, zone); diff --git a/usr/src/uts/common/rpc/clnt.h b/usr/src/uts/common/rpc/clnt.h index 1600176aa0..f422f039d6 100644 --- a/usr/src/uts/common/rpc/clnt.h +++ b/usr/src/uts/common/rpc/clnt.h @@ -340,6 +340,9 @@ typedef struct calllist_s { */ extern uint32_t alloc_xid(void); +extern struct zone *rpc_zone(void); +extern zoneid_t rpc_zoneid(void); + extern int clnt_tli_kcreate(struct knetconfig *config, struct netbuf *svcaddr, rpcprog_t, rpcvers_t, uint_t max_msgsize, int retrys, struct cred *cred, CLIENT **ncl); diff --git a/usr/src/uts/common/rpc/clnt_clts.c b/usr/src/uts/common/rpc/clnt_clts.c index a694a0351d..affd816ae7 100644 --- a/usr/src/uts/common/rpc/clnt_clts.c +++ b/usr/src/uts/common/rpc/clnt_clts.c @@ -374,7 +374,7 @@ clnt_clts_kinit(CLIENT *h, struct netbuf *addr, int retrys, cred_t *cred) struct cku_private *p = htop(h); struct rpcstat *rsp; - rsp = zone_getspecific(rpcstat_zone_key, curproc->p_zone); + rsp = zone_getspecific(rpcstat_zone_key, rpc_zone()); ASSERT(rsp != NULL); p->cku_retrys = retrys; @@ -1296,7 +1296,7 @@ endpnt_type_create(struct knetconfig *config) mutex_init(&etype->e_plock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&etype->e_ilock, NULL, MUTEX_DEFAULT, NULL); etype->e_rdev = config->knc_rdev; - etype->e_zoneid = getzoneid(); + etype->e_zoneid = rpc_zoneid(); etype->e_async_count = 0; cv_init(&etype->e_async_cv, NULL, CV_DEFAULT, NULL); @@ -1427,7 +1427,7 @@ endpnt_get(struct knetconfig *config, int useresvport) int i = 0; int error; int retval; - zoneid_t zoneid = getzoneid(); + zoneid_t zoneid = rpc_zoneid(); RPCLOG(1, "endpnt_get: protofmly %s, ", config->knc_protofmly); RPCLOG(1, "rdev %ld\n", config->knc_rdev); diff --git a/usr/src/uts/common/rpc/clnt_cots.c b/usr/src/uts/common/rpc/clnt_cots.c index 965fb3056f..e5a7e5b3d7 100644 --- a/usr/src/uts/common/rpc/clnt_cots.c +++ b/usr/src/uts/common/rpc/clnt_cots.c @@ -543,7 +543,7 @@ clnt_cots_kcreate(dev_t dev, struct netbuf *addr, int family, rpcprog_t prog, RPCLOG(8, "clnt_cots_kcreate: prog %u\n", prog); - rpcstat = zone_getspecific(rpcstat_zone_key, curproc->p_zone); + rpcstat = zone_getspecific(rpcstat_zone_key, rpc_zone()); ASSERT(rpcstat != NULL); /* Allocate and intialize the client handle. */ @@ -1737,7 +1737,7 @@ connmgr_get( clock_t prev_time; int tidu_size; bool_t connected; - zoneid_t zoneid = getzoneid(); + zoneid_t zoneid = rpc_zoneid(); /* * If the call is not a retry, look for a transport entry that @@ -2459,7 +2459,7 @@ connmgr_connect( */ struct rpcstat *rpcstat; - rpcstat = zone_getspecific(rpcstat_zone_key, curproc->p_zone); + rpcstat = zone_getspecific(rpcstat_zone_key, rpc_zone()); ASSERT(rpcstat != NULL); RPCLOG0(1, "connmgr_connect: cannot alloc mp for " diff --git a/usr/src/uts/common/rpc/mt_rpcinit.c b/usr/src/uts/common/rpc/mt_rpcinit.c index 630345e5f5..65cfc46b34 100644 --- a/usr/src/uts/common/rpc/mt_rpcinit.c +++ b/usr/src/uts/common/rpc/mt_rpcinit.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -167,3 +167,20 @@ alloc_xid(void) mutex_exit(&xid_lock); return (xid); } + +/* + * These functions are temporary and designed for the upgrade-workaround only. + * They cannot be used for general zone-crossing RPC client support, and will + * be removed shortly. + */ +struct zone * +rpc_zone(void) +{ + return (nfs_global_client_only != 0 ? global_zone : curproc->p_zone); +} + +zoneid_t +rpc_zoneid(void) +{ + return (nfs_global_client_only != 0 ? GLOBAL_ZONEID : getzoneid()); +} diff --git a/usr/src/uts/common/rpc/rpcmod.c b/usr/src/uts/common/rpc/rpcmod.c index be8a2c341f..2f1d601a5a 100644 --- a/usr/src/uts/common/rpc/rpcmod.c +++ b/usr/src/uts/common/rpc/rpcmod.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1990 Mentat Inc. */ @@ -496,7 +496,7 @@ rpcmodopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp) mutex_init(&rmp->rm_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&rmp->rm_cwait, NULL, CV_DEFAULT, NULL); - rmp->rm_zoneid = getzoneid(); + rmp->rm_zoneid = rpc_zoneid(); /* * slot type will be set by kRPC client and server ioctl's */ @@ -1380,7 +1380,7 @@ mir_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) mir->mir_frag_len = -(int32_t)sizeof (uint32_t); - mir->mir_zoneid = getzoneid(); + mir->mir_zoneid = rpc_zoneid(); mutex_init(&mir->mir_mutex, NULL, MUTEX_DEFAULT, NULL); cv_init(&mir->mir_condvar, NULL, CV_DRIVER, NULL); cv_init(&mir->mir_timer_cv, NULL, CV_DRIVER, NULL); diff --git a/usr/src/uts/common/sys/systm.h b/usr/src/uts/common/sys/systm.h index 36ef678d4a..1015641e7f 100644 --- a/usr/src/uts/common/sys/systm.h +++ b/usr/src/uts/common/sys/systm.h @@ -110,6 +110,12 @@ extern char *isa_list; /* For sysinfo's isalist option */ extern int noexec_user_stack; /* patchable via /etc/system */ extern int noexec_user_stack_log; /* patchable via /etc/system */ +/* + * Use NFS client operations in the global zone only. Under contract with + * admin/install; do not change without coordinating with that consolidation. + */ +extern int nfs_global_client_only; + extern void report_stack_exec(proc_t *, caddr_t); extern void startup(void); diff --git a/usr/src/uts/common/sys/zone.h b/usr/src/uts/common/sys/zone.h index 867e531c85..0bc997a57b 100644 --- a/usr/src/uts/common/sys/zone.h +++ b/usr/src/uts/common/sys/zone.h @@ -120,7 +120,8 @@ typedef enum { * communicates with zoneadmd, but only uses Z_REBOOT and Z_HALT. */ typedef enum zone_cmd { - Z_READY, Z_BOOT, Z_REBOOT, Z_HALT, Z_NOTE_UNINSTALLING + Z_READY, Z_BOOT, Z_REBOOT, Z_HALT, Z_NOTE_UNINSTALLING, + Z_MOUNT, Z_UNMOUNT } zone_cmd_t; #define ZONEBOOTARGS_MAX 257 /* uadmin()'s buffer is 257 bytes. */ |
