6 * You may not use this file except in compliance with the License.
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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25 /*
26 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
27 */
28
29 /*
30 * System includes
31 */
32 #include <assert.h>
33 #include <errno.h>
34 #include <libintl.h>
35 #include <libnvpair.h>
36 #include <libzfs.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/mntent.h>
41 #include <sys/mnttab.h>
42 #include <sys/mount.h>
43 #include <sys/stat.h>
44 #include <sys/types.h>
45 #include <sys/vfstab.h>
46 #include <sys/zone.h>
47 #include <sys/mkdev.h>
48 #include <unistd.h>
49
50 #include <libbe.h>
51 #include <libbe_priv.h>
52
53 #define BE_TMP_MNTPNT "/tmp/.be.XXXXXX"
309 return (ret);
310 }
311
312 /*
313 * If altroot not provided, create a temporary alternate root
314 * to mount on
315 */
316 if (*altroot == NULL) {
317 if ((ret = be_make_tmp_mountpoint(&tmp_altroot))
318 != BE_SUCCESS) {
319 be_print_err(gettext("be_mount: failed to "
320 "make temporary mountpoint\n"));
321 ZFS_CLOSE(zhp);
322 return (ret);
323 }
324 gen_tmp_altroot = B_TRUE;
325 } else {
326 tmp_altroot = *altroot;
327 }
328
329 /* Mount the BE's root file system */
330 if ((ret = be_mount_root(zhp, tmp_altroot)) != BE_SUCCESS) {
331 be_print_err(gettext("be_mount: failed to "
332 "mount BE root file system\n"));
333 if (gen_tmp_altroot)
334 free(tmp_altroot);
335 ZFS_CLOSE(zhp);
336 return (ret);
337 }
338
339 /* Iterate through BE's children filesystems */
340 if ((err = zfs_iter_filesystems(zhp, be_mount_callback,
341 tmp_altroot)) != 0) {
342 be_print_err(gettext("be_mount: failed to "
343 "mount BE (%s) on %s\n"), bt.obe_name, tmp_altroot);
344 if (gen_tmp_altroot)
345 free(tmp_altroot);
346 ZFS_CLOSE(zhp);
347 return (err);
348 }
349
350 md.altroot = tmp_altroot;
351 md.shared_fs = flags & BE_MOUNT_FLAG_SHARED_FS;
352 md.shared_rw = flags & BE_MOUNT_FLAG_SHARED_RW;
353
354 /*
355 * Mount shared file systems if mount flag says so.
356 */
357 if (md.shared_fs) {
358 /*
359 * Mount all ZFS file systems not under the BE's root dataset
360 */
361 (void) zpool_iter(g_zfs, zpool_shared_fs_callback, &md);
362
363 /* TODO: Mount all non-ZFS file systems - Not supported yet */
364 }
365
366 /*
367 * If we're in the global zone and the global zone has a valid uuid,
368 * mount all supported non-global zones.
369 */
370 if (getzoneid() == GLOBAL_ZONEID &&
371 !(flags & BE_MOUNT_FLAG_NO_ZONES) &&
372 be_get_uuid(bt.obe_root_ds, &uu) == BE_SUCCESS) {
373 if ((ret = be_mount_zones(zhp, &md)) != BE_SUCCESS) {
511 /* TODO: Unmount all non-ZFS file systems - Not supported yet */
512
513 /* Unmount all ZFS file systems not under the BE root dataset */
514 if ((ret = unmount_shared_fs(&ud)) != BE_SUCCESS) {
515 be_print_err(gettext("be_unmount: failed to "
516 "unmount shared file systems\n"));
517 ZFS_CLOSE(zhp);
518 return (ret);
519 }
520
521 /* Unmount all children datasets under the BE's root dataset */
522 if ((zret = zfs_iter_filesystems(zhp, be_unmount_callback,
523 &ud)) != 0) {
524 be_print_err(gettext("be_unmount: failed to "
525 "unmount BE (%s)\n"), bt.obe_name);
526 ZFS_CLOSE(zhp);
527 return (zret);
528 }
529
530 /* Unmount this BE's root filesystem */
531 if ((ret = be_unmount_root(zhp, &ud)) != BE_SUCCESS) {
532 ZFS_CLOSE(zhp);
533 return (ret);
534 }
535
536 ZFS_CLOSE(zhp);
537
538 return (BE_SUCCESS);
539 }
540
541 /*
542 * Function: be_mount_zone_root
543 * Description: Mounts the zone root dataset for a zone.
544 * Parameters:
545 * zfs - zfs_handle_t pointer to zone root dataset
546 * md - be_mount_data_t pointer to data for zone to be mounted
547 * Returns:
548 * BE_SUCCESS - Success
549 * be_errno_t - Failure
550 * Scope:
551 * Semi-private (library wide use only)
552 */
553 int
554 be_mount_zone_root(zfs_handle_t *zhp, be_mount_data_t *md)
555 {
556 char mountpoint[MAXPATHLEN];
557 int err = 0;
558
559 /* Get mountpoint property of dataset */
560 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
561 sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
562 be_print_err(gettext("be_mount_zone_root: failed to "
563 "get mountpoint property for %s: %s\n"), zfs_get_name(zhp),
564 libzfs_error_description(g_zfs));
565 return (zfs_err_to_be_err(g_zfs));
566 }
567
568 /*
569 * Make sure zone's root dataset is set to 'legacy'. This is
570 * currently a requirement in this implementation of zones
571 * support.
572 */
573 if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0) {
574 be_print_err(gettext("be_mount_zone_root: "
575 "zone root dataset mountpoint is not 'legacy'\n"));
576 return (BE_ERR_ZONE_ROOT_NOT_LEGACY);
577 }
578
579 /*
580 * Legacy mount the zone root dataset.
581 *
582 * As a workaround for 6176743, we mount the zone's root with the
583 * MS_OVERLAY option in case an alternate BE is mounted, and we're
584 * mounting the root for the zone from the current BE here. When an
585 * alternate BE is mounted, it ties up the zone's zoneroot directory
586 * for the current BE since the zone's zonepath is loopback mounted
587 * from the current BE.
588 *
589 * TODO: The MS_OVERLAY option needs to be removed when 6176743
590 * is fixed.
591 */
592 if (mount(zfs_get_name(zhp), md->altroot, MS_OVERLAY, MNTTYPE_ZFS,
593 NULL, 0, NULL, 0) != 0) {
594 err = errno;
595 be_print_err(gettext("be_mount_zone_root: failed to "
596 "legacy mount zone root dataset (%s) at %s\n"),
597 zfs_get_name(zhp), md->altroot);
598 return (errno_to_be_err(err));
|
6 * You may not use this file except in compliance with the License.
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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25 /*
26 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 */
28
29 /*
30 * System includes
31 */
32 #include <assert.h>
33 #include <errno.h>
34 #include <libgen.h>
35 #include <libintl.h>
36 #include <libnvpair.h>
37 #include <libzfs.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/mntent.h>
42 #include <sys/mnttab.h>
43 #include <sys/mount.h>
44 #include <sys/stat.h>
45 #include <sys/types.h>
46 #include <sys/vfstab.h>
47 #include <sys/zone.h>
48 #include <sys/mkdev.h>
49 #include <unistd.h>
50
51 #include <libbe.h>
52 #include <libbe_priv.h>
53
54 #define BE_TMP_MNTPNT "/tmp/.be.XXXXXX"
310 return (ret);
311 }
312
313 /*
314 * If altroot not provided, create a temporary alternate root
315 * to mount on
316 */
317 if (*altroot == NULL) {
318 if ((ret = be_make_tmp_mountpoint(&tmp_altroot))
319 != BE_SUCCESS) {
320 be_print_err(gettext("be_mount: failed to "
321 "make temporary mountpoint\n"));
322 ZFS_CLOSE(zhp);
323 return (ret);
324 }
325 gen_tmp_altroot = B_TRUE;
326 } else {
327 tmp_altroot = *altroot;
328 }
329
330 md.altroot = tmp_altroot;
331 md.shared_fs = flags & BE_MOUNT_FLAG_SHARED_FS;
332 md.shared_rw = flags & BE_MOUNT_FLAG_SHARED_RW;
333
334 /* Mount the BE's root file system */
335 if (getzoneid() == GLOBAL_ZONEID) {
336 if ((ret = be_mount_root(zhp, tmp_altroot)) != BE_SUCCESS) {
337 be_print_err(gettext("be_mount: failed to "
338 "mount BE root file system\n"));
339 if (gen_tmp_altroot)
340 free(tmp_altroot);
341 ZFS_CLOSE(zhp);
342 return (ret);
343 }
344 } else {
345 /* Legacy mount the zone root dataset */
346 if ((ret = be_mount_zone_root(zhp, &md)) != BE_SUCCESS) {
347 be_print_err(gettext("be_mount: failed to "
348 "mount BE zone root file system\n"));
349 free(md.altroot);
350 ZFS_CLOSE(zhp);
351 return (ret);
352 }
353 }
354
355 /* Iterate through BE's children filesystems */
356 if ((err = zfs_iter_filesystems(zhp, be_mount_callback,
357 tmp_altroot)) != 0) {
358 be_print_err(gettext("be_mount: failed to "
359 "mount BE (%s) on %s\n"), bt.obe_name, tmp_altroot);
360 if (gen_tmp_altroot)
361 free(tmp_altroot);
362 ZFS_CLOSE(zhp);
363 return (err);
364 }
365
366 /*
367 * Mount shared file systems if mount flag says so.
368 */
369 if (md.shared_fs) {
370 /*
371 * Mount all ZFS file systems not under the BE's root dataset
372 */
373 (void) zpool_iter(g_zfs, zpool_shared_fs_callback, &md);
374
375 /* TODO: Mount all non-ZFS file systems - Not supported yet */
376 }
377
378 /*
379 * If we're in the global zone and the global zone has a valid uuid,
380 * mount all supported non-global zones.
381 */
382 if (getzoneid() == GLOBAL_ZONEID &&
383 !(flags & BE_MOUNT_FLAG_NO_ZONES) &&
384 be_get_uuid(bt.obe_root_ds, &uu) == BE_SUCCESS) {
385 if ((ret = be_mount_zones(zhp, &md)) != BE_SUCCESS) {
523 /* TODO: Unmount all non-ZFS file systems - Not supported yet */
524
525 /* Unmount all ZFS file systems not under the BE root dataset */
526 if ((ret = unmount_shared_fs(&ud)) != BE_SUCCESS) {
527 be_print_err(gettext("be_unmount: failed to "
528 "unmount shared file systems\n"));
529 ZFS_CLOSE(zhp);
530 return (ret);
531 }
532
533 /* Unmount all children datasets under the BE's root dataset */
534 if ((zret = zfs_iter_filesystems(zhp, be_unmount_callback,
535 &ud)) != 0) {
536 be_print_err(gettext("be_unmount: failed to "
537 "unmount BE (%s)\n"), bt.obe_name);
538 ZFS_CLOSE(zhp);
539 return (zret);
540 }
541
542 /* Unmount this BE's root filesystem */
543 if (getzoneid() == GLOBAL_ZONEID) {
544 if ((ret = be_unmount_root(zhp, &ud)) != BE_SUCCESS) {
545 ZFS_CLOSE(zhp);
546 return (ret);
547 }
548 } else {
549 if ((ret = be_unmount_zone_root(zhp, &ud)) != BE_SUCCESS) {
550 ZFS_CLOSE(zhp);
551 return (ret);
552 }
553 }
554
555 ZFS_CLOSE(zhp);
556
557 return (BE_SUCCESS);
558 }
559
560 /*
561 * Function: be_mount_zone_root
562 * Description: Mounts the zone root dataset for a zone.
563 * Parameters:
564 * zfs - zfs_handle_t pointer to zone root dataset
565 * md - be_mount_data_t pointer to data for zone to be mounted
566 * Returns:
567 * BE_SUCCESS - Success
568 * be_errno_t - Failure
569 * Scope:
570 * Semi-private (library wide use only)
571 */
572 int
573 be_mount_zone_root(zfs_handle_t *zhp, be_mount_data_t *md)
574 {
575 struct stat buf;
576 char mountpoint[MAXPATHLEN];
577 int err = 0;
578
579 /* Get mountpoint property of dataset */
580 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
581 sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
582 be_print_err(gettext("be_mount_zone_root: failed to "
583 "get mountpoint property for %s: %s\n"), zfs_get_name(zhp),
584 libzfs_error_description(g_zfs));
585 return (zfs_err_to_be_err(g_zfs));
586 }
587
588 /*
589 * Make sure zone's root dataset is set to 'legacy'. This is
590 * currently a requirement in this implementation of zones
591 * support.
592 */
593 if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0) {
594 be_print_err(gettext("be_mount_zone_root: "
595 "zone root dataset mountpoint is not 'legacy'\n"));
596 return (BE_ERR_ZONE_ROOT_NOT_LEGACY);
597 }
598
599 /* Create the mountpoint if it doesn't exist */
600 if (lstat(md->altroot, &buf) != 0) {
601 if (mkdirp(md->altroot, 0755) != 0) {
602 err = errno;
603 be_print_err(gettext("be_mount_zone_root: failed "
604 "to create mountpoint %s\n"), md->altroot);
605 return (errno_to_be_err(err));
606 }
607 }
608
609 /*
610 * Legacy mount the zone root dataset.
611 *
612 * As a workaround for 6176743, we mount the zone's root with the
613 * MS_OVERLAY option in case an alternate BE is mounted, and we're
614 * mounting the root for the zone from the current BE here. When an
615 * alternate BE is mounted, it ties up the zone's zoneroot directory
616 * for the current BE since the zone's zonepath is loopback mounted
617 * from the current BE.
618 *
619 * TODO: The MS_OVERLAY option needs to be removed when 6176743
620 * is fixed.
621 */
622 if (mount(zfs_get_name(zhp), md->altroot, MS_OVERLAY, MNTTYPE_ZFS,
623 NULL, 0, NULL, 0) != 0) {
624 err = errno;
625 be_print_err(gettext("be_mount_zone_root: failed to "
626 "legacy mount zone root dataset (%s) at %s\n"),
627 zfs_get_name(zhp), md->altroot);
628 return (errno_to_be_err(err));
|