fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
033f983390fa5d2b54e3e09d83ac9000d71ddaaeek * Common Development and Distribution License (the "License").
033f983390fa5d2b54e3e09d83ac9000d71ddaaeek * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * or http://www.opensolaris.org/os/licensing.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
c3d26abc9ee97b4f60233556aadeb57e0bd30bb9Matthew Ahrens * Copyright (c) 2014 Integros [integros.com]
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante/* Portions Copyright 2010 Robert Milkowski */
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/types.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/param.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/systm.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/sysmacros.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/kmem.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/pathname.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/vnode.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/vfs.h>
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb#include <sys/vfs_opreg.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/mntent.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/mount.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/cmn_err.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "fs/fs_subr.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/zfs_znode.h>
893a6d32980d24be1349478f44169009d4801c25ahrens#include <sys/zfs_dir.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/zil.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/fs/zfs.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dmu.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dsl_prop.h>
b1b8ab34de515a5e83206da22c3d7e563241b021lling#include <sys/dsl_dataset.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/dsl_deleg.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/spa.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/zap.h>
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum#include <sys/sa.h>
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens#include <sys/sa_impl.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/varargs.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/policy.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/atomic.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/mkdev.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/modctl.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/refstr.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/zfs_ioctl.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/zfs_ctldir.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/zfs_fuid.h>
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock#include <sys/bootconf.h>
a0965f35d4137b1f6bb1655ae1cb8fee88dfa66fbonwick#include <sys/sunddi.h>
033f983390fa5d2b54e3e09d83ac9000d71ddaaeek#include <sys/dnlc.h>
f18faf3f3e5def85fdfff681617d227703ace2adek#include <sys/dmu_objset.h>
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw#include <sys/spa_boot.h>
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum#include "zfs_comutil.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensint zfsfstype;
fa9e4066f08beec538e775443c5be79dd423fcabahrensvfsops_t *zfs_vfsops = NULL;
a0965f35d4137b1f6bb1655ae1cb8fee88dfa66fbonwickstatic major_t zfs_major;
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic minor_t zfs_minor;
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic kmutex_t zfs_dev_mtx;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilsonextern int sys_shutdown;
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int zfs_mountroot(vfs_t *vfsp, enum whymountroot);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int zfs_root(vfs_t *vfsp, vnode_t **vpp);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void zfs_freevfs(vfs_t *vfsp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic const fs_operation_def_t zfs_vfsops_template[] = {
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb VFSNAME_MOUNT, { .vfs_mount = zfs_mount },
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb VFSNAME_MOUNTROOT, { .vfs_mountroot = zfs_mountroot },
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb VFSNAME_UNMOUNT, { .vfs_unmount = zfs_umount },
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb VFSNAME_ROOT, { .vfs_root = zfs_root },
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb VFSNAME_STATVFS, { .vfs_statvfs = zfs_statvfs },
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb VFSNAME_SYNC, { .vfs_sync = zfs_sync },
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb VFSNAME_VGET, { .vfs_vget = zfs_vget },
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb VFSNAME_FREEVFS, { .vfs_freevfs = zfs_freevfs },
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb NULL, NULL
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic const fs_operation_def_t zfs_vfsops_eio_template[] = {
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb VFSNAME_FREEVFS, { .vfs_freevfs = zfs_freevfs },
aa59c4cb15a6ac5d4e585dadf7a055b580abf579rsb NULL, NULL
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * We need to keep a count of active fs's.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This is necessary to prevent our module
fa9e4066f08beec538e775443c5be79dd423fcabahrens * from being unloaded after a umount -f
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic uint32_t zfs_active_fs_count = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char *noatime_cancel[] = { MNTOPT_ATIME, NULL };
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char *atime_cancel[] = { MNTOPT_NOATIME, NULL };
7b55fa8ea6046becb3b72f8886a503979c322084ckstatic char *noxattr_cancel[] = { MNTOPT_XATTR, NULL };
7b55fa8ea6046becb3b72f8886a503979c322084ckstatic char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL };
fa9e4066f08beec538e775443c5be79dd423fcabahrens
7b55fa8ea6046becb3b72f8886a503979c322084ck/*
b510d37840323dfb912eab2c7f56325938ed47adlling * MO_DEFAULT is not used since the default value is determined
b510d37840323dfb912eab2c7f56325938ed47adlling * by the equivalent property.
7b55fa8ea6046becb3b72f8886a503979c322084ck */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic mntopt_t mntopts[] = {
7b55fa8ea6046becb3b72f8886a503979c322084ck { MNTOPT_NOXATTR, noxattr_cancel, NULL, 0, NULL },
7b55fa8ea6046becb3b72f8886a503979c322084ck { MNTOPT_XATTR, xattr_cancel, NULL, 0, NULL },
b510d37840323dfb912eab2c7f56325938ed47adlling { MNTOPT_NOATIME, noatime_cancel, NULL, 0, NULL },
fa9e4066f08beec538e775443c5be79dd423fcabahrens { MNTOPT_ATIME, atime_cancel, NULL, 0, NULL }
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic mntopts_t zfs_mntopts = {
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (mntopts) / sizeof (mntopt_t),
fa9e4066f08beec538e775443c5be79dd423fcabahrens mntopts
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*ARGSUSED*/
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_sync(vfs_t *vfsp, short flag, cred_t *cr)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Data integrity is job one. We don't want a compromised kernel
fa9e4066f08beec538e775443c5be79dd423fcabahrens * writing to the storage pool, so we never sync during panic.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (panicstr)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SYNC_ATTR is used by fsflush() to force old filesystems like UFS
fa9e4066f08beec538e775443c5be79dd423fcabahrens * to sync metadata, which they would otherwise cache indefinitely.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Semantically, the only requirement is that the sync be initiated.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The DMU syncs out txgs frequently, so there's nothing to do.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (flag & SYNC_ATTR)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (vfsp != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Sync a specific filesystem.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = vfsp->vfs_data;
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson dsl_pool_t *dp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_ENTER(zfsvfs);
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson dp = dmu_objset_pool(zfsvfs->z_os);
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson /*
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson * If the system is shutting down, then skip any
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson * filesystems which may exist on a suspended pool.
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson */
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson if (sys_shutdown && spa_suspended(dp->dp_spa)) {
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson ZFS_EXIT(zfsvfs);
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson return (0);
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson }
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (zfsvfs->z_log != NULL)
5002558f6bfef3915c7f3b4ecb7c19c7f044bf5bNeil Perrin zil_commit(zfsvfs->z_log, 0);
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_EXIT(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Sync all ZFS filesystems. This is what happens when you
fa9e4066f08beec538e775443c5be79dd423fcabahrens * run sync(1M). Unlike other filesystems, ZFS honors the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * request by waiting for all pools to commit all dirty data.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens spa_sync_allpools();
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockzfs_create_unique_device(dev_t *dev)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock major_t new_major;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT3U(zfs_minor, <=, MAXMIN32);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock minor_t start = zfs_minor;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_enter(&zfs_dev_mtx);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (zfs_minor >= MAXMIN32) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * If we're still using the real major
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * keep out of /dev/zfs and /dev/zvol minor
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * number space. If we're using a getudev()'ed
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * major number, we can use all of its minors.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (zfs_major == ddi_name_to_major(ZFS_DRIVER))
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfs_minor = ZFS_MIN_MINOR;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock else
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfs_minor = 0;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfs_minor++;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock *dev = makedevice(zfs_major, zfs_minor);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_exit(&zfs_dev_mtx);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } while (vfs_devismounted(*dev) && zfs_minor != start);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (zfs_minor == start) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * We are using all ~262,000 minor numbers for the
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * current major number. Create a new major number.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if ((new_major = getudev()) == (major_t)-1) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock cmn_err(CE_WARN,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock "zfs_mount: Can't get unique major "
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock "device number.");
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (-1);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_enter(&zfs_dev_mtx);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfs_major = new_major;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfs_minor = 0;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_exit(&zfs_dev_mtx);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock break;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* CONSTANTCONDITION */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } while (1);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (0);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensatime_changed_cb(void *arg, uint64_t newval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = arg;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (newval == TRUE) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_atime = TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME);
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_ATIME, NULL, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_atime = FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_ATIME);
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME, NULL, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
7b55fa8ea6046becb3b72f8886a503979c322084ckstatic void
7b55fa8ea6046becb3b72f8886a503979c322084ckxattr_changed_cb(void *arg, uint64_t newval)
7b55fa8ea6046becb3b72f8886a503979c322084ck{
7b55fa8ea6046becb3b72f8886a503979c322084ck zfsvfs_t *zfsvfs = arg;
7b55fa8ea6046becb3b72f8886a503979c322084ck
7b55fa8ea6046becb3b72f8886a503979c322084ck if (newval == TRUE) {
7b55fa8ea6046becb3b72f8886a503979c322084ck /* XXX locking on vfs_flag? */
7b55fa8ea6046becb3b72f8886a503979c322084ck zfsvfs->z_vfs->vfs_flag |= VFS_XATTR;
7b55fa8ea6046becb3b72f8886a503979c322084ck vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR);
7b55fa8ea6046becb3b72f8886a503979c322084ck vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_XATTR, NULL, 0);
7b55fa8ea6046becb3b72f8886a503979c322084ck } else {
7b55fa8ea6046becb3b72f8886a503979c322084ck /* XXX locking on vfs_flag? */
7b55fa8ea6046becb3b72f8886a503979c322084ck zfsvfs->z_vfs->vfs_flag &= ~VFS_XATTR;
7b55fa8ea6046becb3b72f8886a503979c322084ck vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_XATTR);
7b55fa8ea6046becb3b72f8886a503979c322084ck vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR, NULL, 0);
7b55fa8ea6046becb3b72f8886a503979c322084ck }
7b55fa8ea6046becb3b72f8886a503979c322084ck}
7b55fa8ea6046becb3b72f8886a503979c322084ck
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensblksz_changed_cb(void *arg, uint64_t newval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = arg;
b515258426fed6c7311fd3f1dea697cfbd4085c6Matthew Ahrens ASSERT3U(newval, <=, spa_maxblocksize(dmu_objset_spa(zfsvfs->z_os)));
b515258426fed6c7311fd3f1dea697cfbd4085c6Matthew Ahrens ASSERT3U(newval, >=, SPA_MINBLOCKSIZE);
b515258426fed6c7311fd3f1dea697cfbd4085c6Matthew Ahrens ASSERT(ISP2(newval));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_max_blksz = newval;
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_vfs->vfs_bsize = newval;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensreadonly_changed_cb(void *arg, uint64_t newval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = arg;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (newval) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* XXX locking on vfs_flag? */
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RW);
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RO, NULL, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* XXX locking on vfs_flag? */
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RO);
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RW, NULL, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensdevices_changed_cb(void *arg, uint64_t newval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = arg;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (newval == FALSE) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_vfs->vfs_flag |= VFS_NODEVICES;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES);
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES, NULL, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NODEVICES;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES);
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES, NULL, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetuid_changed_cb(void *arg, uint64_t newval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = arg;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (newval == FALSE) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_vfs->vfs_flag |= VFS_NOSETUID;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_SETUID);
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID, NULL, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NOSETUID;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID);
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_SETUID, NULL, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensexec_changed_cb(void *arg, uint64_t newval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = arg;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (newval == FALSE) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_vfs->vfs_flag |= VFS_NOEXEC;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_EXEC);
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC, NULL, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NOEXEC;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC);
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_EXEC, NULL, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The nbmand mount option can be changed at mount time.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * We can't allow it to be toggled on live file systems or incorrect
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * behavior may be seen from cifs clients
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This property isn't registered via dsl_prop_register(), but this callback
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * will be called when a file system is first mounted
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwnbmand_changed_cb(void *arg, uint64_t newval)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zfsvfs_t *zfsvfs = arg;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (newval == FALSE) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND, NULL, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND, NULL, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrenssnapdir_changed_cb(void *arg, uint64_t newval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = arg;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_show_ctldir = newval;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvscan_changed_cb(void *arg, uint64_t newval)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zfsvfs_t *zfsvfs = arg;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zfsvfs->z_vscan = newval;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a3c49ce110f325a563c245bedc4d533adddb7211Albert Leestatic void
a3c49ce110f325a563c245bedc4d533adddb7211Albert Leeacl_mode_changed_cb(void *arg, uint64_t newval)
a3c49ce110f325a563c245bedc4d533adddb7211Albert Lee{
a3c49ce110f325a563c245bedc4d533adddb7211Albert Lee zfsvfs_t *zfsvfs = arg;
a3c49ce110f325a563c245bedc4d533adddb7211Albert Lee
a3c49ce110f325a563c245bedc4d533adddb7211Albert Lee zfsvfs->z_acl_mode = newval;
a3c49ce110f325a563c245bedc4d533adddb7211Albert Lee}
a3c49ce110f325a563c245bedc4d533adddb7211Albert Lee
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensacl_inherit_changed_cb(void *arg, uint64_t newval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = arg;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_acl_inherit = newval;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockzfs_register_callbacks(vfs_t *vfsp)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock struct dsl_dataset *ds = NULL;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock objset_t *os = NULL;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfsvfs_t *zfsvfs = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint64_t nbmand;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t readonly = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t do_readonly = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t setuid = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t do_setuid = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t exec = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t do_exec = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t devices = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t do_devices = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t xattr = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t do_xattr = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t atime = B_FALSE;
d5285cae913f4e01ffa0e6693a6d8ef1fbea30baGeorge Wilson boolean_t do_atime = B_FALSE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock int error = 0;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT(vfsp);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfsvfs = vfsp->vfs_data;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT(zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock os = zfsvfs->z_os;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * The act of registering our callbacks will destroy any mount
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * options we may have. In order to enable temporary overrides
7b55fa8ea6046becb3b72f8886a503979c322084ck * of mount options, we stash away the current values and
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * restore them after we register the callbacks.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson if (vfs_optionisset(vfsp, MNTOPT_RO, NULL) ||
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson !spa_writeable(dmu_objset_spa(os))) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock readonly = B_TRUE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do_readonly = B_TRUE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else if (vfs_optionisset(vfsp, MNTOPT_RW, NULL)) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock readonly = B_FALSE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do_readonly = B_TRUE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL)) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock devices = B_FALSE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock setuid = B_FALSE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do_devices = B_TRUE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do_setuid = B_TRUE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL)) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock devices = B_FALSE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do_devices = B_TRUE;
b1b8ab34de515a5e83206da22c3d7e563241b021lling } else if (vfs_optionisset(vfsp, MNTOPT_DEVICES, NULL)) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock devices = B_TRUE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do_devices = B_TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock setuid = B_FALSE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do_setuid = B_TRUE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else if (vfs_optionisset(vfsp, MNTOPT_SETUID, NULL)) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock setuid = B_TRUE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do_setuid = B_TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock exec = B_FALSE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do_exec = B_TRUE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else if (vfs_optionisset(vfsp, MNTOPT_EXEC, NULL)) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock exec = B_TRUE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock do_exec = B_TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
7b55fa8ea6046becb3b72f8886a503979c322084ck if (vfs_optionisset(vfsp, MNTOPT_NOXATTR, NULL)) {
7b55fa8ea6046becb3b72f8886a503979c322084ck xattr = B_FALSE;
7b55fa8ea6046becb3b72f8886a503979c322084ck do_xattr = B_TRUE;
7b55fa8ea6046becb3b72f8886a503979c322084ck } else if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) {
7b55fa8ea6046becb3b72f8886a503979c322084ck xattr = B_TRUE;
7b55fa8ea6046becb3b72f8886a503979c322084ck do_xattr = B_TRUE;
7b55fa8ea6046becb3b72f8886a503979c322084ck }
b510d37840323dfb912eab2c7f56325938ed47adlling if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) {
b510d37840323dfb912eab2c7f56325938ed47adlling atime = B_FALSE;
b510d37840323dfb912eab2c7f56325938ed47adlling do_atime = B_TRUE;
b510d37840323dfb912eab2c7f56325938ed47adlling } else if (vfs_optionisset(vfsp, MNTOPT_ATIME, NULL)) {
b510d37840323dfb912eab2c7f56325938ed47adlling atime = B_TRUE;
b510d37840323dfb912eab2c7f56325938ed47adlling do_atime = B_TRUE;
b510d37840323dfb912eab2c7f56325938ed47adlling }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * nbmand is a special property. It can only be changed at
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mount time.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is weird, but it is documented to only be changeable
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * at mount time.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (vfs_optionisset(vfsp, MNTOPT_NONBMAND, NULL)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nbmand = B_FALSE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nbmand = B_TRUE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char osname[ZFS_MAX_DATASET_NAME_LEN];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dmu_objset_name(os, osname);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (error = dsl_prop_get_integer(osname, "nbmand", &nbmand,
bb0ade0978a02d3fe0b0165cd4725fdcb593fbfbahrens NULL)) {
bb0ade0978a02d3fe0b0165cd4725fdcb593fbfbahrens return (error);
bb0ade0978a02d3fe0b0165cd4725fdcb593fbfbahrens }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Register property callbacks.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock *
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * It would probably be fine to just check for i/o error from
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * the first prop_register(), but I guess I like to go
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * overboard...
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ds = dmu_objset_ds(os);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens error = dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_ATIME), atime_changed_cb, zfsvfs);
7b55fa8ea6046becb3b72f8886a503979c322084ck error = error ? error : dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_XATTR), xattr_changed_cb, zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock error = error ? error : dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_RECORDSIZE), blksz_changed_cb, zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock error = error ? error : dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_READONLY), readonly_changed_cb, zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock error = error ? error : dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_DEVICES), devices_changed_cb, zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock error = error ? error : dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_SETUID), setuid_changed_cb, zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock error = error ? error : dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_EXEC), exec_changed_cb, zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock error = error ? error : dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_SNAPDIR), snapdir_changed_cb, zfsvfs);
a3c49ce110f325a563c245bedc4d533adddb7211Albert Lee error = error ? error : dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_ACLMODE), acl_mode_changed_cb, zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock error = error ? error : dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_ACLINHERIT), acl_inherit_changed_cb,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfsvfs);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = error ? error : dsl_prop_register(ds,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_VSCAN), vscan_changed_cb, zfsvfs);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (error)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock goto unregister;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Invoke our callbacks to restore temporary mount options.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (do_readonly)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock readonly_changed_cb(zfsvfs, readonly);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (do_setuid)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock setuid_changed_cb(zfsvfs, setuid);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (do_exec)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock exec_changed_cb(zfsvfs, exec);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (do_devices)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock devices_changed_cb(zfsvfs, devices);
7b55fa8ea6046becb3b72f8886a503979c322084ck if (do_xattr)
7b55fa8ea6046becb3b72f8886a503979c322084ck xattr_changed_cb(zfsvfs, xattr);
b510d37840323dfb912eab2c7f56325938ed47adlling if (do_atime)
b510d37840323dfb912eab2c7f56325938ed47adlling atime_changed_cb(zfsvfs, atime);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nbmand_changed_cb(zfsvfs, nbmand);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockunregister:
03bad06fbb261fd4a7151a70dfeff2f5041cce1fJustin Gibbs dsl_prop_unregister_all(ds, zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (error);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
9966ca11f4a1481acce85f690fa59e4084050627Matthew Ahrensstatic int
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumzfs_space_delta_cb(dmu_object_type_t bonustype, void *data,
9966ca11f4a1481acce85f690fa59e4084050627Matthew Ahrens uint64_t *userp, uint64_t *groupp)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens{
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum /*
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum * Is it a valid type of object to track?
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum */
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (bonustype != DMU_OT_ZNODE && bonustype != DMU_OT_SA)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ENOENT));
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum /*
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum * If we have a NULL data pointer
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum * then assume the id's aren't changing and
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum * return EEXIST to the dmu to let it know to
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum * use the same ids
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum */
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum if (data == NULL)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EEXIST));
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (bonustype == DMU_OT_ZNODE) {
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens znode_phys_t *znp = data;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum *userp = znp->zp_uid;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum *groupp = znp->zp_gid;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum } else {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum int hdrsize;
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens sa_hdr_phys_t *sap = data;
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens sa_hdr_phys_t sa = *sap;
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens boolean_t swap = B_FALSE;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum ASSERT(bonustype == DMU_OT_SA);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens if (sa.sa_magic == 0) {
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum /*
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum * This should only happen for newly created
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum * files that haven't had the znode data filled
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum * in yet.
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum */
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum *userp = 0;
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum *groupp = 0;
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens return (0);
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens }
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens if (sa.sa_magic == BSWAP_32(SA_MAGIC)) {
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens sa.sa_magic = SA_MAGIC;
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens sa.sa_layout_info = BSWAP_16(sa.sa_layout_info);
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens swap = B_TRUE;
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens } else {
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens VERIFY3U(sa.sa_magic, ==, SA_MAGIC);
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens }
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens hdrsize = sa_hdrsize(&sa);
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens VERIFY3U(hdrsize, >=, sizeof (sa_hdr_phys_t));
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens *userp = *((uint64_t *)((uintptr_t)data + hdrsize +
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens SA_UID_OFFSET));
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens *groupp = *((uint64_t *)((uintptr_t)data + hdrsize +
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens SA_GID_OFFSET));
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens if (swap) {
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens *userp = BSWAP_64(*userp);
e828a46d29ad418487f50d56b5c19e2a1f9033a7Matthew Ahrens *groupp = BSWAP_64(*groupp);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens return (0);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens}
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensstatic void
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensfuidstr_to_sid(zfsvfs_t *zfsvfs, const char *fuidstr,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens char *domainbuf, int buflen, uid_t *ridp)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens{
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens uint64_t fuid;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens const char *domain;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens fuid = strtonum(fuidstr, NULL);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens domain = zfs_fuid_find_by_idx(zfsvfs, FUID_INDEX(fuid));
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (domain)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens (void) strlcpy(domainbuf, domain, buflen);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens else
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens domainbuf[0] = '\0';
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens *ridp = FUID_RID(fuid);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens}
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensstatic uint64_t
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrenszfs_userquota_prop_to_obj(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens{
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens switch (type) {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens case ZFS_PROP_USERUSED:
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (DMU_USERUSED_OBJECT);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens case ZFS_PROP_GROUPUSED:
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (DMU_GROUPUSED_OBJECT);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens case ZFS_PROP_USERQUOTA:
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (zfsvfs->z_userquota_obj);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens case ZFS_PROP_GROUPQUOTA:
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (zfsvfs->z_groupquota_obj);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (0);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens}
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensint
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrenszfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens uint64_t *cookiep, void *vbuf, uint64_t *bufsizep)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens{
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens int error;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zap_cursor_t zc;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zap_attribute_t za;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfs_useracct_t *buf = vbuf;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens uint64_t obj;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (!dmu_objset_userspace_present(zfsvfs->z_os))
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ENOTSUP));
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens obj = zfs_userquota_prop_to_obj(zfsvfs, type);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (obj == 0) {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens *bufsizep = 0;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (0);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens for (zap_cursor_init_serialized(&zc, zfsvfs->z_os, obj, *cookiep);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens (error = zap_cursor_retrieve(&zc, &za)) == 0;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zap_cursor_advance(&zc)) {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if ((uintptr_t)buf - (uintptr_t)vbuf + sizeof (zfs_useracct_t) >
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens *bufsizep)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens break;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens fuidstr_to_sid(zfsvfs, za.za_name,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens buf->zu_domain, sizeof (buf->zu_domain), &buf->zu_rid);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens buf->zu_space = za.za_first_integer;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens buf++;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (error == ENOENT)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens error = 0;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens ASSERT3U((uintptr_t)buf - (uintptr_t)vbuf, <=, *bufsizep);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens *bufsizep = (uintptr_t)buf - (uintptr_t)vbuf;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens *cookiep = zap_cursor_serialize(&zc);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zap_cursor_fini(&zc);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (error);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens}
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens/*
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * buf must be big enough (eg, 32 bytes)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens */
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensstatic int
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensid_to_fuidstr(zfsvfs_t *zfsvfs, const char *domain, uid_t rid,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens char *buf, boolean_t addok)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens{
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens uint64_t fuid;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens int domainid = 0;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (domain && domain[0]) {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens domainid = zfs_fuid_find_by_domain(zfsvfs, domain, NULL, addok);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (domainid == -1)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ENOENT));
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens fuid = FUID_ENCODE(domainid, rid);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens (void) sprintf(buf, "%llx", (longlong_t)fuid);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (0);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens}
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensint
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrenszfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens const char *domain, uint64_t rid, uint64_t *valp)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens{
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens char buf[32];
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens int err;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens uint64_t obj;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens *valp = 0;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (!dmu_objset_userspace_present(zfsvfs->z_os))
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ENOTSUP));
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens obj = zfs_userquota_prop_to_obj(zfsvfs, type);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (obj == 0)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (0);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_FALSE);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (err)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (err);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens err = zap_lookup(zfsvfs->z_os, obj, buf, 8, 1, valp);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (err == ENOENT)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens err = 0;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (err);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens}
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensint
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrenszfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens const char *domain, uint64_t rid, uint64_t quota)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens{
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens char buf[32];
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens int err;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens dmu_tx_t *tx;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens uint64_t *objp;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens boolean_t fuid_dirtied;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (type != ZFS_PROP_USERQUOTA && type != ZFS_PROP_GROUPQUOTA)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EINVAL));
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (zfsvfs->z_version < ZPL_VERSION_USERSPACE)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ENOTSUP));
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens objp = (type == ZFS_PROP_USERQUOTA) ? &zfsvfs->z_userquota_obj :
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens &zfsvfs->z_groupquota_obj;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_TRUE);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (err)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (err);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens fuid_dirtied = zfsvfs->z_fuid_dirty;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens tx = dmu_tx_create(zfsvfs->z_os);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens dmu_tx_hold_zap(tx, *objp ? *objp : DMU_NEW_OBJECT, B_TRUE, NULL);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (*objp == 0) {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfs_userquota_prop_prefixes[type]);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (fuid_dirtied)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfs_fuid_txhold(zfsvfs, tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens err = dmu_tx_assign(tx, TXG_WAIT);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (err) {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens dmu_tx_abort(tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (err);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens mutex_enter(&zfsvfs->z_lock);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (*objp == 0) {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens *objp = zap_create(zfsvfs->z_os, DMU_OT_USERGROUP_QUOTA,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens DMU_OT_NONE, 0, tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens VERIFY(0 == zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfs_userquota_prop_prefixes[type], 8, 1, objp, tx));
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens mutex_exit(&zfsvfs->z_lock);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (quota == 0) {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens err = zap_remove(zfsvfs->z_os, *objp, buf, tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (err == ENOENT)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens err = 0;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens } else {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens err = zap_update(zfsvfs->z_os, *objp, buf, 8, 1, &quota, tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens ASSERT(err == 0);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (fuid_dirtied)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfs_fuid_sync(zfsvfs, tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens dmu_tx_commit(tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (err);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens}
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensboolean_t
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumzfs_fuid_overquota(zfsvfs_t *zfsvfs, boolean_t isgroup, uint64_t fuid)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens{
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens char buf[32];
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens uint64_t used, quota, usedobj, quotaobj;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens int err;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens usedobj = isgroup ? DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (quotaobj == 0 || zfsvfs->z_replay)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (B_FALSE);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens (void) sprintf(buf, "%llx", (longlong_t)fuid);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, &quota);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (err != 0)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (B_FALSE);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (err != 0)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (B_FALSE);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (used >= quota);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens}
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumboolean_t
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumzfs_owner_overquota(zfsvfs_t *zfsvfs, znode_t *zp, boolean_t isgroup)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum{
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum uint64_t fuid;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum uint64_t quotaobj;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
f1696b231bb1209e1cea95b7ff29b8c60493daa0Mark Shellenbaum fuid = isgroup ? zp->z_gid : zp->z_uid;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (quotaobj == 0 || zfsvfs->z_replay)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (B_FALSE);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (zfs_fuid_overquota(zfsvfs, isgroup, fuid));
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum}
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens/*
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens * Associate this zfsvfs with the given objset, which must be owned.
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens * This will cache a bunch of on-disk state from the objset in the
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens * zfsvfs.
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens */
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrensstatic int
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrenszfsvfs_init(zfsvfs_t *zfsvfs, objset_t *os)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens{
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens int error;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens uint64_t val;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
b515258426fed6c7311fd3f1dea697cfbd4085c6Matthew Ahrens zfsvfs->z_max_blksz = SPA_OLD_MAXBLOCKSIZE;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfsvfs->z_show_ctldir = ZFS_SNAPDIR_VISIBLE;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfsvfs->z_os = os;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zfsvfs->z_version);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (zfsvfs->z_version >
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum zfs_zpl_version_map(spa_version(dmu_objset_spa(os)))) {
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum (void) printf("Can't mount a version %lld file system "
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum "on a version %lld pool\n. Pool must be upgraded to mount "
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum "this file system.", (u_longlong_t)zfsvfs->z_version,
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum (u_longlong_t)spa_version(dmu_objset_spa(os)));
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (SET_ERROR(ENOTSUP));
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens error = zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &val);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs->z_norm = (int)val;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens error = zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &val);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs->z_utf8 = (val != 0);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens error = zfs_get_zplprop(os, ZFS_PROP_CASE, &val);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs->z_case = (uint_t)val;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens /*
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * Fold case on file systems that are always or sometimes case
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * insensitive.
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens */
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE ||
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfsvfs->z_case == ZFS_CASE_MIXED)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens uint64_t sa_obj = 0;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (zfsvfs->z_use_sa) {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum /* should either have both of these objects or none */
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1,
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum &sa_obj);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
1d8ccc7bfd8ab0f27a23c5253d95c22ceb9c27f4Mark Shellenbaum error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END,
1d8ccc7bfd8ab0f27a23c5253d95c22ceb9c27f4Mark Shellenbaum &zfsvfs->z_attr_table);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (zfsvfs->z_version >= ZPL_VERSION_SA)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum sa_register_update_callback(os, zfs_sa_upgrade);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens &zfsvfs->z_root);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens ASSERT(zfsvfs->z_root != 0);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET, 8, 1,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens &zfsvfs->z_unlinkedobj);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfs_userquota_prop_prefixes[ZFS_PROP_USERQUOTA],
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens 8, 1, &zfsvfs->z_userquota_obj);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error == ENOENT)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs->z_userquota_obj = 0;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens else if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfs_userquota_prop_prefixes[ZFS_PROP_GROUPQUOTA],
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens 8, 1, &zfsvfs->z_groupquota_obj);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error == ENOENT)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs->z_groupquota_obj = 0;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens else if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES, 8, 1,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens &zfsvfs->z_fuid_obj);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error == ENOENT)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs->z_fuid_obj = 0;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens else if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SHARES_DIR, 8, 1,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens &zfsvfs->z_shares_dir);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error == ENOENT)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs->z_shares_dir = 0;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens else if (error != 0)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (0);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens}
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrensint
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrenszfsvfs_create(const char *osname, zfsvfs_t **zfvp)
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens{
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens objset_t *os;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs_t *zfsvfs;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens int error;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens /*
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens * We claim to always be readonly so we can open snapshots;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens * other ZPL code will prevent us from writing to snapshots.
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens */
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens error = dmu_objset_own(osname, DMU_OST_ZFS, B_TRUE, zfsvfs, &os);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error) {
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens kmem_free(zfsvfs, sizeof (zfsvfs_t));
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens }
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs->z_vfs = NULL;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens zfsvfs->z_parent = zfsvfs;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens list_create(&zfsvfs->z_all_znodes, sizeof (znode_t),
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens offsetof(znode_t, z_link_node));
c9030f6c93613fe30ee0c16f92b96da7816ac052Alexander Motin rrm_init(&zfsvfs->z_teardown_lock, B_FALSE);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens for (int i = 0; i != ZFS_OBJ_MTX_SZ; i++)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens error = zfsvfs_init(zfsvfs, os);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (error != 0) {
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens dmu_objset_disown(os, zfsvfs);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens *zfvp = NULL;
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens kmem_free(zfsvfs, sizeof (zfsvfs_t));
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens return (error);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens }
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens
af4c679f647cf088543c762e33d41a3ac52cfa14Sean McEnroe *zfvp = zfsvfs;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (0);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens}
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
f18faf3f3e5def85fdfff681617d227703ace2adekstatic int
f18faf3f3e5def85fdfff681617d227703ace2adekzfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
f18faf3f3e5def85fdfff681617d227703ace2adek{
f18faf3f3e5def85fdfff681617d227703ace2adek int error;
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek error = zfs_register_callbacks(zfsvfs->z_vfs);
f18faf3f3e5def85fdfff681617d227703ace2adek if (error)
f18faf3f3e5def85fdfff681617d227703ace2adek return (error);
f18faf3f3e5def85fdfff681617d227703ace2adek
377c02aa0cc369d8f469c7540a74a132e77a2c59Neil Perrin zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data);
377c02aa0cc369d8f469c7540a74a132e77a2c59Neil Perrin
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * If we are not mounting (ie: online recv), then we don't
f18faf3f3e5def85fdfff681617d227703ace2adek * have to worry about replaying the log as we blocked all
f18faf3f3e5def85fdfff681617d227703ace2adek * operations out since we closed the ZIL.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adek if (mounting) {
a6e57bd4c7a2bf9cc33be939d674d4c7d3e67cceNeil Perrin boolean_t readonly;
a6e57bd4c7a2bf9cc33be939d674d4c7d3e67cceNeil Perrin
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * During replay we remove the read only flag to
f18faf3f3e5def85fdfff681617d227703ace2adek * allow replays to succeed.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adek readonly = zfsvfs->z_vfs->vfs_flag & VFS_RDONLY;
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin if (readonly != 0)
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY;
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin else
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin zfs_unlinked_drain(zfsvfs);
f18faf3f3e5def85fdfff681617d227703ace2adek
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante /*
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * Parse and replay the intent log.
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante *
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * Because of ziltest, this must be done after
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * zfs_unlinked_drain(). (Further note: ziltest
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * doesn't use readonly mounts, where
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * zfs_unlinked_drain() isn't called.) This is because
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * ziltest causes spa_sync() to think it's committed,
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * but actually it is not, so the intent log contains
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * many txg's worth of changes.
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante *
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * In particular, if object N is in the unlinked set in
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * the last txg to actually sync, then it could be
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * actually freed in a later txg and then reallocated
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * in a yet later txg. This would write a "create
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * object N" record to the intent log. Normally, this
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * would be fine because the spa_sync() would have
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * written out the fact that object N is free, before
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * we could write the "create object N" intent log
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * record.
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante *
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * But when we are in ziltest mode, we advance the "open
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * txg" without actually spa_sync()-ing the changes to
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * disk. So we would see that object N is still
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * allocated and in the unlinked set, and there is an
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante * intent log record saying to allocate it.
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante */
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson if (spa_writeable(dmu_objset_spa(zfsvfs->z_os))) {
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson if (zil_replay_disable) {
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson zil_destroy(zfsvfs->z_log, B_FALSE);
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson } else {
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson zfsvfs->z_replay = B_TRUE;
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson zil_replay(zfsvfs->z_os, zfsvfs,
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson zfs_replay_vector);
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson zfsvfs->z_replay = B_FALSE;
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson }
1209a471b5681c43d839d4b890f708f500da7346Neil Perrin }
f18faf3f3e5def85fdfff681617d227703ace2adek zfsvfs->z_vfs->vfs_flag |= readonly; /* restore readonly bit */
f18faf3f3e5def85fdfff681617d227703ace2adek }
f18faf3f3e5def85fdfff681617d227703ace2adek
90f2c094b3822f4825f21cef2c2faf7d03b55139Andriy Gapon /*
90f2c094b3822f4825f21cef2c2faf7d03b55139Andriy Gapon * Set the objset user_ptr to track its zfsvfs.
90f2c094b3822f4825f21cef2c2faf7d03b55139Andriy Gapon */
90f2c094b3822f4825f21cef2c2faf7d03b55139Andriy Gapon mutex_enter(&zfsvfs->z_os->os_user_ptr_lock);
90f2c094b3822f4825f21cef2c2faf7d03b55139Andriy Gapon dmu_objset_set_user(zfsvfs->z_os, zfsvfs);
90f2c094b3822f4825f21cef2c2faf7d03b55139Andriy Gapon mutex_exit(&zfsvfs->z_os->os_user_ptr_lock);
90f2c094b3822f4825f21cef2c2faf7d03b55139Andriy Gapon
f18faf3f3e5def85fdfff681617d227703ace2adek return (0);
f18faf3f3e5def85fdfff681617d227703ace2adek}
f18faf3f3e5def85fdfff681617d227703ace2adek
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensvoid
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrenszfsvfs_free(zfsvfs_t *zfsvfs)
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek{
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens int i;
4e9583b23260dab68308b306795694143381ab0fTom Erickson extern krwlock_t zfsvfs_lock; /* in zfs_znode.c */
4e9583b23260dab68308b306795694143381ab0fTom Erickson
4e9583b23260dab68308b306795694143381ab0fTom Erickson /*
4e9583b23260dab68308b306795694143381ab0fTom Erickson * This is a barrier to prevent the filesystem from going away in
4e9583b23260dab68308b306795694143381ab0fTom Erickson * zfs_znode_move() until we can safely ensure that the filesystem is
4e9583b23260dab68308b306795694143381ab0fTom Erickson * not unmounted. We consider the filesystem valid before the barrier
4e9583b23260dab68308b306795694143381ab0fTom Erickson * and invalid after the barrier.
4e9583b23260dab68308b306795694143381ab0fTom Erickson */
4e9583b23260dab68308b306795694143381ab0fTom Erickson rw_enter(&zfsvfs_lock, RW_READER);
4e9583b23260dab68308b306795694143381ab0fTom Erickson rw_exit(&zfsvfs_lock);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfs_fuid_destroy(zfsvfs);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek mutex_destroy(&zfsvfs->z_znodes_lock);
9e1320c015cea6985d2122bc1d654b79fa479f7aMark Shellenbaum mutex_destroy(&zfsvfs->z_lock);
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek list_destroy(&zfsvfs->z_all_znodes);
c9030f6c93613fe30ee0c16f92b96da7816ac052Alexander Motin rrm_destroy(&zfsvfs->z_teardown_lock);
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek rw_destroy(&zfsvfs->z_teardown_inactive_lock);
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek rw_destroy(&zfsvfs->z_fuid_lock);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens mutex_destroy(&zfsvfs->z_hold_mtx[i]);
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek kmem_free(zfsvfs, sizeof (zfsvfs_t));
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek}
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrensstatic void
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrenszfs_set_fuid_feature(zfsvfs_t *zfsvfs)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens{
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum if (zfsvfs->z_vfs) {
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum if (zfsvfs->z_use_fuids) {
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_XVATTR);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_REPARSE);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum } else {
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_XVATTR);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_REPARSE);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens}
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int
088f389458728c464569a5506b58070254fa4f7dahrenszfs_domount(vfs_t *vfsp, char *osname)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dev_t mount_dev;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens uint64_t recordsize, fsid_guid;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock int error = 0;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfsvfs_t *zfsvfs;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT(vfsp);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT(osname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens error = zfsvfs_create(osname, &zfsvfs);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (error)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_vfs = vfsp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* Initialize the generic filesystem structure. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfsp->vfs_bcount = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfsp->vfs_data = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (zfs_create_unique_device(&mount_dev) == -1) {
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens error = SET_ERROR(ENODEV);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock goto out;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(vfs_devismounted(mount_dev) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (error = dsl_prop_get_integer(osname, "recordsize", &recordsize,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock NULL))
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock goto out;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfsp->vfs_dev = mount_dev;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfsp->vfs_fstype = zfsfstype;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfsp->vfs_bsize = recordsize;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfsp->vfs_flag |= VFS_NOTRUNC;
fa9e4066f08beec538e775443c5be79dd423fcabahrens vfsp->vfs_data = zfsvfs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens /*
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * The fsid is 64 bits, composed of an 8-bit fs type, which
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * separates our fsid from any other filesystem types, and a
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * 56-bit objset unique ID. The objset unique ID is unique to
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * all objsets open on this system, provided by unique_create().
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * The 8-bit fs type must be put in the low bits of fsid[1]
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens * because that's where other Solaris filesystems put it.
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens */
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens fsid_guid = dmu_objset_fsid_guid(zfsvfs->z_os);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens ASSERT((fsid_guid & ~((1ULL<<56)-1)) == 0);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens vfsp->vfs_fsid.val[0] = fsid_guid;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens vfsp->vfs_fsid.val[1] = ((fsid_guid>>32) << 8) |
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfsfstype & 0xFF;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Set features for file system.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfs_set_fuid_feature(zfsvfs);
de8267e0f723ed2c38ea9def92d465f69a300f56timh if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {
de8267e0f723ed2c38ea9def92d465f69a300f56timh vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS);
de8267e0f723ed2c38ea9def92d465f69a300f56timh vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE);
de8267e0f723ed2c38ea9def92d465f69a300f56timh vfs_set_feature(vfsp, VFSFT_NOCASESENSITIVE);
de8267e0f723ed2c38ea9def92d465f69a300f56timh } else if (zfsvfs->z_case == ZFS_CASE_MIXED) {
de8267e0f723ed2c38ea9def92d465f69a300f56timh vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS);
de8267e0f723ed2c38ea9def92d465f69a300f56timh vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE);
de8267e0f723ed2c38ea9def92d465f69a300f56timh }
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States vfs_set_feature(vfsp, VFSFT_ZEROCOPY_SUPPORTED);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (dmu_objset_is_snapshot(zfsvfs->z_os)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint64_t pval;
7b55fa8ea6046becb3b72f8886a503979c322084ck
fa9e4066f08beec538e775443c5be79dd423fcabahrens atime_changed_cb(zfsvfs, B_FALSE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens readonly_changed_cb(zfsvfs, B_TRUE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (error = dsl_prop_get_integer(osname, "xattr", &pval, NULL))
7b55fa8ea6046becb3b72f8886a503979c322084ck goto out;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw xattr_changed_cb(zfsvfs, pval);
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs->z_issnap = B_TRUE;
b9deb9cbabad14a90568685547dcba40b98bf84dMark J Musante zfsvfs->z_os->os_sync = ZFS_SYNC_DISABLED;
777badbabf97ea50949b9e46951163ea9fdd10e8Matthew Ahrens
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens mutex_enter(&zfsvfs->z_os->os_user_ptr_lock);
777badbabf97ea50949b9e46951163ea9fdd10e8Matthew Ahrens dmu_objset_set_user(zfsvfs->z_os, zfsvfs);
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens mutex_exit(&zfsvfs->z_os->os_user_ptr_lock);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
f18faf3f3e5def85fdfff681617d227703ace2adek error = zfsvfs_setup(zfsvfs, B_TRUE);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (!zfsvfs->z_issnap)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfsctl_create(zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockout:
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (error) {
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens dmu_objset_disown(zfsvfs->z_os, zfsvfs);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfsvfs_free(zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else {
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&zfs_active_fs_count);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (error);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockvoid
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockzfs_unregister_callbacks(zfsvfs_t *zfsvfs)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock objset_t *os = zfsvfs->z_os;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
03bad06fbb261fd4a7151a70dfeff2f5041cce1fJustin Gibbs if (!dmu_objset_is_snapshot(os))
03bad06fbb261fd4a7151a70dfeff2f5041cce1fJustin Gibbs dsl_prop_unregister_all(dmu_objset_ds(os), zfsvfs);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b1b8ab34de515a5e83206da22c3d7e563241b021lling/*
b1b8ab34de515a5e83206da22c3d7e563241b021lling * Convert a decimal digit string to a uint64_t integer.
b1b8ab34de515a5e83206da22c3d7e563241b021lling */
b1b8ab34de515a5e83206da22c3d7e563241b021llingstatic int
b1b8ab34de515a5e83206da22c3d7e563241b021llingstr_to_uint64(char *str, uint64_t *objnum)
b1b8ab34de515a5e83206da22c3d7e563241b021lling{
b1b8ab34de515a5e83206da22c3d7e563241b021lling uint64_t num = 0;
b1b8ab34de515a5e83206da22c3d7e563241b021lling
b1b8ab34de515a5e83206da22c3d7e563241b021lling while (*str) {
b1b8ab34de515a5e83206da22c3d7e563241b021lling if (*str < '0' || *str > '9')
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EINVAL));
b1b8ab34de515a5e83206da22c3d7e563241b021lling
b1b8ab34de515a5e83206da22c3d7e563241b021lling num = num*10 + *str++ - '0';
b1b8ab34de515a5e83206da22c3d7e563241b021lling }
b1b8ab34de515a5e83206da22c3d7e563241b021lling
b1b8ab34de515a5e83206da22c3d7e563241b021lling *objnum = num;
b1b8ab34de515a5e83206da22c3d7e563241b021lling return (0);
b1b8ab34de515a5e83206da22c3d7e563241b021lling}
b1b8ab34de515a5e83206da22c3d7e563241b021lling
b1b8ab34de515a5e83206da22c3d7e563241b021lling/*
b1b8ab34de515a5e83206da22c3d7e563241b021lling * The boot path passed from the boot loader is in the form of
b1b8ab34de515a5e83206da22c3d7e563241b021lling * "rootpool-name/root-filesystem-object-number'. Convert this
b1b8ab34de515a5e83206da22c3d7e563241b021lling * string to a dataset name: "rootpool-name/root-filesystem-name".
b1b8ab34de515a5e83206da22c3d7e563241b021lling */
b1b8ab34de515a5e83206da22c3d7e563241b021llingstatic int
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gwzfs_parse_bootfs(char *bpath, char *outpath)
b1b8ab34de515a5e83206da22c3d7e563241b021lling{
b1b8ab34de515a5e83206da22c3d7e563241b021lling char *slashp;
b1b8ab34de515a5e83206da22c3d7e563241b021lling uint64_t objnum;
b1b8ab34de515a5e83206da22c3d7e563241b021lling int error;
b1b8ab34de515a5e83206da22c3d7e563241b021lling
b1b8ab34de515a5e83206da22c3d7e563241b021lling if (*bpath == 0 || *bpath == '/')
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EINVAL));
b1b8ab34de515a5e83206da22c3d7e563241b021lling
193974072f41a843678abf5f61979c748687e66bSherry Moore (void) strcpy(outpath, bpath);
193974072f41a843678abf5f61979c748687e66bSherry Moore
b1b8ab34de515a5e83206da22c3d7e563241b021lling slashp = strchr(bpath, '/');
b1b8ab34de515a5e83206da22c3d7e563241b021lling
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* if no '/', just return the pool name */
b1b8ab34de515a5e83206da22c3d7e563241b021lling if (slashp == NULL) {
b1b8ab34de515a5e83206da22c3d7e563241b021lling return (0);
b1b8ab34de515a5e83206da22c3d7e563241b021lling }
b1b8ab34de515a5e83206da22c3d7e563241b021lling
193974072f41a843678abf5f61979c748687e66bSherry Moore /* if not a number, just return the root dataset name */
193974072f41a843678abf5f61979c748687e66bSherry Moore if (str_to_uint64(slashp+1, &objnum)) {
193974072f41a843678abf5f61979c748687e66bSherry Moore return (0);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
b1b8ab34de515a5e83206da22c3d7e563241b021lling
b1b8ab34de515a5e83206da22c3d7e563241b021lling *slashp = '\0';
b1b8ab34de515a5e83206da22c3d7e563241b021lling error = dsl_dsobj_to_dsname(bpath, objnum, outpath);
b1b8ab34de515a5e83206da22c3d7e563241b021lling *slashp = '/';
b1b8ab34de515a5e83206da22c3d7e563241b021lling
b1b8ab34de515a5e83206da22c3d7e563241b021lling return (error);
b1b8ab34de515a5e83206da22c3d7e563241b021lling}
b1b8ab34de515a5e83206da22c3d7e563241b021lling
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire/*
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * Check that the hex label string is appropriate for the dataset being
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * mounted into the global_zone proper.
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire *
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * Return an error if the hex label string is not default or
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * admin_low/admin_high. For admin_low labels, the corresponding
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * dataset must be readonly.
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire */
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshireint
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshirezfs_check_global_label(const char *dsname, const char *hexsl)
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire{
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (strcasecmp(hexsl, ZFS_MLSLABEL_DEFAULT) == 0)
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire return (0);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (strcasecmp(hexsl, ADMIN_HIGH) == 0)
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire return (0);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (strcasecmp(hexsl, ADMIN_LOW) == 0) {
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire /* must be readonly */
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire uint64_t rdonly;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (dsl_prop_get_integer(dsname,
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire zfs_prop_to_name(ZFS_PROP_READONLY), &rdonly, NULL))
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EACCES));
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire return (rdonly ? 0 : EACCES);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire }
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EACCES));
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire}
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire/*
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * Determine whether the mount is allowed according to MAC check.
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * by comparing (where appropriate) label of the dataset against
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * the label of the zone being mounted into. If the dataset has
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * no label, create one.
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire *
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * Returns 0 if access allowed, error otherwise (e.g. EACCES)
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire */
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshirestatic int
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshirezfs_mount_label_policy(vfs_t *vfsp, char *osname)
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire{
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire int error, retv;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire zone_t *mntzone = NULL;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire ts_label_t *mnt_tsl;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire bslabel_t *mnt_sl;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire bslabel_t ds_sl;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire char ds_hexsl[MAXNAMELEN];
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire retv = EACCES; /* assume the worst */
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire /*
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * Start by getting the dataset label if it exists.
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire */
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire error = dsl_prop_get(osname, zfs_prop_to_name(ZFS_PROP_MLSLABEL),
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire 1, sizeof (ds_hexsl), &ds_hexsl, NULL);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (error)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EACCES));
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire /*
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * If labeling is NOT enabled, then disallow the mount of datasets
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * which have a non-default label already. No other label checks
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * are needed.
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire */
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (!is_system_labeled()) {
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0)
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire return (0);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EACCES));
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire }
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire /*
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * Get the label of the mountpoint. If mounting into the global
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * zone (i.e. mountpoint is not within an active zone and the
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * zoned property is off), the label must be default or
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * admin_low/admin_high only; no other checks are needed.
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire */
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire mntzone = zone_find_by_any_path(refstr_value(vfsp->vfs_mntpt), B_FALSE);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (mntzone->zone_id == GLOBAL_ZONEID) {
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire uint64_t zoned;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire zone_rele(mntzone);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (dsl_prop_get_integer(osname,
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire zfs_prop_to_name(ZFS_PROP_ZONED), &zoned, NULL))
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EACCES));
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (!zoned)
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire return (zfs_check_global_label(osname, ds_hexsl));
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire else
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire /*
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * This is the case of a zone dataset being mounted
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * initially, before the zone has been fully created;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * allow this mount into global zone.
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire */
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire return (0);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire }
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire mnt_tsl = mntzone->zone_slabel;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire ASSERT(mnt_tsl != NULL);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire label_hold(mnt_tsl);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire mnt_sl = label2bslabel(mnt_tsl);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0) {
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire /*
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * The dataset doesn't have a real label, so fabricate one.
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire */
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire char *str = NULL;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (l_to_str_internal(mnt_sl, &str) == 0 &&
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_prop_set_string(osname,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens zfs_prop_to_name(ZFS_PROP_MLSLABEL),
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens ZPROP_SRC_LOCAL, str) == 0)
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire retv = 0;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (str != NULL)
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire kmem_free(str, strlen(str) + 1);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire } else if (hexstr_to_label(ds_hexsl, &ds_sl) == 0) {
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire /*
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * Now compare labels to complete the MAC check. If the
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * labels are equal then allow access. If the mountpoint
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * label dominates the dataset label, allow readonly access.
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire * Otherwise, access is denied.
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire */
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (blequal(mnt_sl, &ds_sl))
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire retv = 0;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire else if (bldominates(mnt_sl, &ds_sl)) {
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire retv = 0;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire }
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire }
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire label_rele(mnt_tsl);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire zone_rele(mntzone);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire return (retv);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire}
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockzfs_mountroot(vfs_t *vfsp, enum whymountroot why)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock int error = 0;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock static int zfsrootdone = 0;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfsvfs_t *zfsvfs = NULL;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock znode_t *zp = NULL;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock vnode_t *vp = NULL;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw char *zfs_bootfs;
051aabe6136ff13e81542a427e9693ffe1503525taylor char *zfs_devid;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT(vfsp);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
b1b8ab34de515a5e83206da22c3d7e563241b021lling * The filesystem that we mount as root is defined in the
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw * boot property "zfs-bootfs" with a format of
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw * "poolname/root-dataset-objnum".
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (why == ROOT_INIT) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (zfsrootdone++)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EBUSY));
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw /*
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw * the process of doing a spa_load will require the
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw * clock to be set before we could (for example) do
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw * something better by looking at the timestamp on
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw * an uberblock, so just set it to -1.
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw */
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw clkset(-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
051aabe6136ff13e81542a427e9693ffe1503525taylor if ((zfs_bootfs = spa_get_bootprop("zfs-bootfs")) == NULL) {
051aabe6136ff13e81542a427e9693ffe1503525taylor cmn_err(CE_NOTE, "spa_get_bootfs: can not get "
051aabe6136ff13e81542a427e9693ffe1503525taylor "bootfs name");
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EINVAL));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
051aabe6136ff13e81542a427e9693ffe1503525taylor zfs_devid = spa_get_bootprop("diskdevid");
051aabe6136ff13e81542a427e9693ffe1503525taylor error = spa_import_rootpool(rootfs.bo_name, zfs_devid);
051aabe6136ff13e81542a427e9693ffe1503525taylor if (zfs_devid)
051aabe6136ff13e81542a427e9693ffe1503525taylor spa_free_bootprop(zfs_devid);
051aabe6136ff13e81542a427e9693ffe1503525taylor if (error) {
051aabe6136ff13e81542a427e9693ffe1503525taylor spa_free_bootprop(zfs_bootfs);
051aabe6136ff13e81542a427e9693ffe1503525taylor cmn_err(CE_NOTE, "spa_import_rootpool: error %d",
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw error);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw return (error);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (error = zfs_parse_bootfs(zfs_bootfs, rootfs.bo_name)) {
051aabe6136ff13e81542a427e9693ffe1503525taylor spa_free_bootprop(zfs_bootfs);
051aabe6136ff13e81542a427e9693ffe1503525taylor cmn_err(CE_NOTE, "zfs_parse_bootfs: error %d",
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw error);
b1b8ab34de515a5e83206da22c3d7e563241b021lling return (error);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
051aabe6136ff13e81542a427e9693ffe1503525taylor spa_free_bootprop(zfs_bootfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (error = vfs_lock(vfsp))
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
088f389458728c464569a5506b58070254fa4f7dahrens if (error = zfs_domount(vfsp, rootfs.bo_name)) {
051aabe6136ff13e81542a427e9693ffe1503525taylor cmn_err(CE_NOTE, "zfs_domount: error %d", error);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock goto out;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfsvfs = (zfsvfs_t *)vfsp->vfs_data;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT(zfsvfs);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (error = zfs_zget(zfsvfs, zfsvfs->z_root, &zp)) {
051aabe6136ff13e81542a427e9693ffe1503525taylor cmn_err(CE_NOTE, "zfs_zget: error %d", error);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock goto out;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock vp = ZTOV(zp);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_enter(&vp->v_lock);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock vp->v_flag |= VROOT;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_exit(&vp->v_lock);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock rootvp = vp;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
40d3dfe15f0068009eaddacc3ded2afa9c994fa0marks * Leave rootvp held. The root file system is never unmounted.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock vfs_add((struct vnode *)0, vfsp,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockout:
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock vfs_unlock(vfsp);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw return (error);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else if (why == ROOT_REMOUNT) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock readonly_changed_cb(vfsp->vfs_data, B_FALSE);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock vfsp->vfs_flag |= VFS_REMOUNT;
b510d37840323dfb912eab2c7f56325938ed47adlling
b510d37840323dfb912eab2c7f56325938ed47adlling /* refresh mount options */
b510d37840323dfb912eab2c7f56325938ed47adlling zfs_unregister_callbacks(vfsp->vfs_data);
b510d37840323dfb912eab2c7f56325938ed47adlling return (zfs_register_callbacks(vfsp));
b510d37840323dfb912eab2c7f56325938ed47adlling
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else if (why == ROOT_UNMOUNT) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfs_unregister_callbacks((zfsvfs_t *)vfsp->vfs_data);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) zfs_sync(vfsp, 0, 0);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (0);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * if "why" is equal to anything else other than ROOT_INIT,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * ROOT_REMOUNT, or ROOT_UNMOUNT, we do not support it.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ENOTSUP));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/*ARGSUSED*/
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockzfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock char *osname;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock pathname_t spn;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock int error = 0;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock uio_seg_t fromspace = (uap->flags & MS_SYSSPACE) ?
b1b8ab34de515a5e83206da22c3d7e563241b021lling UIO_SYSSPACE : UIO_USERSPACE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock int canwrite;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (mvp->v_type != VDIR)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ENOTDIR));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_enter(&mvp->v_lock);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if ((uap->flags & MS_REMOUNT) == 0 &&
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (uap->flags & MS_OVERLAY) == 0 &&
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_exit(&mvp->v_lock);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EBUSY));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_exit(&mvp->v_lock);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * ZFS does not support passing unparsed data in via MS_DATA.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Users should use the MS_OPTIONSTR interface; this means
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * that all option parsing is already done and the options struct
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * can be interrogated.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if ((uap->flags & MS_DATA) && uap->datalen > 0)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EINVAL));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Get the objset name (the "special" mount argument).
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (error = pn_get(uap->spec, fromspace, &spn))
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (error);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock osname = spn.pn_path;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Check for mount privilege?
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * If we don't have privilege then see if
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * we have local permission to allow it
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks error = secpolicy_fs_mount(cr, mvp, vfsp);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (error) {
98679b5614193e2e84c0b9fed6d7c0e92bc35509Mark Shellenbaum if (dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) == 0) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks vattr_t vattr;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Make sure user is the owner of the mount point
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * or has sufficient privileges.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks vattr.va_mask = AT_UID;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
98679b5614193e2e84c0b9fed6d7c0e92bc35509Mark Shellenbaum if (VOP_GETATTR(mvp, &vattr, 0, cr, NULL)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks goto out;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks if (secpolicy_vnode_owner(cr, vattr.va_uid) != 0 &&
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks VOP_ACCESS(mvp, VWRITE, 0, cr, NULL) != 0) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks goto out;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks secpolicy_fs_mount_clearopts(cr, vfsp);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks } else {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks goto out;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Refuse to mount a filesystem if we are in a local zone and the
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * dataset is not visible.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (!INGLOBALZONE(curproc) &&
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (!zone_dataset_visible(osname, &canwrite) || !canwrite)) {
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens error = SET_ERROR(EPERM);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock goto out;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire error = zfs_mount_label_policy(vfsp, osname);
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire if (error)
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire goto out;
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire
b510d37840323dfb912eab2c7f56325938ed47adlling /*
b510d37840323dfb912eab2c7f56325938ed47adlling * When doing a remount, we simply refresh our temporary properties
b510d37840323dfb912eab2c7f56325938ed47adlling * according to those options set in the current VFS options.
b510d37840323dfb912eab2c7f56325938ed47adlling */
b510d37840323dfb912eab2c7f56325938ed47adlling if (uap->flags & MS_REMOUNT) {
b510d37840323dfb912eab2c7f56325938ed47adlling /* refresh mount options */
b510d37840323dfb912eab2c7f56325938ed47adlling zfs_unregister_callbacks(vfsp->vfs_data);
b510d37840323dfb912eab2c7f56325938ed47adlling error = zfs_register_callbacks(vfsp);
b510d37840323dfb912eab2c7f56325938ed47adlling goto out;
b510d37840323dfb912eab2c7f56325938ed47adlling }
b510d37840323dfb912eab2c7f56325938ed47adlling
088f389458728c464569a5506b58070254fa4f7dahrens error = zfs_domount(vfsp, osname);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby /*
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby * Add an extra VFS_HOLD on our parent vfs so that it can't
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby * disappear due to a forced unmount.
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby */
984a131b733dcb12000748fcfcda5cac286ac00aChris Kirby if (error == 0 && ((zfsvfs_t *)vfsp->vfs_data)->z_issnap)
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby VFS_HOLD(mvp->v_vfsp);
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockout:
fa9e4066f08beec538e775443c5be79dd423fcabahrens pn_free(&spn);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = vfsp->vfs_data;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dev32_t d32;
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens uint64_t refdbytes, availbytes, usedobjs, availobjs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_ENTER(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens dmu_objset_space(zfsvfs->z_os,
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens &refdbytes, &availbytes, &usedobjs, &availobjs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The underlying storage pool actually uses multiple block sizes.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * We report the fragsize as the smallest block size we support,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and we report our blocksize as the filesystem's maximum blocksize.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens statp->f_frsize = 1UL << SPA_MINBLOCKSHIFT;
fa9e4066f08beec538e775443c5be79dd423fcabahrens statp->f_bsize = zfsvfs->z_max_blksz;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The following report "total" blocks of various kinds in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file system, but reported in terms of f_frsize - the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * "fragment" size.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens statp->f_blocks = (refdbytes + availbytes) >> SPA_MINBLOCKSHIFT;
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens statp->f_bfree = availbytes >> SPA_MINBLOCKSHIFT;
fa9e4066f08beec538e775443c5be79dd423fcabahrens statp->f_bavail = statp->f_bfree; /* no root reservation */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * statvfs() should really be called statufs(), because it assumes
fa9e4066f08beec538e775443c5be79dd423fcabahrens * static metadata. ZFS doesn't preallocate files, so the best
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we can do is report the max that could possibly fit in f_files,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and that minus the number actually used in f_ffree.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * For f_ffree, report the smaller of the number of object available
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and the number of blocks (each object will take at least a block).
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens statp->f_ffree = MIN(availobjs, statp->f_bfree);
fa9e4066f08beec538e775443c5be79dd423fcabahrens statp->f_favail = statp->f_ffree; /* no "root reservation" */
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens statp->f_files = statp->f_ffree + usedobjs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) cmpldev(&d32, vfsp->vfs_dev);
fa9e4066f08beec538e775443c5be79dd423fcabahrens statp->f_fsid = d32;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * We're a zfs filesystem.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strcpy(statp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
a5be7ebb94dde0271db3c498c22a4b6afdb72af3marks statp->f_flag = vf_to_stf(vfsp->vfs_flag);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens statp->f_namemax = MAXNAMELEN - 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * We have all of 32 characters to stuff a string here.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Is there anything useful we could/should provide?
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens bzero(statp->f_fstr, sizeof (statp->f_fstr));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_EXIT(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_root(vfs_t *vfsp, vnode_t **vpp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = vfsp->vfs_data;
fa9e4066f08beec538e775443c5be79dd423fcabahrens znode_t *rootzp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int error;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_ENTER(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (error == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *vpp = ZTOV(rootzp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_EXIT(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
f18faf3f3e5def85fdfff681617d227703ace2adek/*
f18faf3f3e5def85fdfff681617d227703ace2adek * Teardown the zfsvfs::z_os.
f18faf3f3e5def85fdfff681617d227703ace2adek *
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk * Note, if 'unmounting' is FALSE, we return with the 'z_teardown_lock'
f18faf3f3e5def85fdfff681617d227703ace2adek * and 'z_teardown_inactive_lock' held.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adekstatic int
f18faf3f3e5def85fdfff681617d227703ace2adekzfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
f18faf3f3e5def85fdfff681617d227703ace2adek{
874395d5f8cae2b9cd2d1fcbfcfe963a0c23966dmaybee znode_t *zp;
f18faf3f3e5def85fdfff681617d227703ace2adek
c9030f6c93613fe30ee0c16f92b96da7816ac052Alexander Motin rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG);
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek if (!unmounting) {
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * We purge the parent filesystem's vfsp as the parent
f18faf3f3e5def85fdfff681617d227703ace2adek * filesystem and all of its snapshots have their vnode's
f18faf3f3e5def85fdfff681617d227703ace2adek * v_vfsp set to the parent's filesystem's vfsp. Note,
f18faf3f3e5def85fdfff681617d227703ace2adek * 'z_parent' is self referential for non-snapshots.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adek (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0);
f18faf3f3e5def85fdfff681617d227703ace2adek }
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * Close the zil. NB: Can't close the zil while zfs_inactive
f18faf3f3e5def85fdfff681617d227703ace2adek * threads are blocked as zil_close can call zfs_inactive.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adek if (zfsvfs->z_log) {
f18faf3f3e5def85fdfff681617d227703ace2adek zil_close(zfsvfs->z_log);
f18faf3f3e5def85fdfff681617d227703ace2adek zfsvfs->z_log = NULL;
f18faf3f3e5def85fdfff681617d227703ace2adek }
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_WRITER);
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * If we are not unmounting (ie: online recv) and someone already
f18faf3f3e5def85fdfff681617d227703ace2adek * unmounted this file system while we were doing the switcheroo,
f18faf3f3e5def85fdfff681617d227703ace2adek * or a reopen of z_os failed then just bail out now.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adek if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) {
f18faf3f3e5def85fdfff681617d227703ace2adek rw_exit(&zfsvfs->z_teardown_inactive_lock);
c9030f6c93613fe30ee0c16f92b96da7816ac052Alexander Motin rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EIO));
f18faf3f3e5def85fdfff681617d227703ace2adek }
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * At this point there are no vops active, and any new vops will
f18faf3f3e5def85fdfff681617d227703ace2adek * fail with EIO since we have z_teardown_lock for writer (only
f18faf3f3e5def85fdfff681617d227703ace2adek * relavent for forced unmount).
f18faf3f3e5def85fdfff681617d227703ace2adek *
f18faf3f3e5def85fdfff681617d227703ace2adek * Release all holds on dbufs.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adek mutex_enter(&zfsvfs->z_znodes_lock);
874395d5f8cae2b9cd2d1fcbfcfe963a0c23966dmaybee for (zp = list_head(&zfsvfs->z_all_znodes); zp != NULL;
874395d5f8cae2b9cd2d1fcbfcfe963a0c23966dmaybee zp = list_next(&zfsvfs->z_all_znodes, zp))
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (zp->z_sa_hdl) {
874395d5f8cae2b9cd2d1fcbfcfe963a0c23966dmaybee ASSERT(ZTOV(zp)->v_count > 0);
874395d5f8cae2b9cd2d1fcbfcfe963a0c23966dmaybee zfs_znode_dmu_fini(zp);
f18faf3f3e5def85fdfff681617d227703ace2adek }
f18faf3f3e5def85fdfff681617d227703ace2adek mutex_exit(&zfsvfs->z_znodes_lock);
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * If we are unmounting, set the unmounted flag and let new vops
f18faf3f3e5def85fdfff681617d227703ace2adek * unblock. zfs_inactive will have the unmounted behavior, and all
f18faf3f3e5def85fdfff681617d227703ace2adek * other vops will fail with EIO.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adek if (unmounting) {
f18faf3f3e5def85fdfff681617d227703ace2adek zfsvfs->z_unmounted = B_TRUE;
f18faf3f3e5def85fdfff681617d227703ace2adek rw_exit(&zfsvfs->z_teardown_inactive_lock);
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
f18faf3f3e5def85fdfff681617d227703ace2adek }
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * z_os will be NULL if there was an error in attempting to reopen
f18faf3f3e5def85fdfff681617d227703ace2adek * zfsvfs, so just return as the properties had already been
f18faf3f3e5def85fdfff681617d227703ace2adek * unregistered and cached data had been evicted before.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adek if (zfsvfs->z_os == NULL)
f18faf3f3e5def85fdfff681617d227703ace2adek return (0);
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * Unregister properties.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adek zfs_unregister_callbacks(zfsvfs);
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * Evict cached data
f18faf3f3e5def85fdfff681617d227703ace2adek */
2e2c135528b3edfe9aaf67d1f004dc0202fa1a54Matthew Ahrens if (dsl_dataset_is_dirty(dmu_objset_ds(zfsvfs->z_os)) &&
2e2c135528b3edfe9aaf67d1f004dc0202fa1a54Matthew Ahrens !(zfsvfs->z_vfs->vfs_flag & VFS_RDONLY))
2e2c135528b3edfe9aaf67d1f004dc0202fa1a54Matthew Ahrens txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dmu_objset_evict_dbufs(zfsvfs->z_os);
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek return (0);
f18faf3f3e5def85fdfff681617d227703ace2adek}
f18faf3f3e5def85fdfff681617d227703ace2adek
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*ARGSUSED*/
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_umount(vfs_t *vfsp, int fflag, cred_t *cr)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = vfsp->vfs_data;
f18faf3f3e5def85fdfff681617d227703ace2adek objset_t *os;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ret = secpolicy_fs_unmount(cr, vfsp);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (ret) {
98679b5614193e2e84c0b9fed6d7c0e92bc35509Mark Shellenbaum if (dsl_deleg_access((char *)refstr_value(vfsp->vfs_resource),
98679b5614193e2e84c0b9fed6d7c0e92bc35509Mark Shellenbaum ZFS_DELEG_PERM_MOUNT, cr))
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (ret);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
033f983390fa5d2b54e3e09d83ac9000d71ddaaeek
ed097989586a51afeee476d7fbba56222d447ad8ek /*
ed097989586a51afeee476d7fbba56222d447ad8ek * We purge the parent filesystem's vfsp as the parent filesystem
ed097989586a51afeee476d7fbba56222d447ad8ek * and all of its snapshots have their vnode's v_vfsp set to the
ed097989586a51afeee476d7fbba56222d447ad8ek * parent's filesystem's vfsp. Note, 'z_parent' is self
ed097989586a51afeee476d7fbba56222d447ad8ek * referential for non-snapshots.
ed097989586a51afeee476d7fbba56222d447ad8ek */
ed097989586a51afeee476d7fbba56222d447ad8ek (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0);
033f983390fa5d2b54e3e09d83ac9000d71ddaaeek
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Unmount any snapshots mounted under .zfs before unmounting the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * dataset itself.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (zfsvfs->z_ctldir != NULL &&
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks (ret = zfsctl_umount_snapshots(vfsp, fflag, cr)) != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (ret);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (!(fflag & MS_FORCE)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens * Check the number of active vnodes in the file system.
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens * Our count is maintained in the vfs structure, but the
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens * number is off by 1 to indicate a hold on the vfs
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens * structure itself.
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens *
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens * The '.zfs' directory maintains a reference of its
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens * own, and any active references underneath are
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens * reflected in the vnode count.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (zfsvfs->z_ctldir == NULL) {
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (vfsp->vfs_count > 1)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EBUSY));
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens } else {
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (vfsp->vfs_count > 2 ||
f18faf3f3e5def85fdfff681617d227703ace2adek zfsvfs->z_ctldir->v_count > 1)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EBUSY));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens vfsp->vfs_flag |= VFS_UNMOUNTED;
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens
f18faf3f3e5def85fdfff681617d227703ace2adek VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0);
f18faf3f3e5def85fdfff681617d227703ace2adek os = zfsvfs->z_os;
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens /*
f18faf3f3e5def85fdfff681617d227703ace2adek * z_os will be NULL if there was an error in
f18faf3f3e5def85fdfff681617d227703ace2adek * attempting to reopen zfsvfs.
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens */
f18faf3f3e5def85fdfff681617d227703ace2adek if (os != NULL) {
f18faf3f3e5def85fdfff681617d227703ace2adek /*
f18faf3f3e5def85fdfff681617d227703ace2adek * Unset the objset user_ptr.
f18faf3f3e5def85fdfff681617d227703ace2adek */
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens mutex_enter(&os->os_user_ptr_lock);
f18faf3f3e5def85fdfff681617d227703ace2adek dmu_objset_set_user(os, NULL);
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens mutex_exit(&os->os_user_ptr_lock);
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens
f18faf3f3e5def85fdfff681617d227703ace2adek /*
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee * Finally release the objset
f18faf3f3e5def85fdfff681617d227703ace2adek */
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens dmu_objset_disown(os, zfsvfs);
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens }
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens /*
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens * We can now safely destroy the '.zfs' directory node.
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens */
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (zfsvfs->z_ctldir != NULL)
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens zfsctl_destroy(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = vfsp->vfs_data;
fa9e4066f08beec538e775443c5be79dd423fcabahrens znode_t *zp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t object = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t fid_gen = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t gen_mask;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t zp_gen;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i, err;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *vpp = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_ENTER(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (fidp->fid_len == LONG_FID_LEN) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfid_long_t *zlfid = (zfid_long_t *)fidp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t objsetid = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t setgen = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < sizeof (zlfid->zf_setid); i++)
fa9e4066f08beec538e775443c5be79dd423fcabahrens objsetid |= ((uint64_t)zlfid->zf_setid[i]) << (8 * i);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < sizeof (zlfid->zf_setgen); i++)
fa9e4066f08beec538e775443c5be79dd423fcabahrens setgen |= ((uint64_t)zlfid->zf_setgen[i]) << (8 * i);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_EXIT(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens err = zfsctl_lookup_objset(vfsp, objsetid, &zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (err)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EINVAL));
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_ENTER(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfid_short_t *zfid = (zfid_short_t *)fidp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < sizeof (zfid->zf_object); i++)
fa9e4066f08beec538e775443c5be79dd423fcabahrens object |= ((uint64_t)zfid->zf_object[i]) << (8 * i);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < sizeof (zfid->zf_gen); i++)
fa9e4066f08beec538e775443c5be79dd423fcabahrens fid_gen |= ((uint64_t)zfid->zf_gen[i]) << (8 * i);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_EXIT(zfsvfs);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EINVAL));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* A zero fid_gen means we are in the .zfs control directories */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (fid_gen == 0 &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *vpp = zfsvfs->z_ctldir;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(*vpp != NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (object == ZFSCTL_INO_SNAPDIR) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens VERIFY(zfsctl_root_lookup(*vpp, "snapshot", vpp, NULL,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 0, NULL, NULL, NULL, NULL, NULL) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens VN_HOLD(*vpp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_EXIT(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens gen_mask = -1ULL >> (64 - 8 * i);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (err = zfs_zget(zfsvfs, object, &zp)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_EXIT(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &zp_gen,
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum sizeof (uint64_t));
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum zp_gen = zp_gen & gen_mask;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (zp_gen == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens zp_gen = 1;
893a6d32980d24be1349478f44169009d4801c25ahrens if (zp->z_unlinked || zp_gen != fid_gen) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens dprintf("znode gen (%u) != fid gen (%u)\n", zp_gen, fid_gen);
fa9e4066f08beec538e775443c5be79dd423fcabahrens VN_RELE(ZTOV(zp));
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_EXIT(zfsvfs);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EINVAL));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *vpp = ZTOV(zp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ZFS_EXIT(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
f18faf3f3e5def85fdfff681617d227703ace2adek/*
f18faf3f3e5def85fdfff681617d227703ace2adek * Block out VOPs and close zfsvfs_t::z_os
f18faf3f3e5def85fdfff681617d227703ace2adek *
f18faf3f3e5def85fdfff681617d227703ace2adek * Note, if successful, then we return with the 'z_teardown_lock' and
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * 'z_teardown_inactive_lock' write held. We leave ownership of the underlying
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * dataset and objset intact so that they can be atomically handed off during
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * a subsequent rollback or recv operation and the resume thereafter.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adekint
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrenszfs_suspend_fs(zfsvfs_t *zfsvfs)
f18faf3f3e5def85fdfff681617d227703ace2adek{
f18faf3f3e5def85fdfff681617d227703ace2adek int error;
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek if ((error = zfsvfs_teardown(zfsvfs, B_FALSE)) != 0)
f18faf3f3e5def85fdfff681617d227703ace2adek return (error);
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek return (0);
f18faf3f3e5def85fdfff681617d227703ace2adek}
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek/*
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * Rebuild SA and release VOPs. Note that ownership of the underlying dataset
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * is an invariant across any of the operations that can be performed while the
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * filesystem was suspended. Whether it succeeded or failed, the preconditions
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * are the same: the relevant objset and associated dataset are owned by
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * zfsvfs, held, and long held on entry.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adekint
690041b9caf801816f2d0bac90bc7cecefb73523Andriy Gaponzfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
f18faf3f3e5def85fdfff681617d227703ace2adek{
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum int err;
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski znode_t *zp;
f18faf3f3e5def85fdfff681617d227703ace2adek
c9030f6c93613fe30ee0c16f92b96da7816ac052Alexander Motin ASSERT(RRM_WRITE_HELD(&zfsvfs->z_teardown_lock));
f18faf3f3e5def85fdfff681617d227703ace2adek ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock));
f18faf3f3e5def85fdfff681617d227703ace2adek
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski /*
690041b9caf801816f2d0bac90bc7cecefb73523Andriy Gapon * We already own this, so just update the objset_t, as the one we
690041b9caf801816f2d0bac90bc7cecefb73523Andriy Gapon * had before may have been evicted.
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski */
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens objset_t *os;
690041b9caf801816f2d0bac90bc7cecefb73523Andriy Gapon VERIFY3P(ds->ds_owner, ==, zfsvfs);
690041b9caf801816f2d0bac90bc7cecefb73523Andriy Gapon VERIFY(dsl_dataset_long_held(ds));
690041b9caf801816f2d0bac90bc7cecefb73523Andriy Gapon VERIFY0(dmu_objset_from_ds(ds, &os));
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens err = zfsvfs_init(zfsvfs, os);
1fdcbd00c9cbac286b5f92e08877e8cb3c448420Matthew Ahrens if (err != 0)
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski goto bail;
f18faf3f3e5def85fdfff681617d227703ace2adek
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski VERIFY(zfsvfs_setup(zfsvfs, B_FALSE) == 0);
f18faf3f3e5def85fdfff681617d227703ace2adek
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski zfs_set_fuid_feature(zfsvfs);
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski /*
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * Attempt to re-establish all the active znodes with
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * their dbufs. If a zfs_rezget() fails, then we'll let
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * any potential callers discover that via ZFS_ENTER_VERIFY_VP
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * when they try to use their znode.
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski */
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski mutex_enter(&zfsvfs->z_znodes_lock);
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski for (zp = list_head(&zfsvfs->z_all_znodes); zp;
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski zp = list_next(&zfsvfs->z_all_znodes, zp)) {
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski (void) zfs_rezget(zp);
f18faf3f3e5def85fdfff681617d227703ace2adek }
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski mutex_exit(&zfsvfs->z_znodes_lock);
f18faf3f3e5def85fdfff681617d227703ace2adek
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumbail:
f18faf3f3e5def85fdfff681617d227703ace2adek /* release the VOPs */
f18faf3f3e5def85fdfff681617d227703ace2adek rw_exit(&zfsvfs->z_teardown_inactive_lock);
c9030f6c93613fe30ee0c16f92b96da7816ac052Alexander Motin rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek if (err) {
f18faf3f3e5def85fdfff681617d227703ace2adek /*
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * Since we couldn't setup the sa framework, try to force
91948b51b8e978ddc88a36b2bc3ae83c20cdc9aaKeith M Wesolowski * unmount this file system.
f18faf3f3e5def85fdfff681617d227703ace2adek */
f18faf3f3e5def85fdfff681617d227703ace2adek if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0)
f18faf3f3e5def85fdfff681617d227703ace2adek (void) dounmount(zfsvfs->z_vfs, MS_FORCE, CRED());
f18faf3f3e5def85fdfff681617d227703ace2adek }
f18faf3f3e5def85fdfff681617d227703ace2adek return (err);
f18faf3f3e5def85fdfff681617d227703ace2adek}
f18faf3f3e5def85fdfff681617d227703ace2adek
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_freevfs(vfs_t *vfsp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsvfs_t *zfsvfs = vfsp->vfs_data;
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby /*
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby * If this is a snapshot, we have an extra VFS_HOLD on our parent
f80ce222af313ec87dc070b2219b29c81c5e5d8cChris Kirby * from zfs_mount(). Release it here. If we came through
f80ce222af313ec87dc070b2219b29c81c5e5d8cChris Kirby * zfs_mountroot() instead, we didn't grab an extra hold, so
f80ce222af313ec87dc070b2219b29c81c5e5d8cChris Kirby * skip the VFS_RELE for rootvfs.
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby */
f80ce222af313ec87dc070b2219b29c81c5e5d8cChris Kirby if (zfsvfs->z_issnap && (vfsp != rootvfs))
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby VFS_RELE(zfsvfs->z_parent->z_vfs);
142ae85d92129bf4eed1eb71b99a957379f6083aChris Kirby
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfsvfs_free(zfsvfs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_32(&zfs_active_fs_count);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * VFS_INIT() initialization. Note that there is no VFS_FINI(),
fa9e4066f08beec538e775443c5be79dd423fcabahrens * so we can't safely do any non-idempotent initialization here.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Leave that to zfs_init() and zfs_fini(), which are called
fa9e4066f08beec538e775443c5be79dd423fcabahrens * from the module's _init() and _fini() entry points.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*ARGSUSED*/
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_vfsinit(int fstype, char *name)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int error;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsfstype = fstype;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Setup vfsops and vnodeops tables.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens error = vfs_setfsops(fstype, zfs_vfsops_template, &zfs_vfsops);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (error != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens cmn_err(CE_WARN, "zfs: bad vfs ops template");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens error = zfs_create_op_tables();
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_remove_op_tables();
fa9e4066f08beec538e775443c5be79dd423fcabahrens cmn_err(CE_WARN, "zfs: bad vnode ops template");
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) vfs_freevfsops_by_type(zfsfstype);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_init(&zfs_dev_mtx, NULL, MUTEX_DEFAULT, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
a0965f35d4137b1f6bb1655ae1cb8fee88dfa66fbonwick * Unique major number for all zfs mounts.
a0965f35d4137b1f6bb1655ae1cb8fee88dfa66fbonwick * If we run out of 32-bit minors, we'll getudev() another major.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
a0965f35d4137b1f6bb1655ae1cb8fee88dfa66fbonwick zfs_major = ddi_name_to_major(ZFS_DRIVER);
a0965f35d4137b1f6bb1655ae1cb8fee88dfa66fbonwick zfs_minor = ZFS_MIN_MINOR;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_init(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Initialize .zfs directory structures
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsctl_init();
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Initialize znode cache, vnode ops, etc...
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_znode_init();
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_fini(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfsctl_fini();
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_znode_fini();
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrenszfs_busy(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (zfs_active_fs_count != 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e7437265dc2a4920c197ed4337665539d358b22cahrensint
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrenszfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers)
e7437265dc2a4920c197ed4337665539d358b22cahrens{
e7437265dc2a4920c197ed4337665539d358b22cahrens int error;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens objset_t *os = zfsvfs->z_os;
e7437265dc2a4920c197ed4337665539d358b22cahrens dmu_tx_t *tx;
e7437265dc2a4920c197ed4337665539d358b22cahrens
e7437265dc2a4920c197ed4337665539d358b22cahrens if (newvers < ZPL_VERSION_INITIAL || newvers > ZPL_VERSION)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EINVAL));
e7437265dc2a4920c197ed4337665539d358b22cahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (newvers < zfsvfs->z_version)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EINVAL));
e7437265dc2a4920c197ed4337665539d358b22cahrens
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (zfs_spa_version_map(newvers) >
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum spa_version(dmu_objset_spa(zfsvfs->z_os)))
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ENOTSUP));
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
e7437265dc2a4920c197ed4337665539d358b22cahrens tx = dmu_tx_create(os);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_FALSE, ZPL_VERSION_STR);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (newvers >= ZPL_VERSION_SA && !zfsvfs->z_use_sa) {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE,
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum ZFS_SA_ATTRS);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
e7437265dc2a4920c197ed4337665539d358b22cahrens error = dmu_tx_assign(tx, TXG_WAIT);
e7437265dc2a4920c197ed4337665539d358b22cahrens if (error) {
e7437265dc2a4920c197ed4337665539d358b22cahrens dmu_tx_abort(tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (error);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens error = zap_update(os, MASTER_NODE_OBJ, ZPL_VERSION_STR,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens 8, 1, &newvers, tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (error) {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens dmu_tx_commit(tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (error);
e7437265dc2a4920c197ed4337665539d358b22cahrens }
e7437265dc2a4920c197ed4337665539d358b22cahrens
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (newvers >= ZPL_VERSION_SA && !zfsvfs->z_use_sa) {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum uint64_t sa_obj;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum ASSERT3U(spa_version(dmu_objset_spa(zfsvfs->z_os)), >=,
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum SPA_VERSION_SA);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum sa_obj = zap_create(os, DMU_OT_SA_MASTER_NODE,
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum DMU_OT_NONE, 0, tx);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum error = zap_add(os, MASTER_NODE_OBJ,
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum ZFS_SA_ATTRS, 8, 1, &sa_obj, tx);
fb09f5aad449c97fe309678f3f604982b563a96fMadhav Suresh ASSERT0(error);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum VERIFY(0 == sa_set_sa_object(os, sa_obj));
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum sa_register_update_callback(os, zfs_sa_upgrade);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens spa_history_log_internal_ds(dmu_objset_ds(os), "upgrade", tx,
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens "from %llu to %llu", zfsvfs->z_version, newvers);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
e7437265dc2a4920c197ed4337665539d358b22cahrens dmu_tx_commit(tx);
e7437265dc2a4920c197ed4337665539d358b22cahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens zfsvfs->z_version = newvers;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
44bffe012cad6481c82ad67bacd6b40bd29def2bMark Shellenbaum zfs_set_fuid_feature(zfsvfs);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (0);
e7437265dc2a4920c197ed4337665539d358b22cahrens}
e7437265dc2a4920c197ed4337665539d358b22cahrens
de8267e0f723ed2c38ea9def92d465f69a300f56timh/*
de8267e0f723ed2c38ea9def92d465f69a300f56timh * Read a property stored within the master node.
de8267e0f723ed2c38ea9def92d465f69a300f56timh */
de8267e0f723ed2c38ea9def92d465f69a300f56timhint
de8267e0f723ed2c38ea9def92d465f69a300f56timhzfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
de8267e0f723ed2c38ea9def92d465f69a300f56timh{
de8267e0f723ed2c38ea9def92d465f69a300f56timh const char *pname;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh int error = ENOENT;
de8267e0f723ed2c38ea9def92d465f69a300f56timh
de8267e0f723ed2c38ea9def92d465f69a300f56timh /*
de8267e0f723ed2c38ea9def92d465f69a300f56timh * Look up the file system's value for the property. For the
de8267e0f723ed2c38ea9def92d465f69a300f56timh * version property, we look up a slightly different string.
de8267e0f723ed2c38ea9def92d465f69a300f56timh */
de8267e0f723ed2c38ea9def92d465f69a300f56timh if (prop == ZFS_PROP_VERSION)
de8267e0f723ed2c38ea9def92d465f69a300f56timh pname = ZPL_VERSION_STR;
de8267e0f723ed2c38ea9def92d465f69a300f56timh else
de8267e0f723ed2c38ea9def92d465f69a300f56timh pname = zfs_prop_to_name(prop);
de8267e0f723ed2c38ea9def92d465f69a300f56timh
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if (os != NULL)
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
de8267e0f723ed2c38ea9def92d465f69a300f56timh
aa60ed0e2b50d65074dae0e2a3996354449e1707maybee if (error == ENOENT) {
de8267e0f723ed2c38ea9def92d465f69a300f56timh /* No value set, use the default value */
de8267e0f723ed2c38ea9def92d465f69a300f56timh switch (prop) {
aa60ed0e2b50d65074dae0e2a3996354449e1707maybee case ZFS_PROP_VERSION:
aa60ed0e2b50d65074dae0e2a3996354449e1707maybee *value = ZPL_VERSION;
aa60ed0e2b50d65074dae0e2a3996354449e1707maybee break;
de8267e0f723ed2c38ea9def92d465f69a300f56timh case ZFS_PROP_NORMALIZE:
de8267e0f723ed2c38ea9def92d465f69a300f56timh case ZFS_PROP_UTF8ONLY:
de8267e0f723ed2c38ea9def92d465f69a300f56timh *value = 0;
de8267e0f723ed2c38ea9def92d465f69a300f56timh break;
de8267e0f723ed2c38ea9def92d465f69a300f56timh case ZFS_PROP_CASE:
de8267e0f723ed2c38ea9def92d465f69a300f56timh *value = ZFS_CASE_SENSITIVE;
de8267e0f723ed2c38ea9def92d465f69a300f56timh break;
de8267e0f723ed2c38ea9def92d465f69a300f56timh default:
aa60ed0e2b50d65074dae0e2a3996354449e1707maybee return (error);
de8267e0f723ed2c38ea9def92d465f69a300f56timh }
aa60ed0e2b50d65074dae0e2a3996354449e1707maybee error = 0;
de8267e0f723ed2c38ea9def92d465f69a300f56timh }
aa60ed0e2b50d65074dae0e2a3996354449e1707maybee return (error);
de8267e0f723ed2c38ea9def92d465f69a300f56timh}
de8267e0f723ed2c38ea9def92d465f69a300f56timh
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk/*
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk * Return true if the coresponding vfs's unmounted flag is set.
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk * Otherwise return false.
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk * If this function returns true we know VFS unmount has been initiated.
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk */
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchukboolean_t
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchukzfs_get_vfs_flag_unmounted(objset_t *os)
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk{
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk zfsvfs_t *zfvp;
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk boolean_t unmounted = B_FALSE;
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk ASSERT(dmu_objset_type(os) == DMU_OST_ZFS);
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk mutex_enter(&os->os_user_ptr_lock);
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk zfvp = dmu_objset_get_user(os);
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk if (zfvp != NULL && zfvp->z_vfs != NULL &&
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk (zfvp->z_vfs->vfs_flag & VFS_UNMOUNTED))
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk unmounted = B_TRUE;
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk mutex_exit(&os->os_user_ptr_lock);
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk return (unmounted);
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk}
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic vfsdef_t vfw = {
fa9e4066f08beec538e775443c5be79dd423fcabahrens VFSDEF_VERSION,
fa9e4066f08beec538e775443c5be79dd423fcabahrens MNTTYPE_ZFS,
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_vfsinit,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VSW_HASPROTO|VSW_CANRWRO|VSW_CANREMOUNT|VSW_VOLATILEDEV|VSW_STATS|
0fbb751d81ab0a7c7ddfd8d4e447e075a9f7024fJohn Levon VSW_XID|VSW_ZMOUNT,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &zfs_mntopts
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstruct modlfs zfs_modlfs = {
e7437265dc2a4920c197ed4337665539d358b22cahrens &mod_fsops, "ZFS filesystem version " SPA_VERSION_STRING, &vfw
fa9e4066f08beec538e775443c5be79dd423fcabahrens};