2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. 2N/A * Routines to manage ZFS mounts. We separate all the nasty routines that have 2N/A * to deal with the OS. The following functions are the main entry points -- 2N/A * they are used by mount and unmount and when changing a filesystem's 2N/A * This file also contains the functions used to manage sharing filesystems via 2N/A * zfs_is_shared_nfs() 2N/A * zfs_is_shared_smb() 2N/A * zfs_unshareall_nfs() 2N/A * zfs_unshareall_smb() 2N/A * zfs_unshareall_bypath() 2N/A * The following functions are available for pool consumers, and will 2N/A * zpool_enable_datasets() 2N/A * zpool_disable_datasets() 2N/A * The share protocols table must be in the same order as the zfs_share_prot_t 2N/A * search the sharetab cache for the given mountpoint and protocol, returning 2N/A * a zfs_share_type_t value. 2N/A * Returns true if the specified directory is empty. If we can't open the 2N/A * directory at all, return true so that the mount can fail with a more 2N/A * informative error message. 2N/A * Checks to see if the mount is active. If the filesystem is mounted, we fill 2N/A * in 'where' with the current mountpoint, and return 1. Otherwise, we return 2N/A * Returns true if the given dataset is mountable, false otherwise. Returns the 2N/A * mountpoint in 'buf'. 2N/A * Mount the given filesystem. 2N/A * If the pool is imported read-only then all mounts must be read-only 2N/A * See if there's a temporary mount point defined in the 2N/A * zfs_is_mountable() checks to see whether the dataset's 2N/A * "mountpoint", "canmount", and "zoned" properties are consistent 2N/A * with being mounted. It does not do a full evaluation of all 2N/A * possible obstacles to mounting. 2N/A * For encrypted datasets attempt to load the key. 2N/A * zfs_key_load will return -1 and set errno to ENOTTY if 2N/A * we need to prompt and we are in the SMF start method 2N/A * that have keysource=passphrase,prompt should also have had 2N/A * canmount=noauto. To preserve that partiuclar behaviour 2N/A * we check errno but any other key loading failure we report. 2N/A * Also the zfs_key_load used to be in the zfs_is_mountable() 2N/A * function but it got moved out because that function is also 2N/A * called during dataset destroy and we don't want to attempt 2N/A * key load while destroying a dataset. 2N/A * If a dataset being mounted with a regular (i.e., not 2N/A * temporary) mount inherits its mountpoint from its 2N/A * parent, make sure the parent isn't temp-mounted. 2N/A /* lop off last component to construct the parent name */ 2N/A "failure opening parent"));
2N/A * Don't mount parent datasets or check for a temp-mounted 2N/A * parent dataset if we're operating in a local 2N/A * zone and the parent of the dataset is not zoned. 2N/A * In other words, if the parent dataset is across the "zone 2N/A * boundary" from the child dataset, the parent zone 2N/A * can't be mounted anyway, so no point in trying. Nor is 2N/A * there a problem if the parent is temp-mounted. A 2N/A * temporary mount in the global zone doesn't interfere 2N/A * with the mount in local zone. 2N/A "parent dataset has a temporary " 2N/A "cannot mount '%s' on '%s'"),
2N/A * Mount the parent dataset. We do this to 2N/A * lessen the likelihood that mounts will be 2N/A * done out of order, which can cause 2N/A * mountpoint directories to contain 2N/A * intermediate directories, which prevents 2N/A * mounts from succeeding (because zfs won't do 2N/A * a mount on a non-empty directory). 2N/A * We call zfs_mount() recursively to accomplish 2N/A * this, working our way up the dataset 2N/A * hierarchy. The recursion will stop when a 2N/A * dataset is reached which is already mounted 2N/A * or which has a "local" (i.e., not inherited) 2N/A * mountpoint or which has no parent (i.e., 2N/A * the root of the hierarchy). Then the 2N/A * recursion will unwind, mounting each dataset 2N/A * as it goes down the tree. If a temporarily- 2N/A * mounted dataset is encountered above the one 2N/A * we're trying to mount, report an error and 2N/A * don't mount anything. We don't permit regular 2N/A * zfs mounts under temporary mounts. 2N/A "failure mounting parent dataset"));
2N/A "cannot mount '%s' on '%s'"),
2N/A /* Create the directory if it doesn't already exist */ 2N/A /* temp mounts require that the mount point already exist */ 2N/A "mountpoint must already exist " 2N/A "for temporary mounts"));
2N/A "failed to create mountpoint, " 2N/A * Determine if the mountpoint is empty. If so, refuse to perform the 2N/A * mount. We don't perform this check if MS_OVERLAY is specified, which 2N/A * would defeat the point. We also avoid this check if 'remount' is 2N/A "directory is not empty"));
2N/A * Check to see if this a shadow mount and adjust the mount options as 2N/A /* perform the mount */ 2N/A * Generic errors are nasty, but there are just way too many 2N/A * from mount(), and they're well-understood. We pick a few 2N/A * common ones to improve upon. 2N/A "mountpoint or dataset is busy"));
2N/A "Can't mount file system, FSID conflicts " 2N/A "with another mounted file system"));
2N/A "Insufficient privileges"));
2N/A "file system on a version %d pool. Pool must be" 2N/A " upgraded to mount this file system."),
2N/A * Add the mounted entry into our cache. Because it may 2N/A * be a remount, remove it first. 2N/A * Add this newly mounted fs into the cache. The cache must be a 2N/A * complete representation of all known fs's. Note that the mntopts 2N/A * string cannot be added to this entry since it is not complete. 2N/A * mount() only returns the values of properties that were requested. 2N/A * This would miss properties added by the system such as zone=ZONENAME 2N/A * and sharezone=ZONEID. So we leave the mntopts out of the cache 2N/A * entry and add them later if and when they are needed. 2N/A * Unmount a single filesystem. 2N/A * Unmount the given filesystem. 2N/A /* check to see if we need to unmount the filesystem */ 2N/A * if it isn't NULL. This could get overwritten. 2N/A * Unshare and unmount the filesystem 2N/A * Unmount the shadow filesystem if necessary. 2N/A * mount this filesystem and any children inheriting the mountpoint property. 2N/A * To do this, just act like we're changing the mountpoint property, but don't 2N/A * unmount the filesystems first. 2N/A * Unmount this filesystem and any children inheriting the mountpoint property. 2N/A * To do this, just act like we're changing the mountpoint property, but don't 2N/A * remount the filesystems afterwards. 2N/A * Check to see if the filesystem is currently shared. 2N/A * Share the given filesystem according to the options in the specified 2N/A * protocol specific properties (sharenfs, sharesmb). We rely 2N/A * on "libshare" to do the dirty work for us. 2N/A * Perform sharing upgrades 2N/A * If the 'zoned' property is set, then zfs_is_shareable() 2N/A * will have already bailed out if we are in the global zone. 2N/A * NFS can be a server in a local zone, but nothing else 2N/A * Skip this protocol, if protocol is not supported 2N/A * Wait for completion. 2N/A * Unshare a filesystem by mountpoint. 2N/A * Unshare the given filesystem. 2N/A /* check to see if need to unmount the filesystem */ 2N/A * if it isn't NULL. This could get overwritten. 2N/A * Same as zfs_unmountall(), but for NFS and SMB unshares. 2N/A /* Any share prop will do -- it is just to gather the right FSs */ 2N/A * Remove the mountpoint associated with the current dataset, if necessary. 2N/A * We only remove the underlying directory if: 2N/A * - The mountpoint is not 'none' or 'legacy' 2N/A * - The mountpoint is non-empty 2N/A * - The mountpoint is the default or inherited 2N/A * - The 'zoned' property is set, or we're in a local zone 2N/A * Any other directories we leave alone. 2N/A * Try to remove the directory, silently ignoring any errors. 2N/A * The filesystem may have since been removed or moved around, 2N/A * and this error isn't really useful to the administrator in 2N/A * Since we are iterating over the datasets in the pool 2N/A * in dataset hierarchy we do a prelim attempt at getting 2N/A * encryption keys loaded if they are needed. 2N/A * This is needed for cases where a dataset's mountpoint 2N/A * is lexically before that of the dataset it inherits 2N/A * the keysource property (and thus its wrapping key) from, 2N/A * If we were to return a failure here we would terminate the 2N/A * dataset iteration at this point, so worst case no datasets 2N/A * would get mounted if the top level is encrypted and its key 2N/A * wasn't available but keys for other datasets are. 2N/A * Mount and share all datasets within the given pool. This assumes that no 2N/A * datasets within the pool are currently mounted. Because users can create 2N/A * complicated nested hierarchies of mountpoints, we first gather all the 2N/A * datasets and mountpoints within the pool, and sort them by mountpoint. Once 2N/A * we have the list of all filesystems, we iterate over them in order and mount 2N/A * Gather all non-snap datasets within the pool. 2N/A * If the top level dataset is encrypted load its keys. 2N/A * Sort the datasets by mountpoint. 2N/A * And mount all the datasets, keeping track of which ones succeeded or 2N/A * failed. Treat an already mounted dataset the same as success. 2N/A * Then share all the ones that need to be shared. This needs 2N/A * to be a separate pass in order to avoid excessive reloading 2N/A * of the configuration. Good should never be NULL since 2N/A * zfs_alloc is supposed to exit if memory isn't available. 2N/A/* alias for 2002/240 */ 2N/A * Unshare and unmount all datasets within the given pool. We don't want to 2N/A * rely on traversing the DSL to discover the filesystems within the pool, 2N/A * because this may be expensive (if not all of them are mounted), and can fail 2N/A * arbitrarily (on I/O error, for example). Instead, we walk /etc/mnttab and 2N/A * gather all the filesystems that are currently mounted. 2N/A * Ignore non-ZFS entries. 2N/A * Ignore filesystems not within this pool. 2N/A * At this point we've found a filesystem within our pool. Add 2N/A * it to our growing list. 2N/A * This is allowed to fail, in case there is some I/O error. It 2N/A * is only used to determine if we need to remove the underlying 2N/A * mountpoint, so failure is not fatal. 2N/A * At this point, we have the entire list of filesystems, so sort it by 2N/A * Walk through and first unshare everything. 2N/A "Failed to unshare %s\n"),
2N/A * Now unmount everything, removing the underlying directories as