7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "@(#)vplat.c 1.60 08/04/08 SMI"
28
29 /*
30 * This module contains functions used to bring up and tear down the
31 * Virtual Platform: [un]mounting file-systems, [un]plumbing network
32 * interfaces, [un]configuring devices, establishing resource controls,
33 * and creating/destroying the zone in the kernel. These actions, on
34 * the way up, ready the zone; on the way down, they halt the zone.
35 * See the much longer block comment at the beginning of zoneadmd.c
36 * for a bigger picture of how the whole program functions.
37 *
38 * This module also has primary responsibility for the layout of "scratch
39 * zones." These are mounted, but inactive, zones that are used during
40 * operating system upgrade and potentially other administrative action. The
41 * scratch zone environment is similar to the miniroot environment. The zone's
42 * actual root is mounted read-write on /a, and the standard paths (/usr,
43 * /sbin, /lib) all lead to read-only copies of the running system's binaries.
44 * This allows the administrative tools to manipulate the zone using "-R /a"
45 * without relying on any binaries in the zone itself.
46 *
47 * If the scratch zone is on an alternate root (Live Upgrade [LU] boot
787
788 _exit(ZEXIT_EXEC);
789 } else {
790 (void) waitpid(child_pid, &child_status, 0);
791 }
792
793 if (WIFSIGNALED(child_status)) {
794 zerror(zlogp, B_FALSE, "%s unexpectedly terminated due to "
795 "signal %d", path, WTERMSIG(child_status));
796 return (-1);
797 }
798 assert(WIFEXITED(child_status));
799 if (WEXITSTATUS(child_status) == ZEXIT_EXEC) {
800 zerror(zlogp, B_FALSE, "failed to exec %s", path);
801 return (-1);
802 }
803 return (WEXITSTATUS(child_status));
804 }
805
806 static int
807 dofsck(zlog_t *zlogp, const char *fstype, const char *rawdev)
808 {
809 char cmdbuf[MAXPATHLEN];
810 char *argv[4];
811 int status;
812
813 /*
814 * We could alternatively have called /usr/sbin/fsck -F <fstype>, but
815 * that would cost us an extra fork/exec without buying us anything.
816 */
817 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck", fstype)
818 >= sizeof (cmdbuf)) {
819 zerror(zlogp, B_FALSE, "file-system type %s too long", fstype);
820 return (-1);
821 }
822
823 argv[0] = "fsck";
824 argv[1] = "-m";
825 argv[2] = (char *)rawdev;
826 argv[3] = NULL;
827
828 status = forkexec(zlogp, cmdbuf, argv);
829 if (status == 0 || status == -1)
830 return (status);
831 zerror(zlogp, B_FALSE, "fsck of '%s' failed with exit status %d; "
832 "run fsck manually", rawdev, status);
833 return (-1);
834 }
835
836 static int
837 domount(zlog_t *zlogp, const char *fstype, const char *opts,
838 const char *special, const char *directory)
839 {
840 char cmdbuf[MAXPATHLEN];
841 char *argv[6];
842 int status;
1244 * of the device instead of a direct mount
1245 */
1246 if (check_lofs_needed(zlogp, fsptr) == -1)
1247 return (-1);
1248 } else if (strcmp(fsptr->zone_fs_type, MNTTYPE_LOFS) == 0) {
1249 /*
1250 * For lofs mounts, the special node is inside the
1251 * alternate root. We need lofs resolution for
1252 * this case in order to get at the underlying
1253 * read-write path.
1254 */
1255 resolve_lofs(zlogp, fsptr->zone_fs_special,
1256 sizeof (fsptr->zone_fs_special));
1257 }
1258 }
1259
1260 /*
1261 * Run 'fsck -m' if there's a device to fsck.
1262 */
1263 if (fsptr->zone_fs_raw[0] != '\0' &&
1264 dofsck(zlogp, fsptr->zone_fs_type, fsptr->zone_fs_raw) != 0)
1265 return (-1);
1266
1267 /*
1268 * Build up mount option string.
1269 */
1270 optstr[0] = '\0';
1271 if (fsptr->zone_fs_options != NULL) {
1272 (void) strlcpy(optstr, fsptr->zone_fs_options->zone_fsopt_opt,
1273 sizeof (optstr));
1274 for (optptr = fsptr->zone_fs_options->zone_fsopt_next;
1275 optptr != NULL; optptr = optptr->zone_fsopt_next) {
1276 (void) strlcat(optstr, ",", sizeof (optstr));
1277 (void) strlcat(optstr, optptr->zone_fsopt_opt,
1278 sizeof (optstr));
1279 }
1280 }
1281
1282 if ((rv = domount(zlogp, fsptr->zone_fs_type, optstr,
1283 fsptr->zone_fs_special, path)) != 0)
1284 return (rv);
1285
|
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "@(#)vplat.c 1.61 08/05/07 SMI"
28
29 /*
30 * This module contains functions used to bring up and tear down the
31 * Virtual Platform: [un]mounting file-systems, [un]plumbing network
32 * interfaces, [un]configuring devices, establishing resource controls,
33 * and creating/destroying the zone in the kernel. These actions, on
34 * the way up, ready the zone; on the way down, they halt the zone.
35 * See the much longer block comment at the beginning of zoneadmd.c
36 * for a bigger picture of how the whole program functions.
37 *
38 * This module also has primary responsibility for the layout of "scratch
39 * zones." These are mounted, but inactive, zones that are used during
40 * operating system upgrade and potentially other administrative action. The
41 * scratch zone environment is similar to the miniroot environment. The zone's
42 * actual root is mounted read-write on /a, and the standard paths (/usr,
43 * /sbin, /lib) all lead to read-only copies of the running system's binaries.
44 * This allows the administrative tools to manipulate the zone using "-R /a"
45 * without relying on any binaries in the zone itself.
46 *
47 * If the scratch zone is on an alternate root (Live Upgrade [LU] boot
787
788 _exit(ZEXIT_EXEC);
789 } else {
790 (void) waitpid(child_pid, &child_status, 0);
791 }
792
793 if (WIFSIGNALED(child_status)) {
794 zerror(zlogp, B_FALSE, "%s unexpectedly terminated due to "
795 "signal %d", path, WTERMSIG(child_status));
796 return (-1);
797 }
798 assert(WIFEXITED(child_status));
799 if (WEXITSTATUS(child_status) == ZEXIT_EXEC) {
800 zerror(zlogp, B_FALSE, "failed to exec %s", path);
801 return (-1);
802 }
803 return (WEXITSTATUS(child_status));
804 }
805
806 static int
807 isregfile(const char *path)
808 {
809 struct stat64 st;
810
811 if (stat64(path, &st) == -1)
812 return (-1);
813
814 return (S_ISREG(st.st_mode));
815 }
816
817 static int
818 dofsck(zlog_t *zlogp, const char *fstype, const char *rawdev)
819 {
820 char cmdbuf[MAXPATHLEN];
821 char *argv[4];
822 int status;
823
824 /*
825 * We could alternatively have called /usr/sbin/fsck -F <fstype>, but
826 * that would cost us an extra fork/exec without buying us anything.
827 */
828 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck", fstype)
829 >= sizeof (cmdbuf)) {
830 zerror(zlogp, B_FALSE, "file-system type %s too long", fstype);
831 return (-1);
832 }
833
834 /*
835 * If it doesn't exist, that's OK: we verified this previously.
836 */
837 if (isregfile(cmdbuf) == -1)
838 return (0);
839
840 argv[0] = "fsck";
841 argv[1] = "-m";
842 argv[2] = (char *)rawdev;
843 argv[3] = NULL;
844
845 status = forkexec(zlogp, cmdbuf, argv);
846 if (status == 0 || status == -1)
847 return (status);
848 zerror(zlogp, B_FALSE, "fsck of '%s' failed with exit status %d; "
849 "run fsck manually", rawdev, status);
850 return (-1);
851 }
852
853 static int
854 domount(zlog_t *zlogp, const char *fstype, const char *opts,
855 const char *special, const char *directory)
856 {
857 char cmdbuf[MAXPATHLEN];
858 char *argv[6];
859 int status;
1261 * of the device instead of a direct mount
1262 */
1263 if (check_lofs_needed(zlogp, fsptr) == -1)
1264 return (-1);
1265 } else if (strcmp(fsptr->zone_fs_type, MNTTYPE_LOFS) == 0) {
1266 /*
1267 * For lofs mounts, the special node is inside the
1268 * alternate root. We need lofs resolution for
1269 * this case in order to get at the underlying
1270 * read-write path.
1271 */
1272 resolve_lofs(zlogp, fsptr->zone_fs_special,
1273 sizeof (fsptr->zone_fs_special));
1274 }
1275 }
1276
1277 /*
1278 * Run 'fsck -m' if there's a device to fsck.
1279 */
1280 if (fsptr->zone_fs_raw[0] != '\0' &&
1281 dofsck(zlogp, fsptr->zone_fs_type, fsptr->zone_fs_raw) != 0) {
1282 return (-1);
1283 } else if (isregfile(fsptr->zone_fs_special) == 1 &&
1284 dofsck(zlogp, fsptr->zone_fs_type, fsptr->zone_fs_special) != 0) {
1285 return (-1);
1286 }
1287
1288 /*
1289 * Build up mount option string.
1290 */
1291 optstr[0] = '\0';
1292 if (fsptr->zone_fs_options != NULL) {
1293 (void) strlcpy(optstr, fsptr->zone_fs_options->zone_fsopt_opt,
1294 sizeof (optstr));
1295 for (optptr = fsptr->zone_fs_options->zone_fsopt_next;
1296 optptr != NULL; optptr = optptr->zone_fsopt_next) {
1297 (void) strlcat(optstr, ",", sizeof (optstr));
1298 (void) strlcat(optstr, optptr->zone_fsopt_opt,
1299 sizeof (optstr));
1300 }
1301 }
1302
1303 if ((rv = domount(zlogp, fsptr->zone_fs_type, optstr,
1304 fsptr->zone_fs_special, path)) != 0)
1305 return (rv);
1306
|