f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * CDDL HEADER START
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The contents of this file are subject to the terms of the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Common Development and Distribution License (the "License").
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * You may not use this file except in compliance with the License.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * or http://www.opensolaris.org/os/licensing.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * See the License for the specific language governing permissions
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and limitations under the License.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * When distributing Covered Code, include this CDDL HEADER in each
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If applicable, add the following below this CDDL HEADER, with the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * fields enclosed by brackets "[]" replaced with your own identifying
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * information: Portions Copyright [yyyy] [name of copyright owner]
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * CDDL HEADER END
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
85aac7c12e738f35fbcd61cdc0503288fb66b382Igor Kozhukhov * Copyright 2015 EveryCity Ltd.
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens * Copyright (c) 2015 by Delphix. All rights reserved.
89d19e002086cf26431426fe713cfef456067882Alexander Eremin */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * System includes
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <assert.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <errno.h>
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin#include <libgen.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libintl.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libnvpair.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libzfs.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <stdio.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <stdlib.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <string.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/mntent.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/mnttab.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/mount.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/stat.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/types.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/vfstab.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/zone.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/mkdev.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <unistd.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libbe.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libbe_priv.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#define BE_TMP_MNTPNT "/tmp/.be.XXXXXX"
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassetypedef struct dir_data {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *dir;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *ds;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse} dir_data_t;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* Private function prototypes */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_mount_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_unmount_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_get_legacy_fs_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int fix_mountpoint(zfs_handle_t *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int fix_mountpoint_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int get_mountpoint_from_vfstab(char *, const char *, char *, size_t,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse boolean_t);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int loopback_mount_shared_fs(zfs_handle_t *, be_mount_data_t *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int loopback_mount_zonepath(const char *, be_mount_data_t *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int iter_shared_fs_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int zpool_shared_fs_callback(zpool_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int unmount_shared_fs(be_unmount_data_t *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int add_to_fs_list(be_fs_list_data_t *, const char *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_mount_root(zfs_handle_t *, char *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_unmount_root(zfs_handle_t *, be_unmount_data_t *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_mount_zones(zfs_handle_t *, be_mount_data_t *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_unmount_zones(be_unmount_data_t *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_mount_one_zone(zfs_handle_t *, be_mount_data_t *, char *, char *,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_unmount_one_zone(be_unmount_data_t *, char *, char *, char *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_get_ds_from_dir_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* Public Functions */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_mount
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Mounts a BE and its subordinate datasets at a given mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_attrs - pointer to nvlist_t of attributes being passed in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The following attributes are used by this function:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_ORIG_BE_NAME *required
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_MOUNTPOINT *required
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_MOUNT_FLAGS *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Public
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_mount(nvlist_t *be_attrs)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *be_name = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *mountpoint = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uint16_t flags = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Initialize libzfs handle */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_zfs_init())
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INIT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get original BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, &be_name)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_ORIG_BE_NAME attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Validate original BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_valid_be_name(be_name)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: invalid BE name %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get mountpoint */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_string(be_attrs, BE_ATTR_MOUNTPOINT, &mountpoint)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_MOUNTPOINT attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get flags */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_MOUNT_FLAGS, DATA_TYPE_UINT16, &flags, NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_MOUNT_FLAGS attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = _be_mount(be_name, &mountpoint, flags);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_zfs_fini();
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_unmount
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Unmounts a BE and its subordinate datasets.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_attrs - pointer to nvlist_t of attributes being passed in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The following attributes are used by this function:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_ORIG_BE_NAME *required
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_UNMOUNT_FLAGS *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Public
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_unmount(nvlist_t *be_attrs)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *be_name = NULL;
89d19e002086cf26431426fe713cfef456067882Alexander Eremin char *be_name_mnt = NULL;
89d19e002086cf26431426fe713cfef456067882Alexander Eremin char *ds = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uint16_t flags = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Initialize libzfs handle */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_zfs_init())
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INIT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get original BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, &be_name)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_ORIG_BE_NAME attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
89d19e002086cf26431426fe713cfef456067882Alexander Eremin /* Check if we have mountpoint argument instead of BE name */
89d19e002086cf26431426fe713cfef456067882Alexander Eremin if (be_name[0] == '/') {
89d19e002086cf26431426fe713cfef456067882Alexander Eremin if ((ds = be_get_ds_from_dir(be_name)) != NULL) {
89d19e002086cf26431426fe713cfef456067882Alexander Eremin if ((be_name_mnt = strrchr(ds, '/')) != NULL) {
89d19e002086cf26431426fe713cfef456067882Alexander Eremin be_name = be_name_mnt + 1;
89d19e002086cf26431426fe713cfef456067882Alexander Eremin }
89d19e002086cf26431426fe713cfef456067882Alexander Eremin } else {
89d19e002086cf26431426fe713cfef456067882Alexander Eremin be_print_err(gettext("be_unmount: no datasets mounted "
89d19e002086cf26431426fe713cfef456067882Alexander Eremin "at '%s'\n"), be_name);
89d19e002086cf26431426fe713cfef456067882Alexander Eremin return (BE_ERR_INVAL);
89d19e002086cf26431426fe713cfef456067882Alexander Eremin }
89d19e002086cf26431426fe713cfef456067882Alexander Eremin }
89d19e002086cf26431426fe713cfef456067882Alexander Eremin
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Validate original BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_valid_be_name(be_name)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: invalid BE name %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get unmount flags */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_UNMOUNT_FLAGS, DATA_TYPE_UINT16, &flags, NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: failed to loookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_UNMOUNT_FLAGS attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = _be_unmount(be_name, flags);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_zfs_fini();
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* Semi-Private Functions */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: _be_mount
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Mounts a BE. If the altroot is not provided, this function
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * will generate a temporary mountpoint to mount the BE at. It
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * will return this temporary mountpoint to the caller via the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * altroot reference pointer passed in. This returned value is
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * allocated on heap storage and is the repsonsibility of the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * caller to free.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_name - pointer to name of BE to mount.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * altroot - reference pointer to altroot of where to mount BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * flags - flag indicating special handling for mounting the BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse_be_mount(char *be_name, char **altroot, int flags)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_transaction_data_t bt = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_mount_data_t md = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char obe_root_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *mp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *tmp_altroot = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS, err = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uuid_t uu = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse boolean_t gen_tmp_altroot = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (be_name == NULL || altroot == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set be_name as obe_name in bt structure */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_name = be_name;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Find which zpool obe_name lives in */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((err = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "find zpool for BE (%s)\n"), bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_BE_NOENT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (err < 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: zpool_iter failed: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate string for obe_name's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (obe_root_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_root_ds = obe_root_ds;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_FILESYSTEM)) ==
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), bt.obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Make sure BE's root dataset isn't already mounted somewhere */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_is_mounted(zhp, &mp)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: %s is already mounted "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "at %s\n"), bt.obe_name, mp != NULL ? mp : "");
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(mp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_MOUNTED);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Fix this BE's mountpoint if its root dataset isn't set to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * either 'legacy' or '/'.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = fix_mountpoint(zhp)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: mountpoint check "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed for %s\n"), bt.obe_root_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If altroot not provided, create a temporary alternate root
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to mount on
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (*altroot == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_make_tmp_mountpoint(&tmp_altroot))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "make temporary mountpoint\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse gen_tmp_altroot = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse tmp_altroot = *altroot;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin md.altroot = tmp_altroot;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin md.shared_fs = flags & BE_MOUNT_FLAG_SHARED_FS;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin md.shared_rw = flags & BE_MOUNT_FLAG_SHARED_RW;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Mount the BE's root file system */
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (getzoneid() == GLOBAL_ZONEID) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if ((ret = be_mount_root(zhp, tmp_altroot)) != BE_SUCCESS) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_mount: failed to "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "mount BE root file system\n"));
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (gen_tmp_altroot)
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin free(tmp_altroot);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin ZFS_CLOSE(zhp);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin return (ret);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin } else {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin /* Legacy mount the zone root dataset */
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if ((ret = be_mount_zone_root(zhp, &md)) != BE_SUCCESS) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_mount: failed to "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "mount BE zone root file system\n"));
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin free(md.altroot);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin ZFS_CLOSE(zhp);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin return (ret);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate through BE's children filesystems */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((err = zfs_iter_filesystems(zhp, be_mount_callback,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse tmp_altroot)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mount BE (%s) on %s\n"), bt.obe_name, tmp_altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (gen_tmp_altroot)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(tmp_altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (err);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Mount shared file systems if mount flag says so.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (md.shared_fs) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Mount all ZFS file systems not under the BE's root dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) zpool_iter(g_zfs, zpool_shared_fs_callback, &md);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* TODO: Mount all non-ZFS file systems - Not supported yet */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If we're in the global zone and the global zone has a valid uuid,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mount all supported non-global zones.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (getzoneid() == GLOBAL_ZONEID &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse !(flags & BE_MOUNT_FLAG_NO_ZONES) &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_get_uuid(bt.obe_root_ds, &uu) == BE_SUCCESS) {
40ccc6ad48401a6fe660d7d49d6f60e9320403c9Alexander Eremin if (be_mount_zones(zhp, &md) != BE_SUCCESS) {
40ccc6ad48401a6fe660d7d49d6f60e9320403c9Alexander Eremin ret = BE_ERR_NO_MOUNTED_ZONE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If a NULL altroot was passed in, pass the generated altroot
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * back to the caller in altroot.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
40ccc6ad48401a6fe660d7d49d6f60e9320403c9Alexander Eremin if (gen_tmp_altroot) {
40ccc6ad48401a6fe660d7d49d6f60e9320403c9Alexander Eremin if (ret == BE_SUCCESS || ret == BE_ERR_NO_MOUNTED_ZONE)
40ccc6ad48401a6fe660d7d49d6f60e9320403c9Alexander Eremin *altroot = tmp_altroot;
40ccc6ad48401a6fe660d7d49d6f60e9320403c9Alexander Eremin else
40ccc6ad48401a6fe660d7d49d6f60e9320403c9Alexander Eremin free(tmp_altroot);
40ccc6ad48401a6fe660d7d49d6f60e9320403c9Alexander Eremin }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
40ccc6ad48401a6fe660d7d49d6f60e9320403c9Alexander Eremin return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: _be_unmount
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Unmount a BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_name - pointer to name of BE to unmount.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * flags - flags for unmounting the BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse_be_unmount(char *be_name, int flags)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_transaction_data_t bt = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_unmount_data_t ud = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uuid_t uu = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char obe_root_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *mp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int zret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (be_name == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set be_name as obe_name in bt structure */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_name = be_name;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Find which zpool obe_name lives in */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "find zpool for BE (%s)\n"), bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_BE_NOENT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (zret < 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "zpool_iter failed: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate string for obe_name's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (obe_root_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_root_ds = obe_root_ds;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_FILESYSTEM)) ==
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), bt.obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Make sure BE's root dataset is mounted somewhere */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!zfs_is_mounted(zhp, &mp)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "(%s) not mounted\n"), bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE is not mounted, fix this BE's mountpoint if its root
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset isn't set to either 'legacy' or '/'.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = fix_mountpoint(zhp)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: mountpoint check "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed for %s\n"), bt.obe_root_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
89d19e002086cf26431426fe713cfef456067882Alexander Eremin return (BE_ERR_NOTMOUNTED);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If we didn't get a mountpoint from the zfs_is_mounted call,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * try and get it from its property.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (mp == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get mountpoint of (%s)\n"), bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_ZFS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(mountpoint, mp, sizeof (mountpoint));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(mp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If BE mounted as current root, fail */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(mountpoint, "/") == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "cannot unmount currently running BE\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_UMOUNT_CURR_BE);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ud.altroot = mountpoint;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ud.force = flags & BE_UNMOUNT_FLAG_FORCE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount all supported non-global zones if we're in the global zone */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (getzoneid() == GLOBAL_ZONEID &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_get_uuid(bt.obe_root_ds, &uu) == BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_unmount_zones(&ud)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* TODO: Unmount all non-ZFS file systems - Not supported yet */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount all ZFS file systems not under the BE root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = unmount_shared_fs(&ud)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount shared file systems\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount all children datasets under the BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zret = zfs_iter_filesystems(zhp, be_unmount_callback,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse &ud)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount BE (%s)\n"), bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount this BE's root filesystem */
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (getzoneid() == GLOBAL_ZONEID) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if ((ret = be_unmount_root(zhp, &ud)) != BE_SUCCESS) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin ZFS_CLOSE(zhp);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin return (ret);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin } else {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if ((ret = be_unmount_zone_root(zhp, &ud)) != BE_SUCCESS) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin ZFS_CLOSE(zhp);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin return (ret);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_mount_zone_root
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Mounts the zone root dataset for a zone.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zfs - zfs_handle_t pointer to zone root dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * md - be_mount_data_t pointer to data for zone to be mounted
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_mount_zone_root(zfs_handle_t *zhp, be_mount_data_t *md)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin struct stat buf;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int err = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get mountpoint property of dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_zone_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get mountpoint property for %s: %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Make sure zone's root dataset is set to 'legacy'. This is
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * currently a requirement in this implementation of zones
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * support.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_zone_root: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "zone root dataset mountpoint is not 'legacy'\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_ZONE_ROOT_NOT_LEGACY);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin /* Create the mountpoint if it doesn't exist */
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (lstat(md->altroot, &buf) != 0) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (mkdirp(md->altroot, 0755) != 0) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin err = errno;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_mount_zone_root: failed "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "to create mountpoint %s\n"), md->altroot);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin return (errno_to_be_err(err));
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Legacy mount the zone root dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * As a workaround for 6176743, we mount the zone's root with the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * MS_OVERLAY option in case an alternate BE is mounted, and we're
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mounting the root for the zone from the current BE here. When an
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * alternate BE is mounted, it ties up the zone's zoneroot directory
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * for the current BE since the zone's zonepath is loopback mounted
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * from the current BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * TODO: The MS_OVERLAY option needs to be removed when 6176743
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * is fixed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (mount(zfs_get_name(zhp), md->altroot, MS_OVERLAY, MNTTYPE_ZFS,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL, 0, NULL, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse err = errno;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_zone_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "legacy mount zone root dataset (%s) at %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp), md->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (errno_to_be_err(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_unmount_zone_root
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Unmounts the zone root dataset for a zone.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to zone root dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * ud - be_unmount_data_t pointer to data for zone to be unmounted
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wise use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_unmount_zone_root(zfs_handle_t *zhp, be_unmount_data_t *ud)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount the dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_unmount(zhp, NULL, ud->force ? MS_FORCE : 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_zone_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount zone root dataset %s: %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get the current mountpoint property for the zone root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_zone_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get mountpoint property for zone root dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp), libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If mountpoint not already set to 'legacy', set it to 'legacy' */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_MOUNTPOINT_LEGACY) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_zone_root: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to set mountpoint of zone root dataset "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s to 'legacy': %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_get_legacy_fs
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function iterates through all non-shared file systems
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * of a BE and finds the ones with a legacy mountpoint. For
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * those file systems, it reads the BE's vfstab to get the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint. If found, it adds that file system to the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_fs_list_data_t passed in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * This function can be used to gather legacy mounted file systems
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * for both global BEs and non-global zone BEs. To get data for
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a non-global zone BE, the zoneroot_ds and zoneroot parameters
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * will be specified, otherwise they should be set to NULL.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_name - global BE name from which to get legacy file
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * system list.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_root_ds - root dataset of global BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zoneroot_ds - root dataset of zone.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zoneroot - zoneroot path of zone.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * fld - be_fs_list_data_t pointer.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_get_legacy_fs(char *be_name, char *be_root_ds, char *zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zoneroot, be_fs_list_data_t *fld)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse boolean_t mounted_here = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse boolean_t zone_mounted_here = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS, err = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (be_name == NULL || be_root_ds == NULL || fld == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), be_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If BE is not already mounted, mount it. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!zfs_is_mounted(zhp, &fld->altroot)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = _be_mount(be_name, &fld->altroot,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneroot_ds ? BE_MOUNT_FLAG_NULL :
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to mount BE %s\n"), be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto cleanup;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mounted_here = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (fld->altroot == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get altroot of mounted BE %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_name, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto cleanup;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If a zone root dataset was passed in, we're wanting to get
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * legacy mounted file systems for that zone, not the global
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zoneroot_ds != NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_mount_data_t zone_md = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Close off handle to global BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to zone's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_TYPE_FILESYSTEM)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open zone BE root dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneroot_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto cleanup;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Make sure the zone we're looking for is mounted */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!zfs_is_mounted(zhp, &zone_md.altroot)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zone_altroot[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate alternate root path for zone */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(zone_altroot, sizeof (zone_altroot),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s%s", fld->altroot, zoneroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zone_md.altroot = strdup(zone_altroot)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "memory allocation failed\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_NOMEM;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto cleanup;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_mount_zone_root(zhp, &zone_md))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to mount zone root %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneroot_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(zone_md.altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_md.altroot = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto cleanup;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_mounted_here = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(fld->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fld->altroot = zone_md.altroot;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the root dataset is in the vfstab with a mountpoint of "/",
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * add it to the list
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (get_mountpoint_from_vfstab(fld->altroot, zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mountpoint, sizeof (mountpoint), B_FALSE) == BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(mountpoint, "/") == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (add_to_fs_list(fld, zfs_get_name(zhp))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to add %s to fs list\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_INVAL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto cleanup;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate subordinate file systems looking for legacy mounts */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zhp, be_get_legacy_fs_callback,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fld)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to iterate %s to get legacy mounts\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassecleanup:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If we mounted the zone BE, unmount it */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zone_mounted_here) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_unmount_data_t zone_ud = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_ud.altroot = fld->altroot;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_ud.force = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((err = be_unmount_zone_root(zhp, &zone_ud)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to unmount zone root %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneroot_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (ret == BE_SUCCESS)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = err;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If we mounted this BE, unmount it */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (mounted_here) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((err = _be_unmount(be_name, 0)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to unmount %s\n"), be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (ret == BE_SUCCESS)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = err;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(fld->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fld->altroot = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_free_fs_list
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Function used to free the members of a be_fs_list_data_t
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * structure.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * fld - be_fs_list_data_t pointer to free.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * None
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassevoid
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_free_fs_list(be_fs_list_data_t *fld)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int i;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (fld == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(fld->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (fld->fs_list == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (i = 0; i < fld->fs_num; i++)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(fld->fs_list[i]);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(fld->fs_list);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_get_ds_from_dir(char *dir)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Given a directory path, find the underlying dataset mounted
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * at that directory path if there is one. The returned name
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * is allocated in heap storage, so the caller is responsible
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * for freeing it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dir - char pointer of directory to find.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * NULL - if directory is not mounted from a dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * name of dataset mounted at dir.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassechar *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_get_ds_from_dir(char *dir)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dir_data_t dd = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char resolved_dir[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Make sure length of dir is within the max length */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (dir == NULL || strlen(dir) >= MAXPATHLEN)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (NULL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Resolve dir in case its lofs mounted */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(resolved_dir, dir, sizeof (resolved_dir));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_resolve_lofs(resolved_dir, sizeof (resolved_dir));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd.dir = resolved_dir;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) zfs_iter_root(g_zfs, be_get_ds_from_dir_callback, &dd);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (dd.ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_make_tmp_mountpoint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function generates a random temporary mountpoint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and creates that mountpoint directory. It returns the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint in heap storage, so the caller is responsible
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * for freeing it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * tmp_mp - reference to pointer of where to store generated
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * temporary mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_make_tmp_mountpoint(char **tmp_mp)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int err = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((*tmp_mp = (char *)calloc(1, sizeof (BE_TMP_MNTPNT) + 1)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_make_tmp_mountpoint: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "malloc failed\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_NOMEM);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(*tmp_mp, BE_TMP_MNTPNT, sizeof (BE_TMP_MNTPNT) + 1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (mkdtemp(*tmp_mp) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse err = errno;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_make_tmp_mountpoint: mkdtemp() failed "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "for %s: %s\n"), *tmp_mp, strerror(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(*tmp_mp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *tmp_mp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (errno_to_be_err(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_mount_pool
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function determines if the pool's datase is mounted
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and if not it is used to mount the pool's dataset. The
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * function returns the current mountpoint if we are able
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to mount the dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - handle to the pool's dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * tmp_mntpnt - The temporary mountpoint that the pool's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset is mounted on. This is set only
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * if the attempt to mount the dataset at it's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * set mountpoint fails, and we've used a
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * temporary mount point for this dataset. It
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * is expected that the caller will free this
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * memory.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * orig_mntpnt - The original mountpoint for the pool. If a
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * temporary mount point was needed this will
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be used to reset the mountpoint property to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * it's original mountpoint. It is expected that
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the caller will free this memory.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * pool_mounted - This flag indicates that the pool was mounted
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * in this function.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_mount_pool(
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char **tmp_mntpnt,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char **orig_mntpnt,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse boolean_t *pool_mounted)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *tmp_mntpnt = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *orig_mntpnt = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *pool_mounted = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!zfs_is_mounted(zhp, NULL)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_mount(zhp, NULL, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_pool: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get mountpoint of (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((*orig_mntpnt = strdup(mountpoint)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_pool: memory "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "allocation failed\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_NOMEM);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * attempt to mount on a temp mountpoint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_make_tmp_mountpoint(tmp_mntpnt))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_pool: failed "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "to make temporary mountpoint\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(*orig_mntpnt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *orig_mntpnt = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *tmp_mntpnt) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_pool: failed "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "to set mountpoint of pool dataset %s to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s: %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *orig_mntpnt,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(*tmp_mntpnt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(*orig_mntpnt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *orig_mntpnt = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *tmp_mntpnt = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_mount(zhp, NULL, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_pool: failed "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "to mount dataset %s at %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp), *tmp_mntpnt,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mountpoint) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_pool: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to set mountpoint of pool "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "dataset %s to %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp), *tmp_mntpnt,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(*tmp_mntpnt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(*orig_mntpnt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *orig_mntpnt = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *tmp_mntpnt = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *pool_mounted = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_unmount_pool
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function is used to unmount the pool's dataset if we
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mounted it previously using be_mount_pool().
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - handle to the pool's dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * tmp_mntpnt - If a temprary mount point was used this will
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be set. Since this was created in be_mount_pool
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * we will need to clean it up here.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * orig_mntpnt - The original mountpoint for the pool. This is
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * used to set the dataset mountpoint property
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * back to it's original value in the case where a
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * temporary mountpoint was used.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_unmount_pool(
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *tmp_mntpnt,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *orig_mntpnt)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_unmount(zhp, NULL, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_pool: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount pool (%s): %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (orig_mntpnt != NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (tmp_mntpnt != NULL &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse strcmp(orig_mntpnt, tmp_mntpnt) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) rmdir(tmp_mntpnt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse orig_mntpnt) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_pool: failed "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "to set the mountpoint for dataset (%s) to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s: %s\n"), zfs_get_name(zhp), orig_mntpnt,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* Private Functions */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_mount_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Callback function used to iterate through all of a BE's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * subordinate file systems and to mount them accordingly.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to current file system being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - pointer to the altroot of where to mount BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_mount_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zprop_source_t sourcetype;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse const char *fs_name = zfs_get_name(zhp);
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char source[ZFS_MAX_DATASET_NAME_LEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *altroot = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zhp_mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get dataset's mountpoint and source values */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, zhp_mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (zhp_mountpoint), &sourcetype, source, sizeof (source),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_callback: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get mountpoint and sourcetype for %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fs_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_ZFS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Set this filesystem's 'canmount' property to 'noauto' just incase
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * it's been set 'on'. We do this so that when we change its
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint zfs won't immediately try to mount it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto")) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_callback: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "set canmount to 'noauto' (%s)\n"), fs_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_ZFS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the mountpoint is none, there's nothing to do, goto next.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the mountpoint is legacy, legacy mount it with mount(2).
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the mountpoint is inherited, its mountpoint should
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * already be set. If it's not, then explicitly fix-up
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the mountpoint now by appending its explicitly set
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint value to the BE mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(zhp_mountpoint, ZFS_MOUNTPOINT_NONE) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto next;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (strcmp(zhp_mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the mountpoint is set to 'legacy', we need to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dig into this BE's vfstab to figure out where to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mount it, and just mount it via mount(2).
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (get_mountpoint_from_vfstab(altroot, fs_name,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mountpoint, sizeof (mountpoint), B_TRUE) == BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Legacy mount the file system */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (mount(fs_name, mountpoint, MS_DATA,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse MNTTYPE_ZFS, NULL, 0, NULL, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse gettext("be_mount_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to mount %s on %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fs_name, mountpoint);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse gettext("be_mount_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "no entry for %s in vfstab, "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "skipping ...\n"), fs_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto next;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (sourcetype & ZPROP_SRC_INHERITED) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the mountpoint is inherited, its parent should have
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * already been processed so its current mountpoint value
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * is what its mountpoint ought to be.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(mountpoint, zhp_mountpoint, sizeof (mountpoint));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (sourcetype & ZPROP_SRC_LOCAL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Else process dataset with explicitly set mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(mountpoint, sizeof (mountpoint),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s%s", altroot, zhp_mountpoint);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set the new mountpoint for the dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mountpoint)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to set mountpoint for %s to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s\n"), fs_name, mountpoint);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_ZFS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mountpoint sourcetype of %s is %d, skipping ...\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fs_name, sourcetype);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto next;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Mount this filesystem */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_mount(zhp, NULL, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_callback: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mount dataset %s at %s: %s\n"), fs_name, mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Set this filesystem's 'mountpoint' property back to what
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * it was
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (sourcetype & ZPROP_SRC_LOCAL &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse strcmp(zhp_mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) zfs_prop_set(zhp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_MOUNT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassenext:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate through this dataset's children and mount them */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zhp, be_mount_callback,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse altroot)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_unmount_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Callback function used to iterate through all of a BE's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * subordinate file systems and to unmount them.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to current file system being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - pointer to the mountpoint of where BE is mounted.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_unmount_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_unmount_data_t *ud = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zprop_source_t sourcetype;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse const char *fs_name = zfs_get_name(zhp);
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char source[ZFS_MAX_DATASET_NAME_LEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zhp_mountpoint;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate down this dataset's children first */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_iter_filesystems(zhp, be_unmount_callback, ud)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_UMOUNT;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Is dataset even mounted ? */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!zfs_is_mounted(zhp, NULL))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount this file system */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_unmount(zhp, NULL, ud->force ? MS_FORCE : 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to unmount %s: %s\n"), fs_name,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get dataset's current mountpoint and source value */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (mountpoint), &sourcetype, source, sizeof (source),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get mountpoint and sourcetype for %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fs_name, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (sourcetype & ZPROP_SRC_INHERITED) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the mountpoint is inherited we don't need to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * do anything. When its parent gets processed
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * its mountpoint will be set accordingly.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (sourcetype & ZPROP_SRC_LOCAL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the mountpoint is set to 'legacy', its already
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * been unmounted (from above call to zfs_unmount), and
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * we don't need to do anything else with it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Else process dataset with explicitly set mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get this dataset's mountpoint relative to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the BE's mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((strncmp(mountpoint, ud->altroot,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse strlen(ud->altroot)) == 0) &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (mountpoint[strlen(ud->altroot)] == '/')) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint = mountpoint +
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse strlen(ud->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set this dataset's mountpoint value */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse gettext("be_unmount_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to set mountpoint for "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s to %s: %s\n"), fs_name,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse gettext("be_unmount_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s not mounted under BE's altroot %s, "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "skipping ...\n"), fs_name, ud->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * fs_name is mounted but not under the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * root for this BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_INVALMOUNTPOINT;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mountpoint sourcetype of %s is %d, skipping ...\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fs_name, sourcetype);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_ZFS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set this filesystem's 'canmount' property to 'noauto' */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto")) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to set canmount to 'noauto' (%s)\n"), fs_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (ret == 0)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_ZFS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_get_legacy_fs_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: The callback function is used to iterate through all
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * non-shared file systems of a BE, finding ones that have
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a legacy mountpoint and an entry in the BE's vfstab.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * It adds these file systems to the callback data.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to current file system being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - be_fs_list_data_t pointer
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_get_legacy_fs_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_fs_list_data_t *fld = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse const char *fs_name = zfs_get_name(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zhp_mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get this dataset's mountpoint property */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, zhp_mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (zhp_mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get mountpoint for %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fs_name, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If mountpoint is legacy, try to get its mountpoint from this BE's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * vfstab. If it exists in the vfstab, add this file system to the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * callback data.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(zhp_mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (get_mountpoint_from_vfstab(fld->altroot, fs_name,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mountpoint, sizeof (mountpoint), B_FALSE) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "no entry for %s in vfstab, "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "skipping ...\n"), fs_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto next;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Record file system into the callback data. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (add_to_fs_list(fld, zfs_get_name(zhp)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_legacy_fs_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to add %s to fs list\n"), mountpoint);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_NOMEM);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassenext:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate through this dataset's children file systems */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zhp, be_get_legacy_fs_callback,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fld)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: add_to_fs_list
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Function used to add a file system to the fs_list array in
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a be_fs_list_data_t structure.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * fld - be_fs_list_data_t pointer
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * fs - file system to add
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 1 - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseadd_to_fs_list(be_fs_list_data_t *fld, const char *fs)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (fld == NULL || fs == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((fld->fs_list = (char **)realloc(fld->fs_list,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (char *)*(fld->fs_num + 1))) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("add_to_fs_list: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "memory allocation failed\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((fld->fs_list[fld->fs_num++] = strdup(fs)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("add_to_fs_list: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "memory allocation failed\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: zpool_shared_fs_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Callback function used to iterate through all existing pools
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to find and mount all shared filesystems. This function
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * processes the pool's "pool data" dataset, then uses
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * iter_shared_fs_callback to iterate through the pool's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * datasets.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zlp - zpool_handle_t pointer to the current pool being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * looked at.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - be_mount_data_t pointer
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassezpool_shared_fs_callback(zpool_handle_t *zlp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_mount_data_t *md = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse const char *zpool = zpool_get_name(zlp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get handle to pool's "pool data" dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, zpool, ZFS_TYPE_FILESYSTEM)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("zpool_shared_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to open pool dataset %s: %s\n"), zpool,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zpool_close(zlp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Process this pool's "pool data" dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) loopback_mount_shared_fs(zhp, md);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Interate through this pool's children */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) zfs_iter_filesystems(zhp, iter_shared_fs_callback, md);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zpool_close(zlp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: iter_shared_fs_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Callback function used to iterate through a pool's datasets
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to find and mount all shared filesystems. It makes sure to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * find the BE container dataset of the pool, if it exists, and
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * does not process and iterate down that path.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Note - This function iterates linearly down the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * hierarchical dataset paths and mounts things as it goes
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * along. It does not make sure that something deeper down
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a dataset path has an interim mountpoint for something
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * processed earlier.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to the current dataset being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - be_mount_data_t pointer
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseiter_shared_fs_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_mount_data_t *md = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse const char *name = zfs_get_name(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char container_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char tmp_name[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *pool;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get the pool's name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(tmp_name, name, sizeof (tmp_name));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse pool = strtok(tmp_name, "/");
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (pool) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get the name of this pool's container dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_container_ds(pool, container_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (container_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If what we're processing is this pool's BE container
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset, skip it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(name, container_ds) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Getting the pool name failed, return error */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("iter_shared_fs_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get pool name from %s\n"), name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_POOL_NOENT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Mount this shared filesystem */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) loopback_mount_shared_fs(zhp, md);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate this dataset's children file systems */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) zfs_iter_filesystems(zhp, iter_shared_fs_callback, md);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: loopback_mount_shared_fs
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function loopback mounts a file system into the altroot
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * area of the BE being mounted. Since these are shared file
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * systems, they are expected to be already mounted for the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * current BE, and this function just loopback mounts them into
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the BE mountpoint. If they are not mounted for the current
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * live system, they are skipped and not mounted into the BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * we're mounting.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to the dataset to loopback mount
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * md - be_mount_data_t pointer
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseloopback_mount_shared_fs(zfs_handle_t *zhp, be_mount_data_t *md)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zhp_mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *mp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char optstr[MAX_MNTOPT_STR];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int mflag = MS_OPTIONSTR;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int err;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Check if file system is currently mounted and not delegated
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to a non-global zone (if we're in the global zone)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_is_mounted(zhp, &mp) && (getzoneid() != GLOBAL_ZONEID ||
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse !zfs_prop_get_int(zhp, ZFS_PROP_ZONED))) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If we didn't get a mountpoint from the zfs_is_mounted call,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * get it from the mountpoint property.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (mp == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint, sizeof (zhp_mountpoint), NULL,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL, 0, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse gettext("loopback_mount_shared_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get mountpoint property\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_ZFS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(zhp_mountpoint, mp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (zhp_mountpoint));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(mp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(mountpoint, sizeof (mountpoint), "%s%s",
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse md->altroot, zhp_mountpoint);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Mount it read-only if read-write was not requested */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!md->shared_rw) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mflag |= MS_RDONLY;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Add the "nosub" option to the mount options string */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(optstr, MNTOPT_NOSUB, sizeof (optstr));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Loopback mount this dataset at the altroot */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (mount(zhp_mountpoint, mountpoint, mflag, MNTTYPE_LOFS,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL, 0, optstr, sizeof (optstr)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse err = errno;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("loopback_mount_shared_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to loopback mount %s at %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint, mountpoint, strerror(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_MOUNT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: loopback_mount_zonepath
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function loopback mounts a zonepath into the altroot
40ccc6ad48401a6fe660d7d49d6f60e9320403c9Alexander Eremin * area of the BE being mounted.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zonepath - pointer to zone path in the current BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * md - be_mount_data_t pointer
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseloopback_mount_zonepath(const char *zonepath, be_mount_data_t *md)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse FILE *fp = (FILE *)NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse struct stat st;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *p;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *p1;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *parent_dir;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse struct extmnttab extmtab;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dev_t dev = NODEV;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *parentmnt;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char alt_parentmnt[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse struct mnttab mntref;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char altzonepath[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char optstr[MAX_MNTOPT_STR];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int mflag = MS_OPTIONSTR;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int err;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse fp = fopen(MNTTAB, "r");
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (fp == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse err = errno;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("loopback_mount_zonepath: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to open /etc/mnttab\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (errno_to_be_err(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * before attempting the loopback mount of zonepath under altroot,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * we need to make sure that all intermediate file systems in the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zone path are also mounted under altroot
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* get the parent directory for zonepath */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse p = strrchr(zonepath, '/');
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (p != NULL && p != zonepath) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((parent_dir = (char *)calloc(sizeof (char),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse p - zonepath + 1)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_NOMEM;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(parent_dir, zonepath, p - zonepath + 1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (stat(parent_dir, &st) < 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = errno_to_be_err(errno);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("loopback_mount_zonepath: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to stat %s"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse parent_dir);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(parent_dir);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(parent_dir);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * After the above stat call, st.st_dev contains ID of the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * device over which parent dir resides.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Now, search mnttab and find mount point of parent dir device.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse resetmnttab(fp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse while (getextmntent(fp, &extmtab, sizeof (extmtab)) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dev = makedev(extmtab.mnt_major, extmtab.mnt_minor);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (st.st_dev == dev && strcmp(extmtab.mnt_fstype,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse MNTTYPE_ZFS) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse p1 = strchr(extmtab.mnt_special, '/');
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (p1 == NULL || strncmp(p1 + 1,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_CONTAINER_DS_NAME, 4) != 0 ||
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (*(p1 + 5) != '/' && *(p1 + 5) != '\0')) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * if parent dir is in a shared file
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * system, check whether it is already
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * loopback mounted under altroot or
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * not. It would have been mounted
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * already under altroot if it is in
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a non-shared filesystem.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse parentmnt = strdup(extmtab.mnt_mountp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(alt_parentmnt,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (alt_parentmnt), "%s%s",
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse md->altroot, parentmnt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mntref.mnt_mountp = alt_parentmnt;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mntref.mnt_special = parentmnt;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mntref.mnt_fstype = MNTTYPE_LOFS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mntref.mnt_mntopts = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mntref.mnt_time = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse resetmnttab(fp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (getmntany(fp, (struct mnttab *)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse &extmtab, &mntref) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = loopback_mount_zonepath(
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse parentmnt, md);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (ret != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(parentmnt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(parentmnt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse break;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!md->shared_rw) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mflag |= MS_RDONLY;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(altzonepath, sizeof (altzonepath), "%s%s",
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse md->altroot, zonepath);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Add the "nosub" option to the mount options string */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(optstr, MNTOPT_NOSUB, sizeof (optstr));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Loopback mount this dataset at the altroot */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (mount(zonepath, altzonepath, mflag, MNTTYPE_LOFS,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL, 0, optstr, sizeof (optstr)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse err = errno;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("loopback_mount_zonepath: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to loopback mount %s at %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath, altzonepath, strerror(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_MOUNT;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone :
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) fclose(fp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: unmount_shared_fs
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function iterates through the mnttab and finds all
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * loopback mount entries that reside within the altroot of
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * where the BE is mounted, and unmounts it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * ud - be_unmount_data_t pointer
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseunmount_shared_fs(be_unmount_data_t *ud)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse FILE *fp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse struct mnttab *table = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse struct mnttab ent;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse struct mnttab *entp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse size_t size = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int read_chunk = 32;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int i;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int altroot_len;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int err = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse errno = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Read in the mnttab into a table */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((fp = fopen(MNTTAB, "r")) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse err = errno;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("unmount_shared_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to open mnttab\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (errno_to_be_err(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse while (getmntent(fp, &ent) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (size % read_chunk == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse table = (struct mnttab *)realloc(table,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (size + read_chunk) * sizeof (ent));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse entp = &table[size++];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Copy over the current mnttab entry into our table,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * copying only the fields that we care about.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) memset(entp, 0, sizeof (*entp));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((entp->mnt_mountp = strdup(ent.mnt_mountp)) == NULL ||
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (entp->mnt_fstype = strdup(ent.mnt_fstype)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("unmount_shared_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "memory allocation failed\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_NOMEM);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) fclose(fp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Process the mnttab entries in reverse order, looking for
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * loopback mount entries mounted under our altroot.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse altroot_len = strlen(ud->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (i = size; i > 0; i--) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse entp = &table[i - 1];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If not of type lofs, skip */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(entp->mnt_fstype, MNTTYPE_LOFS) != 0)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If inside the altroot, unmount it */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strncmp(entp->mnt_mountp, ud->altroot, altroot_len) == 0 &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse entp->mnt_mountp[altroot_len] == '/') {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (umount(entp->mnt_mountp) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse err = errno;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (err == EBUSY) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) sleep(1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse err = errno = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (umount(entp->mnt_mountp) != 0)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse err = errno;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (err != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext(
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount_shared_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to unmount shared file "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "system %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse entp->mnt_mountp, strerror(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (errno_to_be_err(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: get_mountpoint_from_vfstab
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function digs into the vfstab in the given altroot,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and searches for an entry for the fs passed in. If found,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * it returns the mountpoint of that fs in the mountpoint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * buffer passed in. If the get_alt_mountpoint flag is set,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * it returns the mountpoint with the altroot prepended.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * altroot - pointer to the alternate root location
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * fs - pointer to the file system name to look for in the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * vfstab in altroot
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint - pointer to buffer of where the mountpoint of
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * fs will be returned.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * size_mp - size of mountpoint argument
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * get_alt_mountpoint - flag to indicate whether or not the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint should be populated with the altroot
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * prepended.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 1 - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseget_mountpoint_from_vfstab(char *altroot, const char *fs, char *mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse size_t size_mp, boolean_t get_alt_mountpoint)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse struct vfstab vp;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse FILE *fp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char alt_vfstab[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate path to alternate root vfstab */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(alt_vfstab, sizeof (alt_vfstab), "%s/etc/vfstab",
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Open alternate root vfstab */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((fp = fopen(alt_vfstab, "r")) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("get_mountpoint_from_vfstab: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to open vfstab (%s)\n"), alt_vfstab);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (getvfsspec(fp, &vp, (char *)fs) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Found entry for fs, grab its mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the flag to prepend the altroot into the mountpoint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * is set, prepend it. Otherwise, just return the mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (get_alt_mountpoint) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(mountpoint, size_mp, "%s%s", altroot,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse vp.vfs_mountp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(mountpoint, vp.vfs_mountp, size_mp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) fclose(fp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) fclose(fp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: fix_mountpoint_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This callback function is used to iterate through a BE's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * children filesystems to check if its mountpoint is currently
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * set to be mounted at some specified altroot. If so, fix it by
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * removing altroot from the beginning of its mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Note - There's no way to tell if a child filesystem's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint isn't broken, and just happens to begin with
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the altroot we're looking for. In this case, this function
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * will errantly remove the altroot portion from the beginning
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * of this filesystem's mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to filesystem being processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - altroot of where BE is to be mounted.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassefix_mountpoint_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zprop_source_t sourcetype;
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char source[ZFS_MAX_DATASET_NAME_LEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zhp_mountpoint = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *altroot = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get dataset's mountpoint and source values */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (mountpoint), &sourcetype, source, sizeof (source),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("fix_mountpoint_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get mountpoint and sourcetype for %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_ZFS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the mountpoint is not inherited and the mountpoint is not
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 'legacy', this file system potentially needs its mountpoint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * fixed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!(sourcetype & ZPROP_SRC_INHERITED) &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Check if this file system's current mountpoint is
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * under the altroot we're fixing it against.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strncmp(mountpoint, altroot, strlen(altroot)) == 0 &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mountpoint[strlen(altroot)] == '/') {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get this dataset's mountpoint relative to the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * altroot.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint = mountpoint + strlen(altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Fix this dataset's mountpoint value */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("fix_mountpoint_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to set mountpoint for %s to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s: %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate through this dataset's children and fix them */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zhp, fix_mountpoint_callback,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse altroot)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_mount_root
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function mounts the root dataset of a BE at the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * specified altroot.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to root dataset of a BE that is
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to be mounted at altroot.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * altroot - location of where to mount the BE root.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_mount_root(zfs_handle_t *zhp, char *altroot)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get mountpoint property of dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get mountpoint property for %s: %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Set the canmount property for the BE's root dataset to 'noauto' just
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * in case it's been set to 'on'. We do this so that when we change its
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint, zfs won't immediately try to mount it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto")
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "set canmount property to 'noauto' (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp), libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set mountpoint for BE's root filesystem */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), altroot)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "set mountpoint of %s to %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp), altroot,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Mount the BE's root filesystem */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_mount(zhp, NULL, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mount dataset %s at %s: %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse altroot, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Set this BE's root filesystem 'mountpoint' property
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * back to what it was before.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mountpoint);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_unmount_root
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function unmounts the root dataset of a BE, but before
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * unmounting, it looks at the BE's vfstab to determine
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * if the root dataset mountpoint should be left as 'legacy'
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * or '/'. If the vfstab contains an entry for this root
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset with a mountpoint of '/', it sets the mountpoint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * property to 'legacy'.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer of the BE root dataset that
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * is currently mounted.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * ud - be_unmount_data_t pointer providing unmount data
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * for the given BE root dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_unmount_root(zfs_handle_t *zhp, be_unmount_data_t *ud)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse boolean_t is_legacy = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* See if this is a legacy mounted root */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (get_mountpoint_from_vfstab(ud->altroot, zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mountpoint, sizeof (mountpoint), B_FALSE) == BE_SUCCESS &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse strcmp(mountpoint, "/") == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse is_legacy = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount the dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_unmount(zhp, NULL, ud->force ? MS_FORCE : 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount BE root dataset %s: %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set canmount property for this BE's root filesystem to noauto */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto")
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "set canmount property for %s to 'noauto': %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp), libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Set mountpoint for BE's root dataset back to '/', or 'legacy'
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * if its a legacy mounted root.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse is_legacy ? ZFS_MOUNTPOINT_LEGACY : "/") != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_root: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "set mountpoint of %s to %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse is_legacy ? ZFS_MOUNTPOINT_LEGACY : "/");
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: fix_mountpoint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function checks the mountpoint of an unmounted BE to make
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * sure that it is set to either 'legacy' or '/'. If it's not,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * then we're in a situation where an unmounted BE has some random
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint set for it. (This could happen if the system was
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * rebooted while an inactive BE was mounted). This function
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * attempts to fix its mountpoints.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to root dataset of the BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * whose mountpoint needs to be checked.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassefix_mountpoint(zfs_handle_t *zhp)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_unmount_data_t ud = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *altroot = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Record what this BE's root dataset mountpoint property is currently
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * set to.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("fix_mountpoint: failed to get "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mountpoint property of (%s): %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_ZFS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the root dataset mountpoint is set to 'legacy' or '/', we're okay.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0 ||
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse strcmp(mountpoint, "/") == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Iterate through this BE's children datasets and fix
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * them if they need fixing.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_iter_filesystems(zhp, fix_mountpoint_callback, mountpoint)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_ZFS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The process of mounting and unmounting the root file system
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * will fix its mountpoint to correctly be either 'legacy' or '/'
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * since be_unmount_root will do the right thing by looking at
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * its vfstab.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate temporary altroot to mount the root file system */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_make_tmp_mountpoint(&altroot)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("fix_mountpoint: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "make temporary mountpoint\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Mount and unmount the root. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_mount_root(zhp, altroot)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("fix_mountpoint: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mount BE root file system\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto cleanup;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ud.altroot = altroot;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_unmount_root(zhp, &ud)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("fix_mountpoint: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount BE root file system\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto cleanup;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassecleanup:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_mount_zones
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function finds all supported non-global zones in the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * given global BE and mounts them with respect to where the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * global BE is currently mounted. The global BE datasets
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * (including its shared datasets) are expected to already
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be mounted.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_zhp - zfs_handle_t pointer to the root dataset of the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * global BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * md - be_mount_data_t pointer to data for global BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_mount_zones(zfs_handle_t *be_zhp, be_mount_data_t *md)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneBrandList_t *brands = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneList_t zlst = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonename = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonepath = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonepath_ds = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int k;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_set_zone_root(md->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((brands = be_get_supported_brandlist()) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "no supported brands\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zlst = z_get_nonglobal_zone_list_by_brand(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zlst == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_brand_list(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (k = 0; (zonename = z_zlist_get_zonename(zlst, k)) != NULL; k++) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (z_zlist_get_current_state(zlst, k) ==
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZONE_STATE_INSTALLED) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath = z_zlist_get_zonepath(zlst, k);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get the dataset of this zonepath in current BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If its not a dataset, skip it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zonepath_ds = be_get_ds_from_dir(zonepath))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Check if this zone is supported based on
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the dataset of its zonepath
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_zone_supported(zonepath_ds)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(zonepath_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath_ds = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * if BE's shared file systems are already mounted,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zone path dataset would have already been lofs
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mounted under altroot. Otherwise, we need to do
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * it here.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!md->shared_fs) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = loopback_mount_zonepath(zonepath, md);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (ret != BE_SUCCESS)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Mount this zone */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = be_mount_one_zone(be_zhp, md, zonename,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath, zonepath_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(zonepath_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath_ds = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (ret != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to mount zone %s under "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "altroot %s\n"), zonename, md->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_brand_list(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_zone_list(zlst);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * libinstzones caches mnttab and uses cached version for resolving lofs
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mounts when we call z_resolve_lofs. It creates the cached version
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * when the first call to z_resolve_lofs happens. So, library's cached
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mnttab doesn't contain entries for lofs mounts created in the above
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * loop. Because of this, subsequent calls to z_resolve_lofs would fail
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to resolve these lofs mounts. So, here we destroy library's cached
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mnttab to force its recreation when the next call to z_resolve_lofs
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * happens.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_destroyMountTable();
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_unmount_zones
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function finds all supported non-global zones in the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * given mounted global BE and unmounts them.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * ud - unmount_data_t pointer data for the global BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_unmount_zones(be_unmount_data_t *ud)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneBrandList_t *brands = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneList_t zlst = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonename = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonepath = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char alt_zonepath[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonepath_ds = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int k;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_set_zone_root(ud->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((brands = be_get_supported_brandlist()) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "no supported brands\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zlst = z_get_nonglobal_zone_list_by_brand(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zlst == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_brand_list(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (k = 0; (zonename = z_zlist_get_zonename(zlst, k)) != NULL; k++) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (z_zlist_get_current_state(zlst, k) ==
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZONE_STATE_INSTALLED) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath = z_zlist_get_zonepath(zlst, k);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Build zone's zonepath wrt the global BE altroot */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(alt_zonepath, sizeof (alt_zonepath),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s%s", ud->altroot, zonepath);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get the dataset of this zonepath. If its not
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a dataset, skip it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zonepath_ds = be_get_ds_from_dir(alt_zonepath))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Check if this zone is supported based on the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset of its zonepath.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_zone_supported(zonepath_ds)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(zonepath_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath_ds = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount this zone */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = be_unmount_one_zone(ud, zonename, zonepath,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(zonepath_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath_ds = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (ret != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_zones:"
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse " failed to unmount zone %s from "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "altroot %s\n"), zonename, ud->altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_brand_list(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_zone_list(zlst);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_mount_one_zone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function is called to mount one zone for a given
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * global BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_zhp - zfs_handle_t pointer to the root dataset of the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * global BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * md - be_mount_data_t pointer to data for global BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zonename - name of zone to mount
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zonepath - zonepath of zone to mount
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zonepath_ds - dataset for the zonepath
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_mount_one_zone(zfs_handle_t *be_zhp, be_mount_data_t *md, char *zonename,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonepath, char *zonepath_ds)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_mount_data_t zone_md = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zone_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zone_altroot[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zoneroot[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zoneroot_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Find the active zone root dataset for this zone for this BE */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_find_active_zone_root(be_zhp, zonepath_ds, zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (zoneroot_ds))) == BE_ERR_ZONE_NO_ACTIVE_ROOT) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_one_zone: did not "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "find active zone root for zone %s, skipping ...\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonename);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (ret != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_one_zone: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "find active zone root for zone %s\n"), zonename);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to active zoneroot dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zone_zhp = zfs_open(g_zfs, zoneroot_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_one_zone: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open zone root dataset (%s): %s\n"), zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate string for zone's altroot path */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_zoneroot(zonepath, zoneroot, sizeof (zoneroot));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(zone_altroot, md->altroot, sizeof (zone_altroot));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcat(zone_altroot, zoneroot, sizeof (zone_altroot));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Build mount_data for the zone */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_md.altroot = zone_altroot;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_md.shared_fs = md->shared_fs;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_md.shared_rw = md->shared_rw;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Mount the zone's root file system */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_mount_zone_root(zone_zhp, &zone_md)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_one_zone: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mount zone root file system at %s\n"), zone_altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate through zone's children filesystems */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zone_zhp, be_mount_callback,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_altroot)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_mount_one_zone: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mount zone subordinate file systems at %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* TODO: Mount all shared file systems for this zone */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zone_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_unmount_one_zone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function unmount one zone for a give global BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * ud - be_unmount_data_t pointer to data for global BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zonename - name of zone to unmount
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zonepath - zonepath of the zone to unmount
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zonepath_ds - dataset for the zonepath
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_unmount_one_zone(be_unmount_data_t *ud, char *zonename, char *zonepath,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonepath_ds)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_unmount_data_t zone_ud = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zone_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zone_altroot[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zoneroot[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zoneroot_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate string for zone's alternate root path */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_zoneroot(zonepath, zoneroot, sizeof (zoneroot));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(zone_altroot, ud->altroot, sizeof (zone_altroot));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcat(zone_altroot, zoneroot, sizeof (zone_altroot));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Build be_unmount_data for zone */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_ud.altroot = zone_altroot;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_ud.force = ud->force;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Find the mounted zone root dataset for this zone for this BE */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_find_mounted_zone_root(zone_altroot, zonepath_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneroot_ds, sizeof (zoneroot_ds))) == BE_ERR_NO_MOUNTED_ZONE) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_one_zone: did not "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "find any zone root mounted for zone %s\n"), zonename);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (ret != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_one_zone: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "find mounted zone root for zone %s\n"), zonename);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to zoneroot dataset mounted for this BE */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zone_zhp = zfs_open(g_zfs, zoneroot_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_one_zone: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open mounted zone root dataset (%s): %s\n"), zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* TODO: Unmount all shared file systems for this zone */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate through zone's children filesystems and unmount them */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zone_zhp, be_unmount_callback,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse &zone_ud)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_one_zone: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount zone subordinate file systems at %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount the zone's root filesystem */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_unmount_zone_root(zone_zhp, &zone_ud)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_unmount_one_zone: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount zone root file system at %s\n"), zone_altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zone_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_get_ds_from_dir_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This is a callback function used to iterate all datasets
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to find the one that is currently mounted at the directory
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * being searched for. If matched, the name of the dataset is
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * returned in heap storage, so the caller is responsible for
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * freeing it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to current dataset being processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - dir_data_t pointer providing name of directory being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * searched for.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 1 - This dataset is mounted at directory being searched for.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - This dataset is not mounted at directory being searched for.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_get_ds_from_dir_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dir_data_t *dd = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *mp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int zret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_is_mounted(zhp, &mp) && mp != NULL &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse strcmp(mp, dd->dir) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((dd->ds = strdup(zfs_get_name(zhp))) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_ds_from_dir_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "memory allocation failed\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zret = zfs_iter_filesystems(zhp, be_get_ds_from_dir_callback, dd);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}