1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy /* 22eda14cbcSMatt Macy * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23eda14cbcSMatt Macy * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>. 24eda14cbcSMatt Macy * All rights reserved. 25eda14cbcSMatt Macy * Copyright (c) 2012, 2015 by Delphix. All rights reserved. 26eda14cbcSMatt Macy * Copyright (c) 2014 Integros [integros.com] 27eda14cbcSMatt Macy * Copyright 2016 Nexenta Systems, Inc. All rights reserved. 28eda14cbcSMatt Macy */ 29eda14cbcSMatt Macy 30eda14cbcSMatt Macy /* Portions Copyright 2010 Robert Milkowski */ 31eda14cbcSMatt Macy 32eda14cbcSMatt Macy #include <sys/types.h> 33eda14cbcSMatt Macy #include <sys/param.h> 34eda14cbcSMatt Macy #include <sys/systm.h> 35eda14cbcSMatt Macy #include <sys/kernel.h> 36eda14cbcSMatt Macy #include <sys/sysmacros.h> 37eda14cbcSMatt Macy #include <sys/kmem.h> 38eda14cbcSMatt Macy #include <sys/acl.h> 39eda14cbcSMatt Macy #include <sys/vnode.h> 40eda14cbcSMatt Macy #include <sys/vfs.h> 41eda14cbcSMatt Macy #include <sys/mntent.h> 42eda14cbcSMatt Macy #include <sys/mount.h> 43eda14cbcSMatt Macy #include <sys/cmn_err.h> 44eda14cbcSMatt Macy #include <sys/zfs_znode.h> 457877fdebSMatt Macy #include <sys/zfs_vnops.h> 46eda14cbcSMatt Macy #include <sys/zfs_dir.h> 47eda14cbcSMatt Macy #include <sys/zil.h> 48eda14cbcSMatt Macy #include <sys/fs/zfs.h> 49eda14cbcSMatt Macy #include <sys/dmu.h> 50eda14cbcSMatt Macy #include <sys/dsl_prop.h> 51eda14cbcSMatt Macy #include <sys/dsl_dataset.h> 52eda14cbcSMatt Macy #include <sys/dsl_deleg.h> 53eda14cbcSMatt Macy #include <sys/spa.h> 54eda14cbcSMatt Macy #include <sys/zap.h> 55eda14cbcSMatt Macy #include <sys/sa.h> 56eda14cbcSMatt Macy #include <sys/sa_impl.h> 57eda14cbcSMatt Macy #include <sys/policy.h> 58eda14cbcSMatt Macy #include <sys/atomic.h> 59eda14cbcSMatt Macy #include <sys/zfs_ioctl.h> 60eda14cbcSMatt Macy #include <sys/zfs_ctldir.h> 61eda14cbcSMatt Macy #include <sys/zfs_fuid.h> 62eda14cbcSMatt Macy #include <sys/sunddi.h> 63eda14cbcSMatt Macy #include <sys/dmu_objset.h> 64eda14cbcSMatt Macy #include <sys/dsl_dir.h> 65eda14cbcSMatt Macy #include <sys/jail.h> 66dbd5678dSMartin Matuska #include <sys/osd.h> 67eda14cbcSMatt Macy #include <ufs/ufs/quota.h> 68eda14cbcSMatt Macy #include <sys/zfs_quota.h> 69eda14cbcSMatt Macy 70eda14cbcSMatt Macy #include "zfs_comutil.h" 71eda14cbcSMatt Macy 72eda14cbcSMatt Macy #ifndef MNTK_VMSETSIZE_BUG 73eda14cbcSMatt Macy #define MNTK_VMSETSIZE_BUG 0 74eda14cbcSMatt Macy #endif 75eda14cbcSMatt Macy #ifndef MNTK_NOMSYNC 76eda14cbcSMatt Macy #define MNTK_NOMSYNC 8 77eda14cbcSMatt Macy #endif 78eda14cbcSMatt Macy 79eda14cbcSMatt Macy struct mtx zfs_debug_mtx; 80eda14cbcSMatt Macy MTX_SYSINIT(zfs_debug_mtx, &zfs_debug_mtx, "zfs_debug", MTX_DEF); 81eda14cbcSMatt Macy 82eda14cbcSMatt Macy SYSCTL_NODE(_vfs, OID_AUTO, zfs, CTLFLAG_RW, 0, "ZFS file system"); 83eda14cbcSMatt Macy 84eda14cbcSMatt Macy int zfs_super_owner; 85eda14cbcSMatt Macy SYSCTL_INT(_vfs_zfs, OID_AUTO, super_owner, CTLFLAG_RW, &zfs_super_owner, 0, 86c03c5b1cSMartin Matuska "File system owners can perform privileged operation on file systems"); 87eda14cbcSMatt Macy 88eda14cbcSMatt Macy int zfs_debug_level; 89eda14cbcSMatt Macy SYSCTL_INT(_vfs_zfs, OID_AUTO, debug, CTLFLAG_RWTUN, &zfs_debug_level, 0, 90eda14cbcSMatt Macy "Debug level"); 91eda14cbcSMatt Macy 92dbd5678dSMartin Matuska struct zfs_jailparam { 93dbd5678dSMartin Matuska int mount_snapshot; 94dbd5678dSMartin Matuska }; 95dbd5678dSMartin Matuska 96dbd5678dSMartin Matuska static struct zfs_jailparam zfs_jailparam0 = { 97dbd5678dSMartin Matuska .mount_snapshot = 0, 98dbd5678dSMartin Matuska }; 99dbd5678dSMartin Matuska 100dbd5678dSMartin Matuska static int zfs_jailparam_slot; 101dbd5678dSMartin Matuska 102dbd5678dSMartin Matuska SYSCTL_JAIL_PARAM_SYS_NODE(zfs, CTLFLAG_RW, "Jail ZFS parameters"); 103ae1a0648SJamie Gritton SYSCTL_JAIL_PARAM(_zfs, mount_snapshot, CTLTYPE_INT | CTLFLAG_RW, "I", 104dbd5678dSMartin Matuska "Allow mounting snapshots in the .zfs directory for unjailed datasets"); 105dbd5678dSMartin Matuska 106eda14cbcSMatt Macy SYSCTL_NODE(_vfs_zfs, OID_AUTO, version, CTLFLAG_RD, 0, "ZFS versions"); 107eda14cbcSMatt Macy static int zfs_version_acl = ZFS_ACL_VERSION; 108eda14cbcSMatt Macy SYSCTL_INT(_vfs_zfs_version, OID_AUTO, acl, CTLFLAG_RD, &zfs_version_acl, 0, 109eda14cbcSMatt Macy "ZFS_ACL_VERSION"); 110eda14cbcSMatt Macy static int zfs_version_spa = SPA_VERSION; 111eda14cbcSMatt Macy SYSCTL_INT(_vfs_zfs_version, OID_AUTO, spa, CTLFLAG_RD, &zfs_version_spa, 0, 112eda14cbcSMatt Macy "SPA_VERSION"); 113eda14cbcSMatt Macy static int zfs_version_zpl = ZPL_VERSION; 114eda14cbcSMatt Macy SYSCTL_INT(_vfs_zfs_version, OID_AUTO, zpl, CTLFLAG_RD, &zfs_version_zpl, 0, 115eda14cbcSMatt Macy "ZPL_VERSION"); 116eda14cbcSMatt Macy 117a4b07a27SJason A. Harmening #if __FreeBSD_version >= 1400018 118a4b07a27SJason A. Harmening static int zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg, 119a4b07a27SJason A. Harmening bool *mp_busy); 120a4b07a27SJason A. Harmening #else 121eda14cbcSMatt Macy static int zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg); 122a4b07a27SJason A. Harmening #endif 123eda14cbcSMatt Macy static int zfs_mount(vfs_t *vfsp); 124eda14cbcSMatt Macy static int zfs_umount(vfs_t *vfsp, int fflag); 125eda14cbcSMatt Macy static int zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp); 126eda14cbcSMatt Macy static int zfs_statfs(vfs_t *vfsp, struct statfs *statp); 127eda14cbcSMatt Macy static int zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp); 128eda14cbcSMatt Macy static int zfs_sync(vfs_t *vfsp, int waitfor); 129eda14cbcSMatt Macy static int zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, uint64_t *extflagsp, 130eda14cbcSMatt Macy struct ucred **credanonp, int *numsecflavors, int *secflavors); 131eda14cbcSMatt Macy static int zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp); 132eda14cbcSMatt Macy static void zfs_freevfs(vfs_t *vfsp); 133eda14cbcSMatt Macy 134eda14cbcSMatt Macy struct vfsops zfs_vfsops = { 135eda14cbcSMatt Macy .vfs_mount = zfs_mount, 136eda14cbcSMatt Macy .vfs_unmount = zfs_umount, 137eda14cbcSMatt Macy .vfs_root = vfs_cache_root, 138eda14cbcSMatt Macy .vfs_cachedroot = zfs_root, 139eda14cbcSMatt Macy .vfs_statfs = zfs_statfs, 140eda14cbcSMatt Macy .vfs_vget = zfs_vget, 141eda14cbcSMatt Macy .vfs_sync = zfs_sync, 142eda14cbcSMatt Macy .vfs_checkexp = zfs_checkexp, 143eda14cbcSMatt Macy .vfs_fhtovp = zfs_fhtovp, 144eda14cbcSMatt Macy .vfs_quotactl = zfs_quotactl, 145eda14cbcSMatt Macy }; 146eda14cbcSMatt Macy 147*c6767dc1SMartin Matuska VFS_SET(zfs_vfsops, zfs, VFCF_DELEGADMIN | VFCF_JAIL 1482a58b312SMartin Matuska #ifdef VFCF_CROSS_COPY_FILE_RANGE 149*c6767dc1SMartin Matuska | VFCF_CROSS_COPY_FILE_RANGE 1502a58b312SMartin Matuska #endif 151*c6767dc1SMartin Matuska #ifdef VFCF_FILEREVINC 152*c6767dc1SMartin Matuska | VFCF_FILEREVINC 153*c6767dc1SMartin Matuska #endif 154*c6767dc1SMartin Matuska ); 155eda14cbcSMatt Macy 156eda14cbcSMatt Macy /* 157eda14cbcSMatt Macy * We need to keep a count of active fs's. 158eda14cbcSMatt Macy * This is necessary to prevent our module 159eda14cbcSMatt Macy * from being unloaded after a umount -f 160eda14cbcSMatt Macy */ 161eda14cbcSMatt Macy static uint32_t zfs_active_fs_count = 0; 162eda14cbcSMatt Macy 163eda14cbcSMatt Macy int 164eda14cbcSMatt Macy zfs_get_temporary_prop(dsl_dataset_t *ds, zfs_prop_t zfs_prop, uint64_t *val, 165eda14cbcSMatt Macy char *setpoint) 166eda14cbcSMatt Macy { 167eda14cbcSMatt Macy int error; 168eda14cbcSMatt Macy zfsvfs_t *zfvp; 169eda14cbcSMatt Macy vfs_t *vfsp; 170eda14cbcSMatt Macy objset_t *os; 171eda14cbcSMatt Macy uint64_t tmp = *val; 172eda14cbcSMatt Macy 173eda14cbcSMatt Macy error = dmu_objset_from_ds(ds, &os); 174eda14cbcSMatt Macy if (error != 0) 175eda14cbcSMatt Macy return (error); 176eda14cbcSMatt Macy 177eda14cbcSMatt Macy error = getzfsvfs_impl(os, &zfvp); 178eda14cbcSMatt Macy if (error != 0) 179eda14cbcSMatt Macy return (error); 180eda14cbcSMatt Macy if (zfvp == NULL) 181eda14cbcSMatt Macy return (ENOENT); 182eda14cbcSMatt Macy vfsp = zfvp->z_vfs; 183eda14cbcSMatt Macy switch (zfs_prop) { 184eda14cbcSMatt Macy case ZFS_PROP_ATIME: 185eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) 186eda14cbcSMatt Macy tmp = 0; 187eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_ATIME, NULL)) 188eda14cbcSMatt Macy tmp = 1; 189eda14cbcSMatt Macy break; 190eda14cbcSMatt Macy case ZFS_PROP_DEVICES: 191eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL)) 192eda14cbcSMatt Macy tmp = 0; 193eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_DEVICES, NULL)) 194eda14cbcSMatt Macy tmp = 1; 195eda14cbcSMatt Macy break; 196eda14cbcSMatt Macy case ZFS_PROP_EXEC: 197eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) 198eda14cbcSMatt Macy tmp = 0; 199eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_EXEC, NULL)) 200eda14cbcSMatt Macy tmp = 1; 201eda14cbcSMatt Macy break; 202eda14cbcSMatt Macy case ZFS_PROP_SETUID: 203eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) 204eda14cbcSMatt Macy tmp = 0; 205eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_SETUID, NULL)) 206eda14cbcSMatt Macy tmp = 1; 207eda14cbcSMatt Macy break; 208eda14cbcSMatt Macy case ZFS_PROP_READONLY: 209eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_RW, NULL)) 210eda14cbcSMatt Macy tmp = 0; 211eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_RO, NULL)) 212eda14cbcSMatt Macy tmp = 1; 213eda14cbcSMatt Macy break; 214eda14cbcSMatt Macy case ZFS_PROP_XATTR: 215eda14cbcSMatt Macy if (zfvp->z_flags & ZSB_XATTR) 216eda14cbcSMatt Macy tmp = zfvp->z_xattr; 217eda14cbcSMatt Macy break; 218eda14cbcSMatt Macy case ZFS_PROP_NBMAND: 219eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NONBMAND, NULL)) 220eda14cbcSMatt Macy tmp = 0; 221eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) 222eda14cbcSMatt Macy tmp = 1; 223eda14cbcSMatt Macy break; 224eda14cbcSMatt Macy default: 225eda14cbcSMatt Macy vfs_unbusy(vfsp); 226eda14cbcSMatt Macy return (ENOENT); 227eda14cbcSMatt Macy } 228eda14cbcSMatt Macy 229eda14cbcSMatt Macy vfs_unbusy(vfsp); 230eda14cbcSMatt Macy if (tmp != *val) { 231c9539b89SMartin Matuska if (setpoint) 232eda14cbcSMatt Macy (void) strcpy(setpoint, "temporary"); 233eda14cbcSMatt Macy *val = tmp; 234eda14cbcSMatt Macy } 235eda14cbcSMatt Macy return (0); 236eda14cbcSMatt Macy } 237eda14cbcSMatt Macy 238eda14cbcSMatt Macy static int 239eda14cbcSMatt Macy zfs_getquota(zfsvfs_t *zfsvfs, uid_t id, int isgroup, struct dqblk64 *dqp) 240eda14cbcSMatt Macy { 241eda14cbcSMatt Macy int error = 0; 242eda14cbcSMatt Macy char buf[32]; 243eda14cbcSMatt Macy uint64_t usedobj, quotaobj; 244eda14cbcSMatt Macy uint64_t quota, used = 0; 245eda14cbcSMatt Macy timespec_t now; 246eda14cbcSMatt Macy 247eda14cbcSMatt Macy usedobj = isgroup ? DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT; 248eda14cbcSMatt Macy quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj; 249eda14cbcSMatt Macy 250eda14cbcSMatt Macy if (quotaobj == 0 || zfsvfs->z_replay) { 251eda14cbcSMatt Macy error = ENOENT; 252eda14cbcSMatt Macy goto done; 253eda14cbcSMatt Macy } 254eda14cbcSMatt Macy (void) sprintf(buf, "%llx", (longlong_t)id); 255eda14cbcSMatt Macy if ((error = zap_lookup(zfsvfs->z_os, quotaobj, 256eda14cbcSMatt Macy buf, sizeof (quota), 1, "a)) != 0) { 257eda14cbcSMatt Macy dprintf("%s(%d): quotaobj lookup failed\n", 258eda14cbcSMatt Macy __FUNCTION__, __LINE__); 259eda14cbcSMatt Macy goto done; 260eda14cbcSMatt Macy } 261eda14cbcSMatt Macy /* 262eda14cbcSMatt Macy * quota(8) uses bsoftlimit as "quoota", and hardlimit as "limit". 263eda14cbcSMatt Macy * So we set them to be the same. 264eda14cbcSMatt Macy */ 265eda14cbcSMatt Macy dqp->dqb_bsoftlimit = dqp->dqb_bhardlimit = btodb(quota); 266eda14cbcSMatt Macy error = zap_lookup(zfsvfs->z_os, usedobj, buf, sizeof (used), 1, &used); 267eda14cbcSMatt Macy if (error && error != ENOENT) { 268eda14cbcSMatt Macy dprintf("%s(%d): usedobj failed; %d\n", 269eda14cbcSMatt Macy __FUNCTION__, __LINE__, error); 270eda14cbcSMatt Macy goto done; 271eda14cbcSMatt Macy } 272eda14cbcSMatt Macy dqp->dqb_curblocks = btodb(used); 273eda14cbcSMatt Macy dqp->dqb_ihardlimit = dqp->dqb_isoftlimit = 0; 274eda14cbcSMatt Macy vfs_timestamp(&now); 275eda14cbcSMatt Macy /* 276eda14cbcSMatt Macy * Setting this to 0 causes FreeBSD quota(8) to print 277eda14cbcSMatt Macy * the number of days since the epoch, which isn't 278eda14cbcSMatt Macy * particularly useful. 279eda14cbcSMatt Macy */ 280eda14cbcSMatt Macy dqp->dqb_btime = dqp->dqb_itime = now.tv_sec; 281eda14cbcSMatt Macy done: 282eda14cbcSMatt Macy return (error); 283eda14cbcSMatt Macy } 284eda14cbcSMatt Macy 285eda14cbcSMatt Macy static int 286a4b07a27SJason A. Harmening #if __FreeBSD_version >= 1400018 287a4b07a27SJason A. Harmening zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg, bool *mp_busy) 288a4b07a27SJason A. Harmening #else 289eda14cbcSMatt Macy zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg) 290a4b07a27SJason A. Harmening #endif 291eda14cbcSMatt Macy { 292eda14cbcSMatt Macy zfsvfs_t *zfsvfs = vfsp->vfs_data; 293eda14cbcSMatt Macy struct thread *td; 294eda14cbcSMatt Macy int cmd, type, error = 0; 295eda14cbcSMatt Macy int bitsize; 296eda14cbcSMatt Macy zfs_userquota_prop_t quota_type; 297eda14cbcSMatt Macy struct dqblk64 dqblk = { 0 }; 298eda14cbcSMatt Macy 299eda14cbcSMatt Macy td = curthread; 300eda14cbcSMatt Macy cmd = cmds >> SUBCMDSHIFT; 301eda14cbcSMatt Macy type = cmds & SUBCMDMASK; 302eda14cbcSMatt Macy 303c7046f76SMartin Matuska if ((error = zfs_enter(zfsvfs, FTAG)) != 0) 304c7046f76SMartin Matuska return (error); 305eda14cbcSMatt Macy if (id == -1) { 306eda14cbcSMatt Macy switch (type) { 307eda14cbcSMatt Macy case USRQUOTA: 308eda14cbcSMatt Macy id = td->td_ucred->cr_ruid; 309eda14cbcSMatt Macy break; 310eda14cbcSMatt Macy case GRPQUOTA: 311eda14cbcSMatt Macy id = td->td_ucred->cr_rgid; 312eda14cbcSMatt Macy break; 313eda14cbcSMatt Macy default: 314eda14cbcSMatt Macy error = EINVAL; 315a4b07a27SJason A. Harmening #if __FreeBSD_version < 1400018 316eda14cbcSMatt Macy if (cmd == Q_QUOTAON || cmd == Q_QUOTAOFF) 317eda14cbcSMatt Macy vfs_unbusy(vfsp); 318a4b07a27SJason A. Harmening #endif 319eda14cbcSMatt Macy goto done; 320eda14cbcSMatt Macy } 321eda14cbcSMatt Macy } 322eda14cbcSMatt Macy /* 323eda14cbcSMatt Macy * Map BSD type to: 324eda14cbcSMatt Macy * ZFS_PROP_USERUSED, 325eda14cbcSMatt Macy * ZFS_PROP_USERQUOTA, 326eda14cbcSMatt Macy * ZFS_PROP_GROUPUSED, 327eda14cbcSMatt Macy * ZFS_PROP_GROUPQUOTA 328eda14cbcSMatt Macy */ 329eda14cbcSMatt Macy switch (cmd) { 330eda14cbcSMatt Macy case Q_SETQUOTA: 331eda14cbcSMatt Macy case Q_SETQUOTA32: 332eda14cbcSMatt Macy if (type == USRQUOTA) 333eda14cbcSMatt Macy quota_type = ZFS_PROP_USERQUOTA; 334eda14cbcSMatt Macy else if (type == GRPQUOTA) 335eda14cbcSMatt Macy quota_type = ZFS_PROP_GROUPQUOTA; 336eda14cbcSMatt Macy else 337eda14cbcSMatt Macy error = EINVAL; 338eda14cbcSMatt Macy break; 339eda14cbcSMatt Macy case Q_GETQUOTA: 340eda14cbcSMatt Macy case Q_GETQUOTA32: 341eda14cbcSMatt Macy if (type == USRQUOTA) 342eda14cbcSMatt Macy quota_type = ZFS_PROP_USERUSED; 343eda14cbcSMatt Macy else if (type == GRPQUOTA) 344eda14cbcSMatt Macy quota_type = ZFS_PROP_GROUPUSED; 345eda14cbcSMatt Macy else 346eda14cbcSMatt Macy error = EINVAL; 347eda14cbcSMatt Macy break; 348eda14cbcSMatt Macy } 349eda14cbcSMatt Macy 350eda14cbcSMatt Macy /* 351eda14cbcSMatt Macy * Depending on the cmd, we may need to get 352eda14cbcSMatt Macy * the ruid and domain (see fuidstr_to_sid?), 353eda14cbcSMatt Macy * the fuid (how?), or other information. 354eda14cbcSMatt Macy * Create fuid using zfs_fuid_create(zfsvfs, id, 355eda14cbcSMatt Macy * ZFS_OWNER or ZFS_GROUP, cr, &fuidp)? 356eda14cbcSMatt Macy * I think I can use just the id? 357eda14cbcSMatt Macy * 358eda14cbcSMatt Macy * Look at zfs_id_overquota() to look up a quota. 359eda14cbcSMatt Macy * zap_lookup(something, quotaobj, fuidstring, 360eda14cbcSMatt Macy * sizeof (long long), 1, "a) 361eda14cbcSMatt Macy * 362eda14cbcSMatt Macy * See zfs_set_userquota() to set a quota. 363eda14cbcSMatt Macy */ 364eda14cbcSMatt Macy if ((uint32_t)type >= MAXQUOTAS) { 365eda14cbcSMatt Macy error = EINVAL; 366eda14cbcSMatt Macy goto done; 367eda14cbcSMatt Macy } 368eda14cbcSMatt Macy 369eda14cbcSMatt Macy switch (cmd) { 370eda14cbcSMatt Macy case Q_GETQUOTASIZE: 371eda14cbcSMatt Macy bitsize = 64; 372eda14cbcSMatt Macy error = copyout(&bitsize, arg, sizeof (int)); 373eda14cbcSMatt Macy break; 374eda14cbcSMatt Macy case Q_QUOTAON: 375eda14cbcSMatt Macy // As far as I can tell, you can't turn quotas on or off on zfs 376eda14cbcSMatt Macy error = 0; 377a4b07a27SJason A. Harmening #if __FreeBSD_version < 1400018 378eda14cbcSMatt Macy vfs_unbusy(vfsp); 379a4b07a27SJason A. Harmening #endif 380eda14cbcSMatt Macy break; 381eda14cbcSMatt Macy case Q_QUOTAOFF: 382eda14cbcSMatt Macy error = ENOTSUP; 383a4b07a27SJason A. Harmening #if __FreeBSD_version < 1400018 384eda14cbcSMatt Macy vfs_unbusy(vfsp); 385a4b07a27SJason A. Harmening #endif 386eda14cbcSMatt Macy break; 387eda14cbcSMatt Macy case Q_SETQUOTA: 388eda14cbcSMatt Macy error = copyin(arg, &dqblk, sizeof (dqblk)); 389eda14cbcSMatt Macy if (error == 0) 390eda14cbcSMatt Macy error = zfs_set_userquota(zfsvfs, quota_type, 391eda14cbcSMatt Macy "", id, dbtob(dqblk.dqb_bhardlimit)); 392eda14cbcSMatt Macy break; 393eda14cbcSMatt Macy case Q_GETQUOTA: 394eda14cbcSMatt Macy error = zfs_getquota(zfsvfs, id, type == GRPQUOTA, &dqblk); 395eda14cbcSMatt Macy if (error == 0) 396eda14cbcSMatt Macy error = copyout(&dqblk, arg, sizeof (dqblk)); 397eda14cbcSMatt Macy break; 398eda14cbcSMatt Macy default: 399eda14cbcSMatt Macy error = EINVAL; 400eda14cbcSMatt Macy break; 401eda14cbcSMatt Macy } 402eda14cbcSMatt Macy done: 403c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 404eda14cbcSMatt Macy return (error); 405eda14cbcSMatt Macy } 406eda14cbcSMatt Macy 407eda14cbcSMatt Macy 408eda14cbcSMatt Macy boolean_t 409eda14cbcSMatt Macy zfs_is_readonly(zfsvfs_t *zfsvfs) 410eda14cbcSMatt Macy { 411eda14cbcSMatt Macy return (!!(zfsvfs->z_vfs->vfs_flag & VFS_RDONLY)); 412eda14cbcSMatt Macy } 413eda14cbcSMatt Macy 414eda14cbcSMatt Macy static int 415eda14cbcSMatt Macy zfs_sync(vfs_t *vfsp, int waitfor) 416eda14cbcSMatt Macy { 417eda14cbcSMatt Macy 418eda14cbcSMatt Macy /* 419eda14cbcSMatt Macy * Data integrity is job one. We don't want a compromised kernel 420eda14cbcSMatt Macy * writing to the storage pool, so we never sync during panic. 421eda14cbcSMatt Macy */ 422eda14cbcSMatt Macy if (panicstr) 423eda14cbcSMatt Macy return (0); 424eda14cbcSMatt Macy 425eda14cbcSMatt Macy /* 426eda14cbcSMatt Macy * Ignore the system syncher. ZFS already commits async data 427eda14cbcSMatt Macy * at zfs_txg_timeout intervals. 428eda14cbcSMatt Macy */ 429eda14cbcSMatt Macy if (waitfor == MNT_LAZY) 430eda14cbcSMatt Macy return (0); 431eda14cbcSMatt Macy 432eda14cbcSMatt Macy if (vfsp != NULL) { 433eda14cbcSMatt Macy /* 434eda14cbcSMatt Macy * Sync a specific filesystem. 435eda14cbcSMatt Macy */ 436eda14cbcSMatt Macy zfsvfs_t *zfsvfs = vfsp->vfs_data; 437eda14cbcSMatt Macy dsl_pool_t *dp; 438eda14cbcSMatt Macy int error; 439eda14cbcSMatt Macy 440c7046f76SMartin Matuska if ((error = zfs_enter(zfsvfs, FTAG)) != 0) 441c7046f76SMartin Matuska return (error); 442eda14cbcSMatt Macy dp = dmu_objset_pool(zfsvfs->z_os); 443eda14cbcSMatt Macy 444eda14cbcSMatt Macy /* 445eda14cbcSMatt Macy * If the system is shutting down, then skip any 446eda14cbcSMatt Macy * filesystems which may exist on a suspended pool. 447eda14cbcSMatt Macy */ 448eda14cbcSMatt Macy if (rebooting && spa_suspended(dp->dp_spa)) { 449c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 450eda14cbcSMatt Macy return (0); 451eda14cbcSMatt Macy } 452eda14cbcSMatt Macy 453eda14cbcSMatt Macy if (zfsvfs->z_log != NULL) 454eda14cbcSMatt Macy zil_commit(zfsvfs->z_log, 0); 455eda14cbcSMatt Macy 456c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 457eda14cbcSMatt Macy } else { 458eda14cbcSMatt Macy /* 459eda14cbcSMatt Macy * Sync all ZFS filesystems. This is what happens when you 4607877fdebSMatt Macy * run sync(8). Unlike other filesystems, ZFS honors the 461eda14cbcSMatt Macy * request by waiting for all pools to commit all dirty data. 462eda14cbcSMatt Macy */ 463eda14cbcSMatt Macy spa_sync_allpools(); 464eda14cbcSMatt Macy } 465eda14cbcSMatt Macy 466eda14cbcSMatt Macy return (0); 467eda14cbcSMatt Macy } 468eda14cbcSMatt Macy 469eda14cbcSMatt Macy static void 470eda14cbcSMatt Macy atime_changed_cb(void *arg, uint64_t newval) 471eda14cbcSMatt Macy { 472eda14cbcSMatt Macy zfsvfs_t *zfsvfs = arg; 473eda14cbcSMatt Macy 474eda14cbcSMatt Macy if (newval == TRUE) { 475eda14cbcSMatt Macy zfsvfs->z_atime = TRUE; 476eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_flag &= ~MNT_NOATIME; 477eda14cbcSMatt Macy vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME); 478eda14cbcSMatt Macy vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_ATIME, NULL, 0); 479eda14cbcSMatt Macy } else { 480eda14cbcSMatt Macy zfsvfs->z_atime = FALSE; 481eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_flag |= MNT_NOATIME; 482eda14cbcSMatt Macy vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_ATIME); 483eda14cbcSMatt Macy vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME, NULL, 0); 484eda14cbcSMatt Macy } 485eda14cbcSMatt Macy } 486eda14cbcSMatt Macy 487eda14cbcSMatt Macy static void 488eda14cbcSMatt Macy xattr_changed_cb(void *arg, uint64_t newval) 489eda14cbcSMatt Macy { 490eda14cbcSMatt Macy zfsvfs_t *zfsvfs = arg; 491eda14cbcSMatt Macy 492eda14cbcSMatt Macy if (newval == ZFS_XATTR_OFF) { 493eda14cbcSMatt Macy zfsvfs->z_flags &= ~ZSB_XATTR; 494eda14cbcSMatt Macy } else { 495eda14cbcSMatt Macy zfsvfs->z_flags |= ZSB_XATTR; 496eda14cbcSMatt Macy 497eda14cbcSMatt Macy if (newval == ZFS_XATTR_SA) 498eda14cbcSMatt Macy zfsvfs->z_xattr_sa = B_TRUE; 499eda14cbcSMatt Macy else 500eda14cbcSMatt Macy zfsvfs->z_xattr_sa = B_FALSE; 501eda14cbcSMatt Macy } 502eda14cbcSMatt Macy } 503eda14cbcSMatt Macy 504eda14cbcSMatt Macy static void 505eda14cbcSMatt Macy blksz_changed_cb(void *arg, uint64_t newval) 506eda14cbcSMatt Macy { 507eda14cbcSMatt Macy zfsvfs_t *zfsvfs = arg; 508eda14cbcSMatt Macy ASSERT3U(newval, <=, spa_maxblocksize(dmu_objset_spa(zfsvfs->z_os))); 509eda14cbcSMatt Macy ASSERT3U(newval, >=, SPA_MINBLOCKSIZE); 510eda14cbcSMatt Macy ASSERT(ISP2(newval)); 511eda14cbcSMatt Macy 512eda14cbcSMatt Macy zfsvfs->z_max_blksz = newval; 513eda14cbcSMatt Macy zfsvfs->z_vfs->mnt_stat.f_iosize = newval; 514eda14cbcSMatt Macy } 515eda14cbcSMatt Macy 516eda14cbcSMatt Macy static void 517eda14cbcSMatt Macy readonly_changed_cb(void *arg, uint64_t newval) 518eda14cbcSMatt Macy { 519eda14cbcSMatt Macy zfsvfs_t *zfsvfs = arg; 520eda14cbcSMatt Macy 521eda14cbcSMatt Macy if (newval) { 522eda14cbcSMatt Macy /* XXX locking on vfs_flag? */ 523eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY; 524eda14cbcSMatt Macy vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RW); 525eda14cbcSMatt Macy vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RO, NULL, 0); 526eda14cbcSMatt Macy } else { 527eda14cbcSMatt Macy /* XXX locking on vfs_flag? */ 528eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 529eda14cbcSMatt Macy vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RO); 530eda14cbcSMatt Macy vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RW, NULL, 0); 531eda14cbcSMatt Macy } 532eda14cbcSMatt Macy } 533eda14cbcSMatt Macy 534eda14cbcSMatt Macy static void 535eda14cbcSMatt Macy setuid_changed_cb(void *arg, uint64_t newval) 536eda14cbcSMatt Macy { 537eda14cbcSMatt Macy zfsvfs_t *zfsvfs = arg; 538eda14cbcSMatt Macy 539eda14cbcSMatt Macy if (newval == FALSE) { 540eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_flag |= VFS_NOSETUID; 541eda14cbcSMatt Macy vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_SETUID); 542eda14cbcSMatt Macy vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID, NULL, 0); 543eda14cbcSMatt Macy } else { 544eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_flag &= ~VFS_NOSETUID; 545eda14cbcSMatt Macy vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID); 546eda14cbcSMatt Macy vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_SETUID, NULL, 0); 547eda14cbcSMatt Macy } 548eda14cbcSMatt Macy } 549eda14cbcSMatt Macy 550eda14cbcSMatt Macy static void 551eda14cbcSMatt Macy exec_changed_cb(void *arg, uint64_t newval) 552eda14cbcSMatt Macy { 553eda14cbcSMatt Macy zfsvfs_t *zfsvfs = arg; 554eda14cbcSMatt Macy 555eda14cbcSMatt Macy if (newval == FALSE) { 556eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_flag |= VFS_NOEXEC; 557eda14cbcSMatt Macy vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_EXEC); 558eda14cbcSMatt Macy vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC, NULL, 0); 559eda14cbcSMatt Macy } else { 560eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_flag &= ~VFS_NOEXEC; 561eda14cbcSMatt Macy vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC); 562eda14cbcSMatt Macy vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_EXEC, NULL, 0); 563eda14cbcSMatt Macy } 564eda14cbcSMatt Macy } 565eda14cbcSMatt Macy 566eda14cbcSMatt Macy /* 567eda14cbcSMatt Macy * The nbmand mount option can be changed at mount time. 568eda14cbcSMatt Macy * We can't allow it to be toggled on live file systems or incorrect 569eda14cbcSMatt Macy * behavior may be seen from cifs clients 570eda14cbcSMatt Macy * 571eda14cbcSMatt Macy * This property isn't registered via dsl_prop_register(), but this callback 572eda14cbcSMatt Macy * will be called when a file system is first mounted 573eda14cbcSMatt Macy */ 574eda14cbcSMatt Macy static void 575eda14cbcSMatt Macy nbmand_changed_cb(void *arg, uint64_t newval) 576eda14cbcSMatt Macy { 577eda14cbcSMatt Macy zfsvfs_t *zfsvfs = arg; 578eda14cbcSMatt Macy if (newval == FALSE) { 579eda14cbcSMatt Macy vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND); 580eda14cbcSMatt Macy vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND, NULL, 0); 581eda14cbcSMatt Macy } else { 582eda14cbcSMatt Macy vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND); 583eda14cbcSMatt Macy vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND, NULL, 0); 584eda14cbcSMatt Macy } 585eda14cbcSMatt Macy } 586eda14cbcSMatt Macy 587eda14cbcSMatt Macy static void 588eda14cbcSMatt Macy snapdir_changed_cb(void *arg, uint64_t newval) 589eda14cbcSMatt Macy { 590eda14cbcSMatt Macy zfsvfs_t *zfsvfs = arg; 591eda14cbcSMatt Macy 592eda14cbcSMatt Macy zfsvfs->z_show_ctldir = newval; 593eda14cbcSMatt Macy } 594eda14cbcSMatt Macy 595eda14cbcSMatt Macy static void 596eda14cbcSMatt Macy acl_mode_changed_cb(void *arg, uint64_t newval) 597eda14cbcSMatt Macy { 598eda14cbcSMatt Macy zfsvfs_t *zfsvfs = arg; 599eda14cbcSMatt Macy 600eda14cbcSMatt Macy zfsvfs->z_acl_mode = newval; 601eda14cbcSMatt Macy } 602eda14cbcSMatt Macy 603eda14cbcSMatt Macy static void 604eda14cbcSMatt Macy acl_inherit_changed_cb(void *arg, uint64_t newval) 605eda14cbcSMatt Macy { 606eda14cbcSMatt Macy zfsvfs_t *zfsvfs = arg; 607eda14cbcSMatt Macy 608eda14cbcSMatt Macy zfsvfs->z_acl_inherit = newval; 609eda14cbcSMatt Macy } 610eda14cbcSMatt Macy 611180f8225SMatt Macy static void 612180f8225SMatt Macy acl_type_changed_cb(void *arg, uint64_t newval) 613180f8225SMatt Macy { 614180f8225SMatt Macy zfsvfs_t *zfsvfs = arg; 615180f8225SMatt Macy 616180f8225SMatt Macy zfsvfs->z_acl_type = newval; 617180f8225SMatt Macy } 618180f8225SMatt Macy 6197a7741afSMartin Matuska static void 6207a7741afSMartin Matuska longname_changed_cb(void *arg, uint64_t newval) 6217a7741afSMartin Matuska { 6227a7741afSMartin Matuska zfsvfs_t *zfsvfs = arg; 6237a7741afSMartin Matuska 6247a7741afSMartin Matuska zfsvfs->z_longname = newval; 6257a7741afSMartin Matuska } 6267a7741afSMartin Matuska 627eda14cbcSMatt Macy static int 628eda14cbcSMatt Macy zfs_register_callbacks(vfs_t *vfsp) 629eda14cbcSMatt Macy { 630eda14cbcSMatt Macy struct dsl_dataset *ds = NULL; 631eda14cbcSMatt Macy objset_t *os = NULL; 632eda14cbcSMatt Macy zfsvfs_t *zfsvfs = NULL; 633eda14cbcSMatt Macy uint64_t nbmand; 634eda14cbcSMatt Macy boolean_t readonly = B_FALSE; 635eda14cbcSMatt Macy boolean_t do_readonly = B_FALSE; 636eda14cbcSMatt Macy boolean_t setuid = B_FALSE; 637eda14cbcSMatt Macy boolean_t do_setuid = B_FALSE; 638eda14cbcSMatt Macy boolean_t exec = B_FALSE; 639eda14cbcSMatt Macy boolean_t do_exec = B_FALSE; 640eda14cbcSMatt Macy boolean_t xattr = B_FALSE; 641eda14cbcSMatt Macy boolean_t atime = B_FALSE; 642eda14cbcSMatt Macy boolean_t do_atime = B_FALSE; 643eda14cbcSMatt Macy boolean_t do_xattr = B_FALSE; 644eda14cbcSMatt Macy int error = 0; 645eda14cbcSMatt Macy 64616038816SMartin Matuska ASSERT3P(vfsp, !=, NULL); 647eda14cbcSMatt Macy zfsvfs = vfsp->vfs_data; 64816038816SMartin Matuska ASSERT3P(zfsvfs, !=, NULL); 649eda14cbcSMatt Macy os = zfsvfs->z_os; 650eda14cbcSMatt Macy 651eda14cbcSMatt Macy /* 652eda14cbcSMatt Macy * This function can be called for a snapshot when we update snapshot's 653eda14cbcSMatt Macy * mount point, which isn't really supported. 654eda14cbcSMatt Macy */ 655eda14cbcSMatt Macy if (dmu_objset_is_snapshot(os)) 656eda14cbcSMatt Macy return (EOPNOTSUPP); 657eda14cbcSMatt Macy 658eda14cbcSMatt Macy /* 659eda14cbcSMatt Macy * The act of registering our callbacks will destroy any mount 660eda14cbcSMatt Macy * options we may have. In order to enable temporary overrides 661eda14cbcSMatt Macy * of mount options, we stash away the current values and 662eda14cbcSMatt Macy * restore them after we register the callbacks. 663eda14cbcSMatt Macy */ 664eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_RO, NULL) || 665eda14cbcSMatt Macy !spa_writeable(dmu_objset_spa(os))) { 666eda14cbcSMatt Macy readonly = B_TRUE; 667eda14cbcSMatt Macy do_readonly = B_TRUE; 668eda14cbcSMatt Macy } else if (vfs_optionisset(vfsp, MNTOPT_RW, NULL)) { 669eda14cbcSMatt Macy readonly = B_FALSE; 670eda14cbcSMatt Macy do_readonly = B_TRUE; 671eda14cbcSMatt Macy } 672eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) { 673eda14cbcSMatt Macy setuid = B_FALSE; 674eda14cbcSMatt Macy do_setuid = B_TRUE; 675eda14cbcSMatt Macy } else if (vfs_optionisset(vfsp, MNTOPT_SETUID, NULL)) { 676eda14cbcSMatt Macy setuid = B_TRUE; 677eda14cbcSMatt Macy do_setuid = B_TRUE; 678eda14cbcSMatt Macy } 679eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) { 680eda14cbcSMatt Macy exec = B_FALSE; 681eda14cbcSMatt Macy do_exec = B_TRUE; 682eda14cbcSMatt Macy } else if (vfs_optionisset(vfsp, MNTOPT_EXEC, NULL)) { 683eda14cbcSMatt Macy exec = B_TRUE; 684eda14cbcSMatt Macy do_exec = B_TRUE; 685eda14cbcSMatt Macy } 686eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NOXATTR, NULL)) { 687eda14cbcSMatt Macy zfsvfs->z_xattr = xattr = ZFS_XATTR_OFF; 688eda14cbcSMatt Macy do_xattr = B_TRUE; 689eda14cbcSMatt Macy } else if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) { 690eda14cbcSMatt Macy zfsvfs->z_xattr = xattr = ZFS_XATTR_DIR; 691eda14cbcSMatt Macy do_xattr = B_TRUE; 692eda14cbcSMatt Macy } else if (vfs_optionisset(vfsp, MNTOPT_DIRXATTR, NULL)) { 693eda14cbcSMatt Macy zfsvfs->z_xattr = xattr = ZFS_XATTR_DIR; 694eda14cbcSMatt Macy do_xattr = B_TRUE; 695eda14cbcSMatt Macy } else if (vfs_optionisset(vfsp, MNTOPT_SAXATTR, NULL)) { 696eda14cbcSMatt Macy zfsvfs->z_xattr = xattr = ZFS_XATTR_SA; 697eda14cbcSMatt Macy do_xattr = B_TRUE; 698eda14cbcSMatt Macy } 699eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) { 700eda14cbcSMatt Macy atime = B_FALSE; 701eda14cbcSMatt Macy do_atime = B_TRUE; 702eda14cbcSMatt Macy } else if (vfs_optionisset(vfsp, MNTOPT_ATIME, NULL)) { 703eda14cbcSMatt Macy atime = B_TRUE; 704eda14cbcSMatt Macy do_atime = B_TRUE; 705eda14cbcSMatt Macy } 706eda14cbcSMatt Macy 707eda14cbcSMatt Macy /* 708eda14cbcSMatt Macy * We need to enter pool configuration here, so that we can use 709eda14cbcSMatt Macy * dsl_prop_get_int_ds() to handle the special nbmand property below. 710eda14cbcSMatt Macy * dsl_prop_get_integer() can not be used, because it has to acquire 711eda14cbcSMatt Macy * spa_namespace_lock and we can not do that because we already hold 712eda14cbcSMatt Macy * z_teardown_lock. The problem is that spa_write_cachefile() is called 713eda14cbcSMatt Macy * with spa_namespace_lock held and the function calls ZFS vnode 714eda14cbcSMatt Macy * operations to write the cache file and thus z_teardown_lock is 715eda14cbcSMatt Macy * acquired after spa_namespace_lock. 716eda14cbcSMatt Macy */ 717eda14cbcSMatt Macy ds = dmu_objset_ds(os); 718eda14cbcSMatt Macy dsl_pool_config_enter(dmu_objset_pool(os), FTAG); 719eda14cbcSMatt Macy 720eda14cbcSMatt Macy /* 721eda14cbcSMatt Macy * nbmand is a special property. It can only be changed at 722eda14cbcSMatt Macy * mount time. 723eda14cbcSMatt Macy * 724eda14cbcSMatt Macy * This is weird, but it is documented to only be changeable 725eda14cbcSMatt Macy * at mount time. 726eda14cbcSMatt Macy */ 727eda14cbcSMatt Macy if (vfs_optionisset(vfsp, MNTOPT_NONBMAND, NULL)) { 728eda14cbcSMatt Macy nbmand = B_FALSE; 729eda14cbcSMatt Macy } else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) { 730eda14cbcSMatt Macy nbmand = B_TRUE; 731bb2d13b6SMartin Matuska } else if ((error = dsl_prop_get_int_ds(ds, "nbmand", &nbmand)) != 0) { 732eda14cbcSMatt Macy dsl_pool_config_exit(dmu_objset_pool(os), FTAG); 733eda14cbcSMatt Macy return (error); 734eda14cbcSMatt Macy } 735eda14cbcSMatt Macy 736eda14cbcSMatt Macy /* 737eda14cbcSMatt Macy * Register property callbacks. 738eda14cbcSMatt Macy * 739eda14cbcSMatt Macy * It would probably be fine to just check for i/o error from 740eda14cbcSMatt Macy * the first prop_register(), but I guess I like to go 741eda14cbcSMatt Macy * overboard... 742eda14cbcSMatt Macy */ 743eda14cbcSMatt Macy error = dsl_prop_register(ds, 744eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_ATIME), atime_changed_cb, zfsvfs); 745eda14cbcSMatt Macy error = error ? error : dsl_prop_register(ds, 746eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_XATTR), xattr_changed_cb, zfsvfs); 747eda14cbcSMatt Macy error = error ? error : dsl_prop_register(ds, 748eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_RECORDSIZE), blksz_changed_cb, zfsvfs); 749eda14cbcSMatt Macy error = error ? error : dsl_prop_register(ds, 750eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_READONLY), readonly_changed_cb, zfsvfs); 751eda14cbcSMatt Macy error = error ? error : dsl_prop_register(ds, 752eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_SETUID), setuid_changed_cb, zfsvfs); 753eda14cbcSMatt Macy error = error ? error : dsl_prop_register(ds, 754eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_EXEC), exec_changed_cb, zfsvfs); 755eda14cbcSMatt Macy error = error ? error : dsl_prop_register(ds, 756eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_SNAPDIR), snapdir_changed_cb, zfsvfs); 757eda14cbcSMatt Macy error = error ? error : dsl_prop_register(ds, 758180f8225SMatt Macy zfs_prop_to_name(ZFS_PROP_ACLTYPE), acl_type_changed_cb, zfsvfs); 759180f8225SMatt Macy error = error ? error : dsl_prop_register(ds, 760eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_ACLMODE), acl_mode_changed_cb, zfsvfs); 761eda14cbcSMatt Macy error = error ? error : dsl_prop_register(ds, 762eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_ACLINHERIT), acl_inherit_changed_cb, 763eda14cbcSMatt Macy zfsvfs); 7647a7741afSMartin Matuska error = error ? error : dsl_prop_register(ds, 7657a7741afSMartin Matuska zfs_prop_to_name(ZFS_PROP_LONGNAME), longname_changed_cb, zfsvfs); 766eda14cbcSMatt Macy dsl_pool_config_exit(dmu_objset_pool(os), FTAG); 767eda14cbcSMatt Macy if (error) 768eda14cbcSMatt Macy goto unregister; 769eda14cbcSMatt Macy 770eda14cbcSMatt Macy /* 771eda14cbcSMatt Macy * Invoke our callbacks to restore temporary mount options. 772eda14cbcSMatt Macy */ 773eda14cbcSMatt Macy if (do_readonly) 774eda14cbcSMatt Macy readonly_changed_cb(zfsvfs, readonly); 775eda14cbcSMatt Macy if (do_setuid) 776eda14cbcSMatt Macy setuid_changed_cb(zfsvfs, setuid); 777eda14cbcSMatt Macy if (do_exec) 778eda14cbcSMatt Macy exec_changed_cb(zfsvfs, exec); 779eda14cbcSMatt Macy if (do_xattr) 780eda14cbcSMatt Macy xattr_changed_cb(zfsvfs, xattr); 781eda14cbcSMatt Macy if (do_atime) 782eda14cbcSMatt Macy atime_changed_cb(zfsvfs, atime); 783eda14cbcSMatt Macy 784eda14cbcSMatt Macy nbmand_changed_cb(zfsvfs, nbmand); 785eda14cbcSMatt Macy 786eda14cbcSMatt Macy return (0); 787eda14cbcSMatt Macy 788eda14cbcSMatt Macy unregister: 789eda14cbcSMatt Macy dsl_prop_unregister_all(ds, zfsvfs); 790eda14cbcSMatt Macy return (error); 791eda14cbcSMatt Macy } 792eda14cbcSMatt Macy 793eda14cbcSMatt Macy /* 794eda14cbcSMatt Macy * Associate this zfsvfs with the given objset, which must be owned. 795eda14cbcSMatt Macy * This will cache a bunch of on-disk state from the objset in the 796eda14cbcSMatt Macy * zfsvfs. 797eda14cbcSMatt Macy */ 798eda14cbcSMatt Macy static int 799eda14cbcSMatt Macy zfsvfs_init(zfsvfs_t *zfsvfs, objset_t *os) 800eda14cbcSMatt Macy { 801eda14cbcSMatt Macy int error; 802eda14cbcSMatt Macy uint64_t val; 803eda14cbcSMatt Macy 804eda14cbcSMatt Macy zfsvfs->z_max_blksz = SPA_OLD_MAXBLOCKSIZE; 805eda14cbcSMatt Macy zfsvfs->z_show_ctldir = ZFS_SNAPDIR_VISIBLE; 806eda14cbcSMatt Macy zfsvfs->z_os = os; 807eda14cbcSMatt Macy 808eda14cbcSMatt Macy error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zfsvfs->z_version); 809eda14cbcSMatt Macy if (error != 0) 810eda14cbcSMatt Macy return (error); 811eda14cbcSMatt Macy if (zfsvfs->z_version > 812eda14cbcSMatt Macy zfs_zpl_version_map(spa_version(dmu_objset_spa(os)))) { 813eda14cbcSMatt Macy (void) printf("Can't mount a version %lld file system " 814eda14cbcSMatt Macy "on a version %lld pool\n. Pool must be upgraded to mount " 815eda14cbcSMatt Macy "this file system.", (u_longlong_t)zfsvfs->z_version, 816eda14cbcSMatt Macy (u_longlong_t)spa_version(dmu_objset_spa(os))); 817eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 818eda14cbcSMatt Macy } 819eda14cbcSMatt Macy error = zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &val); 820eda14cbcSMatt Macy if (error != 0) 821eda14cbcSMatt Macy return (error); 822eda14cbcSMatt Macy zfsvfs->z_norm = (int)val; 823eda14cbcSMatt Macy 824eda14cbcSMatt Macy error = zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &val); 825eda14cbcSMatt Macy if (error != 0) 826eda14cbcSMatt Macy return (error); 827eda14cbcSMatt Macy zfsvfs->z_utf8 = (val != 0); 828eda14cbcSMatt Macy 829eda14cbcSMatt Macy error = zfs_get_zplprop(os, ZFS_PROP_CASE, &val); 830eda14cbcSMatt Macy if (error != 0) 831eda14cbcSMatt Macy return (error); 832eda14cbcSMatt Macy zfsvfs->z_case = (uint_t)val; 833eda14cbcSMatt Macy 834180f8225SMatt Macy error = zfs_get_zplprop(os, ZFS_PROP_ACLTYPE, &val); 835180f8225SMatt Macy if (error != 0) 836180f8225SMatt Macy return (error); 837180f8225SMatt Macy zfsvfs->z_acl_type = (uint_t)val; 838180f8225SMatt Macy 839eda14cbcSMatt Macy /* 840eda14cbcSMatt Macy * Fold case on file systems that are always or sometimes case 841eda14cbcSMatt Macy * insensitive. 842eda14cbcSMatt Macy */ 843eda14cbcSMatt Macy if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE || 844eda14cbcSMatt Macy zfsvfs->z_case == ZFS_CASE_MIXED) 845eda14cbcSMatt Macy zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER; 846eda14cbcSMatt Macy 847eda14cbcSMatt Macy zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os); 848eda14cbcSMatt Macy zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os); 849eda14cbcSMatt Macy 850eda14cbcSMatt Macy uint64_t sa_obj = 0; 851eda14cbcSMatt Macy if (zfsvfs->z_use_sa) { 852eda14cbcSMatt Macy /* should either have both of these objects or none */ 853eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, 854eda14cbcSMatt Macy &sa_obj); 855eda14cbcSMatt Macy if (error != 0) 856eda14cbcSMatt Macy return (error); 85716038816SMartin Matuska 85816038816SMartin Matuska error = zfs_get_zplprop(os, ZFS_PROP_XATTR, &val); 85916038816SMartin Matuska if (error == 0 && val == ZFS_XATTR_SA) 86016038816SMartin Matuska zfsvfs->z_xattr_sa = B_TRUE; 861eda14cbcSMatt Macy } 862eda14cbcSMatt Macy 863eda14cbcSMatt Macy error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END, 864eda14cbcSMatt Macy &zfsvfs->z_attr_table); 865eda14cbcSMatt Macy if (error != 0) 866eda14cbcSMatt Macy return (error); 867eda14cbcSMatt Macy 868eda14cbcSMatt Macy if (zfsvfs->z_version >= ZPL_VERSION_SA) 869eda14cbcSMatt Macy sa_register_update_callback(os, zfs_sa_upgrade); 870eda14cbcSMatt Macy 871eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, 872eda14cbcSMatt Macy &zfsvfs->z_root); 873eda14cbcSMatt Macy if (error != 0) 874eda14cbcSMatt Macy return (error); 87516038816SMartin Matuska ASSERT3U(zfsvfs->z_root, !=, 0); 876eda14cbcSMatt Macy 877eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET, 8, 1, 878eda14cbcSMatt Macy &zfsvfs->z_unlinkedobj); 879eda14cbcSMatt Macy if (error != 0) 880eda14cbcSMatt Macy return (error); 881eda14cbcSMatt Macy 882eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, 883eda14cbcSMatt Macy zfs_userquota_prop_prefixes[ZFS_PROP_USERQUOTA], 884eda14cbcSMatt Macy 8, 1, &zfsvfs->z_userquota_obj); 885eda14cbcSMatt Macy if (error == ENOENT) 886eda14cbcSMatt Macy zfsvfs->z_userquota_obj = 0; 887eda14cbcSMatt Macy else if (error != 0) 888eda14cbcSMatt Macy return (error); 889eda14cbcSMatt Macy 890eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, 891eda14cbcSMatt Macy zfs_userquota_prop_prefixes[ZFS_PROP_GROUPQUOTA], 892eda14cbcSMatt Macy 8, 1, &zfsvfs->z_groupquota_obj); 893eda14cbcSMatt Macy if (error == ENOENT) 894eda14cbcSMatt Macy zfsvfs->z_groupquota_obj = 0; 895eda14cbcSMatt Macy else if (error != 0) 896eda14cbcSMatt Macy return (error); 897eda14cbcSMatt Macy 898eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, 899eda14cbcSMatt Macy zfs_userquota_prop_prefixes[ZFS_PROP_PROJECTQUOTA], 900eda14cbcSMatt Macy 8, 1, &zfsvfs->z_projectquota_obj); 901eda14cbcSMatt Macy if (error == ENOENT) 902eda14cbcSMatt Macy zfsvfs->z_projectquota_obj = 0; 903eda14cbcSMatt Macy else if (error != 0) 904eda14cbcSMatt Macy return (error); 905eda14cbcSMatt Macy 906eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, 907eda14cbcSMatt Macy zfs_userquota_prop_prefixes[ZFS_PROP_USEROBJQUOTA], 908eda14cbcSMatt Macy 8, 1, &zfsvfs->z_userobjquota_obj); 909eda14cbcSMatt Macy if (error == ENOENT) 910eda14cbcSMatt Macy zfsvfs->z_userobjquota_obj = 0; 911eda14cbcSMatt Macy else if (error != 0) 912eda14cbcSMatt Macy return (error); 913eda14cbcSMatt Macy 914eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, 915eda14cbcSMatt Macy zfs_userquota_prop_prefixes[ZFS_PROP_GROUPOBJQUOTA], 916eda14cbcSMatt Macy 8, 1, &zfsvfs->z_groupobjquota_obj); 917eda14cbcSMatt Macy if (error == ENOENT) 918eda14cbcSMatt Macy zfsvfs->z_groupobjquota_obj = 0; 919eda14cbcSMatt Macy else if (error != 0) 920eda14cbcSMatt Macy return (error); 921eda14cbcSMatt Macy 922eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, 923eda14cbcSMatt Macy zfs_userquota_prop_prefixes[ZFS_PROP_PROJECTOBJQUOTA], 924eda14cbcSMatt Macy 8, 1, &zfsvfs->z_projectobjquota_obj); 925eda14cbcSMatt Macy if (error == ENOENT) 926eda14cbcSMatt Macy zfsvfs->z_projectobjquota_obj = 0; 927eda14cbcSMatt Macy else if (error != 0) 928eda14cbcSMatt Macy return (error); 929eda14cbcSMatt Macy 930eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES, 8, 1, 931eda14cbcSMatt Macy &zfsvfs->z_fuid_obj); 932eda14cbcSMatt Macy if (error == ENOENT) 933eda14cbcSMatt Macy zfsvfs->z_fuid_obj = 0; 934eda14cbcSMatt Macy else if (error != 0) 935eda14cbcSMatt Macy return (error); 936eda14cbcSMatt Macy 937eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SHARES_DIR, 8, 1, 938eda14cbcSMatt Macy &zfsvfs->z_shares_dir); 939eda14cbcSMatt Macy if (error == ENOENT) 940eda14cbcSMatt Macy zfsvfs->z_shares_dir = 0; 941eda14cbcSMatt Macy else if (error != 0) 942eda14cbcSMatt Macy return (error); 943eda14cbcSMatt Macy 944eda14cbcSMatt Macy /* 945eda14cbcSMatt Macy * Only use the name cache if we are looking for a 946eda14cbcSMatt Macy * name on a file system that does not require normalization 947eda14cbcSMatt Macy * or case folding. We can also look there if we happen to be 948eda14cbcSMatt Macy * on a non-normalizing, mixed sensitivity file system IF we 949eda14cbcSMatt Macy * are looking for the exact name (which is always the case on 950eda14cbcSMatt Macy * FreeBSD). 951eda14cbcSMatt Macy */ 952eda14cbcSMatt Macy zfsvfs->z_use_namecache = !zfsvfs->z_norm || 953eda14cbcSMatt Macy ((zfsvfs->z_case == ZFS_CASE_MIXED) && 954eda14cbcSMatt Macy !(zfsvfs->z_norm & ~U8_TEXTPREP_TOUPPER)); 955eda14cbcSMatt Macy 956eda14cbcSMatt Macy return (0); 957eda14cbcSMatt Macy } 958eda14cbcSMatt Macy 959eda14cbcSMatt Macy taskq_t *zfsvfs_taskq; 960eda14cbcSMatt Macy 961eda14cbcSMatt Macy static void 962eda14cbcSMatt Macy zfsvfs_task_unlinked_drain(void *context, int pending __unused) 963eda14cbcSMatt Macy { 964eda14cbcSMatt Macy 965eda14cbcSMatt Macy zfs_unlinked_drain((zfsvfs_t *)context); 966eda14cbcSMatt Macy } 967eda14cbcSMatt Macy 968eda14cbcSMatt Macy int 969eda14cbcSMatt Macy zfsvfs_create(const char *osname, boolean_t readonly, zfsvfs_t **zfvp) 970eda14cbcSMatt Macy { 971eda14cbcSMatt Macy objset_t *os; 972eda14cbcSMatt Macy zfsvfs_t *zfsvfs; 973eda14cbcSMatt Macy int error; 974eda14cbcSMatt Macy boolean_t ro = (readonly || (strchr(osname, '@') != NULL)); 975eda14cbcSMatt Macy 976eda14cbcSMatt Macy /* 977eda14cbcSMatt Macy * XXX: Fix struct statfs so this isn't necessary! 978eda14cbcSMatt Macy * 979eda14cbcSMatt Macy * The 'osname' is used as the filesystem's special node, which means 980eda14cbcSMatt Macy * it must fit in statfs.f_mntfromname, or else it can't be 981eda14cbcSMatt Macy * enumerated, so libzfs_mnttab_find() returns NULL, which causes 982eda14cbcSMatt Macy * 'zfs unmount' to think it's not mounted when it is. 983eda14cbcSMatt Macy */ 984eda14cbcSMatt Macy if (strlen(osname) >= MNAMELEN) 985eda14cbcSMatt Macy return (SET_ERROR(ENAMETOOLONG)); 986eda14cbcSMatt Macy 987eda14cbcSMatt Macy zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); 988eda14cbcSMatt Macy 989eda14cbcSMatt Macy error = dmu_objset_own(osname, DMU_OST_ZFS, ro, B_TRUE, zfsvfs, 990eda14cbcSMatt Macy &os); 991eda14cbcSMatt Macy if (error != 0) { 992eda14cbcSMatt Macy kmem_free(zfsvfs, sizeof (zfsvfs_t)); 993eda14cbcSMatt Macy return (error); 994eda14cbcSMatt Macy } 995eda14cbcSMatt Macy 996eda14cbcSMatt Macy error = zfsvfs_create_impl(zfvp, zfsvfs, os); 997eda14cbcSMatt Macy 998eda14cbcSMatt Macy return (error); 999eda14cbcSMatt Macy } 1000eda14cbcSMatt Macy 1001eda14cbcSMatt Macy 1002eda14cbcSMatt Macy int 1003eda14cbcSMatt Macy zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os) 1004eda14cbcSMatt Macy { 1005eda14cbcSMatt Macy int error; 1006eda14cbcSMatt Macy 1007eda14cbcSMatt Macy zfsvfs->z_vfs = NULL; 1008eda14cbcSMatt Macy zfsvfs->z_parent = zfsvfs; 1009eda14cbcSMatt Macy 1010eda14cbcSMatt Macy mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); 1011eda14cbcSMatt Macy mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL); 1012eda14cbcSMatt Macy list_create(&zfsvfs->z_all_znodes, sizeof (znode_t), 1013eda14cbcSMatt Macy offsetof(znode_t, z_link_node)); 1014eda14cbcSMatt Macy TASK_INIT(&zfsvfs->z_unlinked_drain_task, 0, 1015eda14cbcSMatt Macy zfsvfs_task_unlinked_drain, zfsvfs); 10164008dd45SMateusz Guzik ZFS_TEARDOWN_INIT(zfsvfs); 1017ae5642a6SMateusz Guzik ZFS_TEARDOWN_INACTIVE_INIT(zfsvfs); 1018eda14cbcSMatt Macy rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL); 1019eda14cbcSMatt Macy for (int i = 0; i != ZFS_OBJ_MTX_SZ; i++) 1020eda14cbcSMatt Macy mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); 1021eda14cbcSMatt Macy 1022eda14cbcSMatt Macy error = zfsvfs_init(zfsvfs, os); 1023eda14cbcSMatt Macy if (error != 0) { 1024eda14cbcSMatt Macy dmu_objset_disown(os, B_TRUE, zfsvfs); 1025eda14cbcSMatt Macy *zfvp = NULL; 1026eda14cbcSMatt Macy kmem_free(zfsvfs, sizeof (zfsvfs_t)); 1027eda14cbcSMatt Macy return (error); 1028eda14cbcSMatt Macy } 1029eda14cbcSMatt Macy 1030eda14cbcSMatt Macy *zfvp = zfsvfs; 1031eda14cbcSMatt Macy return (0); 1032eda14cbcSMatt Macy } 1033eda14cbcSMatt Macy 1034eda14cbcSMatt Macy static int 1035eda14cbcSMatt Macy zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) 1036eda14cbcSMatt Macy { 1037eda14cbcSMatt Macy int error; 1038eda14cbcSMatt Macy 1039eda14cbcSMatt Macy /* 1040eda14cbcSMatt Macy * Check for a bad on-disk format version now since we 1041eda14cbcSMatt Macy * lied about owning the dataset readonly before. 1042eda14cbcSMatt Macy */ 1043eda14cbcSMatt Macy if (!(zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) && 1044eda14cbcSMatt Macy dmu_objset_incompatible_encryption_version(zfsvfs->z_os)) 1045eda14cbcSMatt Macy return (SET_ERROR(EROFS)); 1046eda14cbcSMatt Macy 1047eda14cbcSMatt Macy error = zfs_register_callbacks(zfsvfs->z_vfs); 1048eda14cbcSMatt Macy if (error) 1049eda14cbcSMatt Macy return (error); 1050eda14cbcSMatt Macy 1051eda14cbcSMatt Macy /* 1052eda14cbcSMatt Macy * If we are not mounting (ie: online recv), then we don't 1053eda14cbcSMatt Macy * have to worry about replaying the log as we blocked all 1054eda14cbcSMatt Macy * operations out since we closed the ZIL. 1055eda14cbcSMatt Macy */ 1056eda14cbcSMatt Macy if (mounting) { 1057eda14cbcSMatt Macy boolean_t readonly; 1058eda14cbcSMatt Macy 1059eda14cbcSMatt Macy ASSERT3P(zfsvfs->z_kstat.dk_kstats, ==, NULL); 1060271171e0SMartin Matuska error = dataset_kstats_create(&zfsvfs->z_kstat, zfsvfs->z_os); 1061271171e0SMartin Matuska if (error) 1062271171e0SMartin Matuska return (error); 1063271171e0SMartin Matuska zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data, 1064271171e0SMartin Matuska &zfsvfs->z_kstat.dk_zil_sums); 1065eda14cbcSMatt Macy 1066eda14cbcSMatt Macy /* 1067eda14cbcSMatt Macy * During replay we remove the read only flag to 1068eda14cbcSMatt Macy * allow replays to succeed. 1069eda14cbcSMatt Macy */ 1070eda14cbcSMatt Macy readonly = zfsvfs->z_vfs->vfs_flag & VFS_RDONLY; 1071eda14cbcSMatt Macy if (readonly != 0) { 1072eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 1073eda14cbcSMatt Macy } else { 1074eda14cbcSMatt Macy dsl_dir_t *dd; 1075eda14cbcSMatt Macy zap_stats_t zs; 1076eda14cbcSMatt Macy 1077eda14cbcSMatt Macy if (zap_get_stats(zfsvfs->z_os, zfsvfs->z_unlinkedobj, 1078eda14cbcSMatt Macy &zs) == 0) { 1079eda14cbcSMatt Macy dataset_kstats_update_nunlinks_kstat( 1080eda14cbcSMatt Macy &zfsvfs->z_kstat, zs.zs_num_entries); 1081eda14cbcSMatt Macy dprintf_ds(zfsvfs->z_os->os_dsl_dataset, 1082eda14cbcSMatt Macy "num_entries in unlinked set: %llu", 108333b8c039SMartin Matuska (u_longlong_t)zs.zs_num_entries); 1084eda14cbcSMatt Macy } 1085eda14cbcSMatt Macy 1086eda14cbcSMatt Macy zfs_unlinked_drain(zfsvfs); 1087eda14cbcSMatt Macy dd = zfsvfs->z_os->os_dsl_dataset->ds_dir; 1088eda14cbcSMatt Macy dd->dd_activity_cancelled = B_FALSE; 1089eda14cbcSMatt Macy } 1090eda14cbcSMatt Macy 1091eda14cbcSMatt Macy /* 1092eda14cbcSMatt Macy * Parse and replay the intent log. 1093eda14cbcSMatt Macy * 1094eda14cbcSMatt Macy * Because of ziltest, this must be done after 1095eda14cbcSMatt Macy * zfs_unlinked_drain(). (Further note: ziltest 1096eda14cbcSMatt Macy * doesn't use readonly mounts, where 1097eda14cbcSMatt Macy * zfs_unlinked_drain() isn't called.) This is because 1098eda14cbcSMatt Macy * ziltest causes spa_sync() to think it's committed, 1099eda14cbcSMatt Macy * but actually it is not, so the intent log contains 1100eda14cbcSMatt Macy * many txg's worth of changes. 1101eda14cbcSMatt Macy * 1102eda14cbcSMatt Macy * In particular, if object N is in the unlinked set in 1103eda14cbcSMatt Macy * the last txg to actually sync, then it could be 1104eda14cbcSMatt Macy * actually freed in a later txg and then reallocated 1105eda14cbcSMatt Macy * in a yet later txg. This would write a "create 1106eda14cbcSMatt Macy * object N" record to the intent log. Normally, this 1107eda14cbcSMatt Macy * would be fine because the spa_sync() would have 1108eda14cbcSMatt Macy * written out the fact that object N is free, before 1109eda14cbcSMatt Macy * we could write the "create object N" intent log 1110eda14cbcSMatt Macy * record. 1111eda14cbcSMatt Macy * 1112eda14cbcSMatt Macy * But when we are in ziltest mode, we advance the "open 1113eda14cbcSMatt Macy * txg" without actually spa_sync()-ing the changes to 1114eda14cbcSMatt Macy * disk. So we would see that object N is still 1115eda14cbcSMatt Macy * allocated and in the unlinked set, and there is an 1116eda14cbcSMatt Macy * intent log record saying to allocate it. 1117eda14cbcSMatt Macy */ 1118eda14cbcSMatt Macy if (spa_writeable(dmu_objset_spa(zfsvfs->z_os))) { 1119eda14cbcSMatt Macy if (zil_replay_disable) { 1120eda14cbcSMatt Macy zil_destroy(zfsvfs->z_log, B_FALSE); 1121eda14cbcSMatt Macy } else { 1122eda14cbcSMatt Macy boolean_t use_nc = zfsvfs->z_use_namecache; 1123eda14cbcSMatt Macy zfsvfs->z_use_namecache = B_FALSE; 1124eda14cbcSMatt Macy zfsvfs->z_replay = B_TRUE; 1125eda14cbcSMatt Macy zil_replay(zfsvfs->z_os, zfsvfs, 1126eda14cbcSMatt Macy zfs_replay_vector); 1127eda14cbcSMatt Macy zfsvfs->z_replay = B_FALSE; 1128eda14cbcSMatt Macy zfsvfs->z_use_namecache = use_nc; 1129eda14cbcSMatt Macy } 1130eda14cbcSMatt Macy } 1131eda14cbcSMatt Macy 1132eda14cbcSMatt Macy /* restore readonly bit */ 1133eda14cbcSMatt Macy if (readonly != 0) 1134eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY; 1135271171e0SMartin Matuska } else { 1136271171e0SMartin Matuska ASSERT3P(zfsvfs->z_kstat.dk_kstats, !=, NULL); 1137271171e0SMartin Matuska zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data, 1138271171e0SMartin Matuska &zfsvfs->z_kstat.dk_zil_sums); 1139eda14cbcSMatt Macy } 1140eda14cbcSMatt Macy 1141eda14cbcSMatt Macy /* 1142eda14cbcSMatt Macy * Set the objset user_ptr to track its zfsvfs. 1143eda14cbcSMatt Macy */ 1144eda14cbcSMatt Macy mutex_enter(&zfsvfs->z_os->os_user_ptr_lock); 1145eda14cbcSMatt Macy dmu_objset_set_user(zfsvfs->z_os, zfsvfs); 1146eda14cbcSMatt Macy mutex_exit(&zfsvfs->z_os->os_user_ptr_lock); 1147eda14cbcSMatt Macy 1148eda14cbcSMatt Macy return (0); 1149eda14cbcSMatt Macy } 1150eda14cbcSMatt Macy 1151eda14cbcSMatt Macy void 1152eda14cbcSMatt Macy zfsvfs_free(zfsvfs_t *zfsvfs) 1153eda14cbcSMatt Macy { 1154eda14cbcSMatt Macy int i; 1155eda14cbcSMatt Macy 1156eda14cbcSMatt Macy zfs_fuid_destroy(zfsvfs); 1157eda14cbcSMatt Macy 1158eda14cbcSMatt Macy mutex_destroy(&zfsvfs->z_znodes_lock); 1159eda14cbcSMatt Macy mutex_destroy(&zfsvfs->z_lock); 1160eda14cbcSMatt Macy list_destroy(&zfsvfs->z_all_znodes); 11614008dd45SMateusz Guzik ZFS_TEARDOWN_DESTROY(zfsvfs); 1162ae5642a6SMateusz Guzik ZFS_TEARDOWN_INACTIVE_DESTROY(zfsvfs); 1163eda14cbcSMatt Macy rw_destroy(&zfsvfs->z_fuid_lock); 1164eda14cbcSMatt Macy for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) 1165eda14cbcSMatt Macy mutex_destroy(&zfsvfs->z_hold_mtx[i]); 1166eda14cbcSMatt Macy dataset_kstats_destroy(&zfsvfs->z_kstat); 1167eda14cbcSMatt Macy kmem_free(zfsvfs, sizeof (zfsvfs_t)); 1168eda14cbcSMatt Macy } 1169eda14cbcSMatt Macy 1170eda14cbcSMatt Macy static void 1171eda14cbcSMatt Macy zfs_set_fuid_feature(zfsvfs_t *zfsvfs) 1172eda14cbcSMatt Macy { 1173eda14cbcSMatt Macy zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os); 1174eda14cbcSMatt Macy zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os); 1175eda14cbcSMatt Macy } 1176eda14cbcSMatt Macy 1177eda14cbcSMatt Macy static int 1178eda14cbcSMatt Macy zfs_domount(vfs_t *vfsp, char *osname) 1179eda14cbcSMatt Macy { 1180eda14cbcSMatt Macy uint64_t recordsize, fsid_guid; 1181eda14cbcSMatt Macy int error = 0; 1182eda14cbcSMatt Macy zfsvfs_t *zfsvfs; 1183eda14cbcSMatt Macy 118416038816SMartin Matuska ASSERT3P(vfsp, !=, NULL); 118516038816SMartin Matuska ASSERT3P(osname, !=, NULL); 1186eda14cbcSMatt Macy 1187eda14cbcSMatt Macy error = zfsvfs_create(osname, vfsp->mnt_flag & MNT_RDONLY, &zfsvfs); 1188eda14cbcSMatt Macy if (error) 1189eda14cbcSMatt Macy return (error); 1190eda14cbcSMatt Macy zfsvfs->z_vfs = vfsp; 1191eda14cbcSMatt Macy 1192eda14cbcSMatt Macy if ((error = dsl_prop_get_integer(osname, 1193eda14cbcSMatt Macy "recordsize", &recordsize, NULL))) 1194eda14cbcSMatt Macy goto out; 1195eda14cbcSMatt Macy zfsvfs->z_vfs->vfs_bsize = SPA_MINBLOCKSIZE; 1196eda14cbcSMatt Macy zfsvfs->z_vfs->mnt_stat.f_iosize = recordsize; 1197eda14cbcSMatt Macy 1198eda14cbcSMatt Macy vfsp->vfs_data = zfsvfs; 1199eda14cbcSMatt Macy vfsp->mnt_flag |= MNT_LOCAL; 1200eda14cbcSMatt Macy vfsp->mnt_kern_flag |= MNTK_LOOKUP_SHARED; 1201eda14cbcSMatt Macy vfsp->mnt_kern_flag |= MNTK_SHARED_WRITES; 1202eda14cbcSMatt Macy vfsp->mnt_kern_flag |= MNTK_EXTENDED_SHARED; 1203eda14cbcSMatt Macy /* 1204eda14cbcSMatt Macy * This can cause a loss of coherence between ARC and page cache 1205eda14cbcSMatt Macy * on ZoF - unclear if the problem is in FreeBSD or ZoF 1206eda14cbcSMatt Macy */ 1207eda14cbcSMatt Macy vfsp->mnt_kern_flag |= MNTK_NO_IOPF; /* vn_io_fault can be used */ 1208eda14cbcSMatt Macy vfsp->mnt_kern_flag |= MNTK_NOMSYNC; 1209eda14cbcSMatt Macy vfsp->mnt_kern_flag |= MNTK_VMSETSIZE_BUG; 1210eda14cbcSMatt Macy 1211eda14cbcSMatt Macy #if defined(_KERNEL) && !defined(KMEM_DEBUG) 1212eda14cbcSMatt Macy vfsp->mnt_kern_flag |= MNTK_FPLOOKUP; 1213eda14cbcSMatt Macy #endif 1214eda14cbcSMatt Macy /* 1215eda14cbcSMatt Macy * The fsid is 64 bits, composed of an 8-bit fs type, which 1216eda14cbcSMatt Macy * separates our fsid from any other filesystem types, and a 1217eda14cbcSMatt Macy * 56-bit objset unique ID. The objset unique ID is unique to 1218eda14cbcSMatt Macy * all objsets open on this system, provided by unique_create(). 1219eda14cbcSMatt Macy * The 8-bit fs type must be put in the low bits of fsid[1] 1220eda14cbcSMatt Macy * because that's where other Solaris filesystems put it. 1221eda14cbcSMatt Macy */ 1222eda14cbcSMatt Macy fsid_guid = dmu_objset_fsid_guid(zfsvfs->z_os); 122316038816SMartin Matuska ASSERT3U((fsid_guid & ~((1ULL << 56) - 1)), ==, 0); 1224eda14cbcSMatt Macy vfsp->vfs_fsid.val[0] = fsid_guid; 1225eda14cbcSMatt Macy vfsp->vfs_fsid.val[1] = ((fsid_guid >> 32) << 8) | 1226eda14cbcSMatt Macy (vfsp->mnt_vfc->vfc_typenum & 0xFF); 1227eda14cbcSMatt Macy 1228eda14cbcSMatt Macy /* 1229eda14cbcSMatt Macy * Set features for file system. 1230eda14cbcSMatt Macy */ 1231eda14cbcSMatt Macy zfs_set_fuid_feature(zfsvfs); 1232eda14cbcSMatt Macy 1233eda14cbcSMatt Macy if (dmu_objset_is_snapshot(zfsvfs->z_os)) { 1234eda14cbcSMatt Macy uint64_t pval; 1235eda14cbcSMatt Macy 1236eda14cbcSMatt Macy atime_changed_cb(zfsvfs, B_FALSE); 1237eda14cbcSMatt Macy readonly_changed_cb(zfsvfs, B_TRUE); 1238eda14cbcSMatt Macy if ((error = dsl_prop_get_integer(osname, 1239eda14cbcSMatt Macy "xattr", &pval, NULL))) 1240eda14cbcSMatt Macy goto out; 1241eda14cbcSMatt Macy xattr_changed_cb(zfsvfs, pval); 1242180f8225SMatt Macy if ((error = dsl_prop_get_integer(osname, 1243180f8225SMatt Macy "acltype", &pval, NULL))) 1244180f8225SMatt Macy goto out; 1245180f8225SMatt Macy acl_type_changed_cb(zfsvfs, pval); 1246eda14cbcSMatt Macy zfsvfs->z_issnap = B_TRUE; 1247eda14cbcSMatt Macy zfsvfs->z_os->os_sync = ZFS_SYNC_DISABLED; 1248eda14cbcSMatt Macy 1249eda14cbcSMatt Macy mutex_enter(&zfsvfs->z_os->os_user_ptr_lock); 1250eda14cbcSMatt Macy dmu_objset_set_user(zfsvfs->z_os, zfsvfs); 1251eda14cbcSMatt Macy mutex_exit(&zfsvfs->z_os->os_user_ptr_lock); 1252eda14cbcSMatt Macy } else { 1253eda14cbcSMatt Macy if ((error = zfsvfs_setup(zfsvfs, B_TRUE))) 1254eda14cbcSMatt Macy goto out; 1255eda14cbcSMatt Macy } 1256eda14cbcSMatt Macy 1257eda14cbcSMatt Macy vfs_mountedfrom(vfsp, osname); 1258eda14cbcSMatt Macy 1259eda14cbcSMatt Macy if (!zfsvfs->z_issnap) 1260eda14cbcSMatt Macy zfsctl_create(zfsvfs); 1261eda14cbcSMatt Macy out: 1262eda14cbcSMatt Macy if (error) { 1263eda14cbcSMatt Macy dmu_objset_disown(zfsvfs->z_os, B_TRUE, zfsvfs); 1264eda14cbcSMatt Macy zfsvfs_free(zfsvfs); 1265eda14cbcSMatt Macy } else { 1266eda14cbcSMatt Macy atomic_inc_32(&zfs_active_fs_count); 1267eda14cbcSMatt Macy } 1268eda14cbcSMatt Macy 1269eda14cbcSMatt Macy return (error); 1270eda14cbcSMatt Macy } 1271eda14cbcSMatt Macy 1272eda14cbcSMatt Macy static void 1273eda14cbcSMatt Macy zfs_unregister_callbacks(zfsvfs_t *zfsvfs) 1274eda14cbcSMatt Macy { 1275eda14cbcSMatt Macy objset_t *os = zfsvfs->z_os; 1276eda14cbcSMatt Macy 1277eda14cbcSMatt Macy if (!dmu_objset_is_snapshot(os)) 1278eda14cbcSMatt Macy dsl_prop_unregister_all(dmu_objset_ds(os), zfsvfs); 1279eda14cbcSMatt Macy } 1280eda14cbcSMatt Macy 1281eda14cbcSMatt Macy static int 1282eda14cbcSMatt Macy getpoolname(const char *osname, char *poolname) 1283eda14cbcSMatt Macy { 1284eda14cbcSMatt Macy char *p; 1285eda14cbcSMatt Macy 1286eda14cbcSMatt Macy p = strchr(osname, '/'); 1287eda14cbcSMatt Macy if (p == NULL) { 1288eda14cbcSMatt Macy if (strlen(osname) >= MAXNAMELEN) 1289eda14cbcSMatt Macy return (ENAMETOOLONG); 1290eda14cbcSMatt Macy (void) strcpy(poolname, osname); 1291eda14cbcSMatt Macy } else { 1292eda14cbcSMatt Macy if (p - osname >= MAXNAMELEN) 1293eda14cbcSMatt Macy return (ENAMETOOLONG); 1294be181ee2SMartin Matuska (void) strlcpy(poolname, osname, p - osname + 1); 1295eda14cbcSMatt Macy } 1296eda14cbcSMatt Macy return (0); 1297eda14cbcSMatt Macy } 1298eda14cbcSMatt Macy 1299653ed678SMariusz Zaborski static void 1300653ed678SMariusz Zaborski fetch_osname_options(char *name, bool *checkpointrewind) 1301653ed678SMariusz Zaborski { 1302653ed678SMariusz Zaborski 1303653ed678SMariusz Zaborski if (name[0] == '!') { 1304653ed678SMariusz Zaborski *checkpointrewind = true; 1305653ed678SMariusz Zaborski memmove(name, name + 1, strlen(name)); 1306653ed678SMariusz Zaborski } else { 1307653ed678SMariusz Zaborski *checkpointrewind = false; 1308653ed678SMariusz Zaborski } 1309653ed678SMariusz Zaborski } 1310653ed678SMariusz Zaborski 1311eda14cbcSMatt Macy static int 1312eda14cbcSMatt Macy zfs_mount(vfs_t *vfsp) 1313eda14cbcSMatt Macy { 1314eda14cbcSMatt Macy kthread_t *td = curthread; 1315eda14cbcSMatt Macy vnode_t *mvp = vfsp->mnt_vnodecovered; 1316eda14cbcSMatt Macy cred_t *cr = td->td_ucred; 1317eda14cbcSMatt Macy char *osname; 1318eda14cbcSMatt Macy int error = 0; 1319eda14cbcSMatt Macy int canwrite; 1320dbd5678dSMartin Matuska bool checkpointrewind, isctlsnap = false; 1321eda14cbcSMatt Macy 1322eda14cbcSMatt Macy if (vfs_getopt(vfsp->mnt_optnew, "from", (void **)&osname, NULL)) 1323eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 1324eda14cbcSMatt Macy 1325eda14cbcSMatt Macy /* 1326eda14cbcSMatt Macy * If full-owner-access is enabled and delegated administration is 1327eda14cbcSMatt Macy * turned on, we must set nosuid. 1328eda14cbcSMatt Macy */ 1329eda14cbcSMatt Macy if (zfs_super_owner && 1330eda14cbcSMatt Macy dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) != ECANCELED) { 1331eda14cbcSMatt Macy secpolicy_fs_mount_clearopts(cr, vfsp); 1332eda14cbcSMatt Macy } 1333eda14cbcSMatt Macy 1334653ed678SMariusz Zaborski fetch_osname_options(osname, &checkpointrewind); 1335bb2d13b6SMartin Matuska isctlsnap = (mvp != NULL && zfsctl_is_node(mvp) && 1336bb2d13b6SMartin Matuska strchr(osname, '@') != NULL); 1337653ed678SMariusz Zaborski 1338eda14cbcSMatt Macy /* 1339eda14cbcSMatt Macy * Check for mount privilege? 1340eda14cbcSMatt Macy * 1341eda14cbcSMatt Macy * If we don't have privilege then see if 1342eda14cbcSMatt Macy * we have local permission to allow it 1343eda14cbcSMatt Macy */ 1344eda14cbcSMatt Macy error = secpolicy_fs_mount(cr, mvp, vfsp); 1345dbd5678dSMartin Matuska if (error && isctlsnap) { 1346dbd5678dSMartin Matuska secpolicy_fs_mount_clearopts(cr, vfsp); 1347dbd5678dSMartin Matuska } else if (error) { 1348eda14cbcSMatt Macy if (dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) != 0) 1349eda14cbcSMatt Macy goto out; 1350eda14cbcSMatt Macy 1351eda14cbcSMatt Macy if (!(vfsp->vfs_flag & MS_REMOUNT)) { 1352eda14cbcSMatt Macy vattr_t vattr; 1353eda14cbcSMatt Macy 1354eda14cbcSMatt Macy /* 1355eda14cbcSMatt Macy * Make sure user is the owner of the mount point 1356eda14cbcSMatt Macy * or has sufficient privileges. 1357eda14cbcSMatt Macy */ 1358eda14cbcSMatt Macy 1359eda14cbcSMatt Macy vattr.va_mask = AT_UID; 1360eda14cbcSMatt Macy 1361eda14cbcSMatt Macy vn_lock(mvp, LK_SHARED | LK_RETRY); 1362eda14cbcSMatt Macy if (VOP_GETATTR(mvp, &vattr, cr)) { 1363ce4dcb97SMartin Matuska VOP_UNLOCK(mvp); 1364eda14cbcSMatt Macy goto out; 1365eda14cbcSMatt Macy } 1366eda14cbcSMatt Macy 1367eda14cbcSMatt Macy if (secpolicy_vnode_owner(mvp, cr, vattr.va_uid) != 0 && 1368eda14cbcSMatt Macy VOP_ACCESS(mvp, VWRITE, cr, td) != 0) { 1369ce4dcb97SMartin Matuska VOP_UNLOCK(mvp); 1370eda14cbcSMatt Macy goto out; 1371eda14cbcSMatt Macy } 1372ce4dcb97SMartin Matuska VOP_UNLOCK(mvp); 1373eda14cbcSMatt Macy } 1374eda14cbcSMatt Macy 1375eda14cbcSMatt Macy secpolicy_fs_mount_clearopts(cr, vfsp); 1376eda14cbcSMatt Macy } 1377eda14cbcSMatt Macy 1378eda14cbcSMatt Macy /* 1379eda14cbcSMatt Macy * Refuse to mount a filesystem if we are in a local zone and the 1380eda14cbcSMatt Macy * dataset is not visible. 1381eda14cbcSMatt Macy */ 1382eda14cbcSMatt Macy if (!INGLOBALZONE(curproc) && 1383eda14cbcSMatt Macy (!zone_dataset_visible(osname, &canwrite) || !canwrite)) { 1384dbd5678dSMartin Matuska boolean_t mount_snapshot = B_FALSE; 1385dbd5678dSMartin Matuska 1386dbd5678dSMartin Matuska /* 1387dbd5678dSMartin Matuska * Snapshots may be mounted in .zfs for unjailed datasets 1388dbd5678dSMartin Matuska * if allowed by the jail param zfs.mount_snapshot. 1389dbd5678dSMartin Matuska */ 1390dbd5678dSMartin Matuska if (isctlsnap) { 1391dbd5678dSMartin Matuska struct prison *pr; 1392dbd5678dSMartin Matuska struct zfs_jailparam *zjp; 1393dbd5678dSMartin Matuska 1394dbd5678dSMartin Matuska pr = curthread->td_ucred->cr_prison; 1395dbd5678dSMartin Matuska mtx_lock(&pr->pr_mtx); 1396dbd5678dSMartin Matuska zjp = osd_jail_get(pr, zfs_jailparam_slot); 1397dbd5678dSMartin Matuska mtx_unlock(&pr->pr_mtx); 1398dbd5678dSMartin Matuska if (zjp && zjp->mount_snapshot) 1399dbd5678dSMartin Matuska mount_snapshot = B_TRUE; 1400dbd5678dSMartin Matuska } 1401dbd5678dSMartin Matuska if (!mount_snapshot) { 1402eda14cbcSMatt Macy error = SET_ERROR(EPERM); 1403eda14cbcSMatt Macy goto out; 1404eda14cbcSMatt Macy } 1405dbd5678dSMartin Matuska } 1406eda14cbcSMatt Macy 1407eda14cbcSMatt Macy vfsp->vfs_flag |= MNT_NFS4ACLS; 1408eda14cbcSMatt Macy 1409eda14cbcSMatt Macy /* 1410eda14cbcSMatt Macy * When doing a remount, we simply refresh our temporary properties 1411eda14cbcSMatt Macy * according to those options set in the current VFS options. 1412eda14cbcSMatt Macy */ 1413eda14cbcSMatt Macy if (vfsp->vfs_flag & MS_REMOUNT) { 1414eda14cbcSMatt Macy zfsvfs_t *zfsvfs = vfsp->vfs_data; 1415eda14cbcSMatt Macy 1416eda14cbcSMatt Macy /* 1417eda14cbcSMatt Macy * Refresh mount options with z_teardown_lock blocking I/O while 1418eda14cbcSMatt Macy * the filesystem is in an inconsistent state. 1419eda14cbcSMatt Macy * The lock also serializes this code with filesystem 1420eda14cbcSMatt Macy * manipulations between entry to zfs_suspend_fs() and return 1421eda14cbcSMatt Macy * from zfs_resume_fs(). 1422eda14cbcSMatt Macy */ 14234008dd45SMateusz Guzik ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, FTAG); 1424eda14cbcSMatt Macy zfs_unregister_callbacks(zfsvfs); 1425eda14cbcSMatt Macy error = zfs_register_callbacks(vfsp); 14264008dd45SMateusz Guzik ZFS_TEARDOWN_EXIT(zfsvfs, FTAG); 1427eda14cbcSMatt Macy goto out; 1428eda14cbcSMatt Macy } 1429eda14cbcSMatt Macy 1430eda14cbcSMatt Macy /* Initial root mount: try hard to import the requested root pool. */ 1431eda14cbcSMatt Macy if ((vfsp->vfs_flag & MNT_ROOTFS) != 0 && 1432eda14cbcSMatt Macy (vfsp->vfs_flag & MNT_UPDATE) == 0) { 1433eda14cbcSMatt Macy char pname[MAXNAMELEN]; 1434eda14cbcSMatt Macy 1435eda14cbcSMatt Macy error = getpoolname(osname, pname); 1436eda14cbcSMatt Macy if (error == 0) 1437653ed678SMariusz Zaborski error = spa_import_rootpool(pname, checkpointrewind); 1438eda14cbcSMatt Macy if (error) 1439eda14cbcSMatt Macy goto out; 1440eda14cbcSMatt Macy } 1441eda14cbcSMatt Macy DROP_GIANT(); 1442eda14cbcSMatt Macy error = zfs_domount(vfsp, osname); 1443eda14cbcSMatt Macy PICKUP_GIANT(); 1444eda14cbcSMatt Macy 1445eda14cbcSMatt Macy out: 1446eda14cbcSMatt Macy return (error); 1447eda14cbcSMatt Macy } 1448eda14cbcSMatt Macy 1449eda14cbcSMatt Macy static int 1450eda14cbcSMatt Macy zfs_statfs(vfs_t *vfsp, struct statfs *statp) 1451eda14cbcSMatt Macy { 1452eda14cbcSMatt Macy zfsvfs_t *zfsvfs = vfsp->vfs_data; 1453eda14cbcSMatt Macy uint64_t refdbytes, availbytes, usedobjs, availobjs; 1454c7046f76SMartin Matuska int error; 1455eda14cbcSMatt Macy 1456eda14cbcSMatt Macy statp->f_version = STATFS_VERSION; 1457eda14cbcSMatt Macy 1458c7046f76SMartin Matuska if ((error = zfs_enter(zfsvfs, FTAG)) != 0) 1459c7046f76SMartin Matuska return (error); 1460eda14cbcSMatt Macy 1461eda14cbcSMatt Macy dmu_objset_space(zfsvfs->z_os, 1462eda14cbcSMatt Macy &refdbytes, &availbytes, &usedobjs, &availobjs); 1463eda14cbcSMatt Macy 1464eda14cbcSMatt Macy /* 1465eda14cbcSMatt Macy * The underlying storage pool actually uses multiple block sizes. 1466eda14cbcSMatt Macy * We report the fragsize as the smallest block size we support, 1467eda14cbcSMatt Macy * and we report our blocksize as the filesystem's maximum blocksize. 1468eda14cbcSMatt Macy */ 1469eda14cbcSMatt Macy statp->f_bsize = SPA_MINBLOCKSIZE; 1470eda14cbcSMatt Macy statp->f_iosize = zfsvfs->z_vfs->mnt_stat.f_iosize; 1471eda14cbcSMatt Macy 1472eda14cbcSMatt Macy /* 1473eda14cbcSMatt Macy * The following report "total" blocks of various kinds in the 1474eda14cbcSMatt Macy * file system, but reported in terms of f_frsize - the 1475eda14cbcSMatt Macy * "fragment" size. 1476eda14cbcSMatt Macy */ 1477eda14cbcSMatt Macy 1478eda14cbcSMatt Macy statp->f_blocks = (refdbytes + availbytes) >> SPA_MINBLOCKSHIFT; 1479eda14cbcSMatt Macy statp->f_bfree = availbytes / statp->f_bsize; 1480eda14cbcSMatt Macy statp->f_bavail = statp->f_bfree; /* no root reservation */ 1481eda14cbcSMatt Macy 1482eda14cbcSMatt Macy /* 1483eda14cbcSMatt Macy * statvfs() should really be called statufs(), because it assumes 1484eda14cbcSMatt Macy * static metadata. ZFS doesn't preallocate files, so the best 1485eda14cbcSMatt Macy * we can do is report the max that could possibly fit in f_files, 1486eda14cbcSMatt Macy * and that minus the number actually used in f_ffree. 1487eda14cbcSMatt Macy * For f_ffree, report the smaller of the number of object available 1488eda14cbcSMatt Macy * and the number of blocks (each object will take at least a block). 1489eda14cbcSMatt Macy */ 1490eda14cbcSMatt Macy statp->f_ffree = MIN(availobjs, statp->f_bfree); 1491eda14cbcSMatt Macy statp->f_files = statp->f_ffree + usedobjs; 1492eda14cbcSMatt Macy 1493eda14cbcSMatt Macy /* 1494eda14cbcSMatt Macy * We're a zfs filesystem. 1495eda14cbcSMatt Macy */ 1496eda14cbcSMatt Macy strlcpy(statp->f_fstypename, "zfs", 1497eda14cbcSMatt Macy sizeof (statp->f_fstypename)); 1498eda14cbcSMatt Macy 1499eda14cbcSMatt Macy strlcpy(statp->f_mntfromname, vfsp->mnt_stat.f_mntfromname, 1500eda14cbcSMatt Macy sizeof (statp->f_mntfromname)); 1501eda14cbcSMatt Macy strlcpy(statp->f_mntonname, vfsp->mnt_stat.f_mntonname, 1502eda14cbcSMatt Macy sizeof (statp->f_mntonname)); 1503eda14cbcSMatt Macy 15047a7741afSMartin Matuska statp->f_namemax = 15057a7741afSMartin Matuska zfsvfs->z_longname ? (ZAP_MAXNAMELEN_NEW - 1) : (MAXNAMELEN - 1); 1506eda14cbcSMatt Macy 1507c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 1508eda14cbcSMatt Macy return (0); 1509eda14cbcSMatt Macy } 1510eda14cbcSMatt Macy 1511eda14cbcSMatt Macy static int 1512eda14cbcSMatt Macy zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp) 1513eda14cbcSMatt Macy { 1514eda14cbcSMatt Macy zfsvfs_t *zfsvfs = vfsp->vfs_data; 1515eda14cbcSMatt Macy znode_t *rootzp; 1516eda14cbcSMatt Macy int error; 1517eda14cbcSMatt Macy 1518c7046f76SMartin Matuska if ((error = zfs_enter(zfsvfs, FTAG)) != 0) 1519c7046f76SMartin Matuska return (error); 1520eda14cbcSMatt Macy 1521eda14cbcSMatt Macy error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); 1522eda14cbcSMatt Macy if (error == 0) 1523eda14cbcSMatt Macy *vpp = ZTOV(rootzp); 1524eda14cbcSMatt Macy 1525c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 1526eda14cbcSMatt Macy 1527eda14cbcSMatt Macy if (error == 0) { 1528eda14cbcSMatt Macy error = vn_lock(*vpp, flags); 1529eda14cbcSMatt Macy if (error != 0) { 1530eda14cbcSMatt Macy VN_RELE(*vpp); 1531eda14cbcSMatt Macy *vpp = NULL; 1532eda14cbcSMatt Macy } 1533eda14cbcSMatt Macy } 1534eda14cbcSMatt Macy return (error); 1535eda14cbcSMatt Macy } 1536eda14cbcSMatt Macy 1537eda14cbcSMatt Macy /* 1538eda14cbcSMatt Macy * Teardown the zfsvfs::z_os. 1539eda14cbcSMatt Macy * 1540eda14cbcSMatt Macy * Note, if 'unmounting' is FALSE, we return with the 'z_teardown_lock' 1541eda14cbcSMatt Macy * and 'z_teardown_inactive_lock' held. 1542eda14cbcSMatt Macy */ 1543eda14cbcSMatt Macy static int 1544eda14cbcSMatt Macy zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting) 1545eda14cbcSMatt Macy { 1546eda14cbcSMatt Macy znode_t *zp; 1547eda14cbcSMatt Macy dsl_dir_t *dd; 1548eda14cbcSMatt Macy 1549eda14cbcSMatt Macy /* 1550eda14cbcSMatt Macy * If someone has not already unmounted this file system, 1551eda14cbcSMatt Macy * drain the zrele_taskq to ensure all active references to the 1552eda14cbcSMatt Macy * zfsvfs_t have been handled only then can it be safely destroyed. 1553eda14cbcSMatt Macy */ 1554eda14cbcSMatt Macy if (zfsvfs->z_os) { 1555eda14cbcSMatt Macy /* 1556eda14cbcSMatt Macy * If we're unmounting we have to wait for the list to 1557eda14cbcSMatt Macy * drain completely. 1558eda14cbcSMatt Macy * 1559eda14cbcSMatt Macy * If we're not unmounting there's no guarantee the list 1560eda14cbcSMatt Macy * will drain completely, but zreles run from the taskq 1561eda14cbcSMatt Macy * may add the parents of dir-based xattrs to the taskq 1562eda14cbcSMatt Macy * so we want to wait for these. 1563eda14cbcSMatt Macy * 156449874af3SMateusz Guzik * We can safely check z_all_znodes for being empty because the 156549874af3SMateusz Guzik * VFS has already blocked operations which add to it. 1566eda14cbcSMatt Macy */ 1567eda14cbcSMatt Macy int round = 0; 156849874af3SMateusz Guzik while (!list_is_empty(&zfsvfs->z_all_znodes)) { 1569eda14cbcSMatt Macy taskq_wait_outstanding(dsl_pool_zrele_taskq( 1570eda14cbcSMatt Macy dmu_objset_pool(zfsvfs->z_os)), 0); 1571eda14cbcSMatt Macy if (++round > 1 && !unmounting) 1572eda14cbcSMatt Macy break; 1573eda14cbcSMatt Macy } 1574eda14cbcSMatt Macy } 15754008dd45SMateusz Guzik ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, FTAG); 1576eda14cbcSMatt Macy 1577eda14cbcSMatt Macy if (!unmounting) { 1578eda14cbcSMatt Macy /* 1579eda14cbcSMatt Macy * We purge the parent filesystem's vfsp as the parent 1580eda14cbcSMatt Macy * filesystem and all of its snapshots have their vnode's 1581eda14cbcSMatt Macy * v_vfsp set to the parent's filesystem's vfsp. Note, 1582eda14cbcSMatt Macy * 'z_parent' is self referential for non-snapshots. 1583eda14cbcSMatt Macy */ 1584eda14cbcSMatt Macy #ifdef FREEBSD_NAMECACHE 1585a3d9bf49SMateusz Guzik cache_purgevfs(zfsvfs->z_parent->z_vfs); 1586eda14cbcSMatt Macy #endif 1587eda14cbcSMatt Macy } 1588eda14cbcSMatt Macy 1589eda14cbcSMatt Macy /* 1590eda14cbcSMatt Macy * Close the zil. NB: Can't close the zil while zfs_inactive 1591eda14cbcSMatt Macy * threads are blocked as zil_close can call zfs_inactive. 1592eda14cbcSMatt Macy */ 1593eda14cbcSMatt Macy if (zfsvfs->z_log) { 1594eda14cbcSMatt Macy zil_close(zfsvfs->z_log); 1595eda14cbcSMatt Macy zfsvfs->z_log = NULL; 1596eda14cbcSMatt Macy } 1597eda14cbcSMatt Macy 1598ae5642a6SMateusz Guzik ZFS_TEARDOWN_INACTIVE_ENTER_WRITE(zfsvfs); 1599eda14cbcSMatt Macy 1600eda14cbcSMatt Macy /* 1601eda14cbcSMatt Macy * If we are not unmounting (ie: online recv) and someone already 1602eda14cbcSMatt Macy * unmounted this file system while we were doing the switcheroo, 1603eda14cbcSMatt Macy * or a reopen of z_os failed then just bail out now. 1604eda14cbcSMatt Macy */ 1605eda14cbcSMatt Macy if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) { 1606ae5642a6SMateusz Guzik ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs); 16074008dd45SMateusz Guzik ZFS_TEARDOWN_EXIT(zfsvfs, FTAG); 1608eda14cbcSMatt Macy return (SET_ERROR(EIO)); 1609eda14cbcSMatt Macy } 1610eda14cbcSMatt Macy 1611eda14cbcSMatt Macy /* 1612eda14cbcSMatt Macy * At this point there are no vops active, and any new vops will 1613eda14cbcSMatt Macy * fail with EIO since we have z_teardown_lock for writer (only 1614eda14cbcSMatt Macy * relevant for forced unmount). 1615eda14cbcSMatt Macy * 1616eda14cbcSMatt Macy * Release all holds on dbufs. 1617eda14cbcSMatt Macy */ 1618eda14cbcSMatt Macy mutex_enter(&zfsvfs->z_znodes_lock); 1619eda14cbcSMatt Macy for (zp = list_head(&zfsvfs->z_all_znodes); zp != NULL; 162016038816SMartin Matuska zp = list_next(&zfsvfs->z_all_znodes, zp)) { 162116038816SMartin Matuska if (zp->z_sa_hdl != NULL) { 1622eda14cbcSMatt Macy zfs_znode_dmu_fini(zp); 1623eda14cbcSMatt Macy } 162416038816SMartin Matuska } 1625eda14cbcSMatt Macy mutex_exit(&zfsvfs->z_znodes_lock); 1626eda14cbcSMatt Macy 1627eda14cbcSMatt Macy /* 1628eda14cbcSMatt Macy * If we are unmounting, set the unmounted flag and let new vops 1629eda14cbcSMatt Macy * unblock. zfs_inactive will have the unmounted behavior, and all 1630eda14cbcSMatt Macy * other vops will fail with EIO. 1631eda14cbcSMatt Macy */ 1632eda14cbcSMatt Macy if (unmounting) { 1633eda14cbcSMatt Macy zfsvfs->z_unmounted = B_TRUE; 1634ae5642a6SMateusz Guzik ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs); 16354008dd45SMateusz Guzik ZFS_TEARDOWN_EXIT(zfsvfs, FTAG); 1636eda14cbcSMatt Macy } 1637eda14cbcSMatt Macy 1638eda14cbcSMatt Macy /* 1639eda14cbcSMatt Macy * z_os will be NULL if there was an error in attempting to reopen 1640eda14cbcSMatt Macy * zfsvfs, so just return as the properties had already been 1641eda14cbcSMatt Macy * unregistered and cached data had been evicted before. 1642eda14cbcSMatt Macy */ 1643eda14cbcSMatt Macy if (zfsvfs->z_os == NULL) 1644eda14cbcSMatt Macy return (0); 1645eda14cbcSMatt Macy 1646eda14cbcSMatt Macy /* 1647eda14cbcSMatt Macy * Unregister properties. 1648eda14cbcSMatt Macy */ 1649eda14cbcSMatt Macy zfs_unregister_callbacks(zfsvfs); 1650eda14cbcSMatt Macy 1651eda14cbcSMatt Macy /* 1652ce4dcb97SMartin Matuska * Evict cached data. We must write out any dirty data before 1653ce4dcb97SMartin Matuska * disowning the dataset. 1654eda14cbcSMatt Macy */ 1655ce4dcb97SMartin Matuska objset_t *os = zfsvfs->z_os; 1656ce4dcb97SMartin Matuska boolean_t os_dirty = B_FALSE; 1657ce4dcb97SMartin Matuska for (int t = 0; t < TXG_SIZE; t++) { 1658ce4dcb97SMartin Matuska if (dmu_objset_is_dirty(os, t)) { 1659ce4dcb97SMartin Matuska os_dirty = B_TRUE; 1660ce4dcb97SMartin Matuska break; 1661ce4dcb97SMartin Matuska } 1662ce4dcb97SMartin Matuska } 1663ce4dcb97SMartin Matuska if (!zfs_is_readonly(zfsvfs) && os_dirty) 1664eda14cbcSMatt Macy txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0); 1665eda14cbcSMatt Macy dmu_objset_evict_dbufs(zfsvfs->z_os); 1666eda14cbcSMatt Macy dd = zfsvfs->z_os->os_dsl_dataset->ds_dir; 1667eda14cbcSMatt Macy dsl_dir_cancel_waiters(dd); 1668eda14cbcSMatt Macy 1669eda14cbcSMatt Macy return (0); 1670eda14cbcSMatt Macy } 1671eda14cbcSMatt Macy 1672eda14cbcSMatt Macy static int 1673eda14cbcSMatt Macy zfs_umount(vfs_t *vfsp, int fflag) 1674eda14cbcSMatt Macy { 1675eda14cbcSMatt Macy kthread_t *td = curthread; 1676eda14cbcSMatt Macy zfsvfs_t *zfsvfs = vfsp->vfs_data; 1677eda14cbcSMatt Macy objset_t *os; 1678eda14cbcSMatt Macy cred_t *cr = td->td_ucred; 1679eda14cbcSMatt Macy int ret; 1680eda14cbcSMatt Macy 1681eda14cbcSMatt Macy ret = secpolicy_fs_unmount(cr, vfsp); 1682eda14cbcSMatt Macy if (ret) { 1683eda14cbcSMatt Macy if (dsl_deleg_access((char *)vfsp->vfs_resource, 1684eda14cbcSMatt Macy ZFS_DELEG_PERM_MOUNT, cr)) 1685eda14cbcSMatt Macy return (ret); 1686eda14cbcSMatt Macy } 1687eda14cbcSMatt Macy 1688eda14cbcSMatt Macy /* 1689eda14cbcSMatt Macy * Unmount any snapshots mounted under .zfs before unmounting the 1690eda14cbcSMatt Macy * dataset itself. 1691eda14cbcSMatt Macy */ 1692eda14cbcSMatt Macy if (zfsvfs->z_ctldir != NULL) { 1693eda14cbcSMatt Macy if ((ret = zfsctl_umount_snapshots(vfsp, fflag, cr)) != 0) 1694eda14cbcSMatt Macy return (ret); 1695eda14cbcSMatt Macy } 1696eda14cbcSMatt Macy 1697eda14cbcSMatt Macy if (fflag & MS_FORCE) { 1698eda14cbcSMatt Macy /* 1699eda14cbcSMatt Macy * Mark file system as unmounted before calling 1700eda14cbcSMatt Macy * vflush(FORCECLOSE). This way we ensure no future vnops 1701eda14cbcSMatt Macy * will be called and risk operating on DOOMED vnodes. 1702eda14cbcSMatt Macy */ 17034008dd45SMateusz Guzik ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, FTAG); 1704eda14cbcSMatt Macy zfsvfs->z_unmounted = B_TRUE; 17054008dd45SMateusz Guzik ZFS_TEARDOWN_EXIT(zfsvfs, FTAG); 1706eda14cbcSMatt Macy } 1707eda14cbcSMatt Macy 1708eda14cbcSMatt Macy /* 1709eda14cbcSMatt Macy * Flush all the files. 1710eda14cbcSMatt Macy */ 1711eda14cbcSMatt Macy ret = vflush(vfsp, 0, (fflag & MS_FORCE) ? FORCECLOSE : 0, td); 1712eda14cbcSMatt Macy if (ret != 0) 1713eda14cbcSMatt Macy return (ret); 1714eda14cbcSMatt Macy while (taskqueue_cancel(zfsvfs_taskq->tq_queue, 1715eda14cbcSMatt Macy &zfsvfs->z_unlinked_drain_task, NULL) != 0) 1716eda14cbcSMatt Macy taskqueue_drain(zfsvfs_taskq->tq_queue, 1717eda14cbcSMatt Macy &zfsvfs->z_unlinked_drain_task); 1718eda14cbcSMatt Macy 171916038816SMartin Matuska VERIFY0(zfsvfs_teardown(zfsvfs, B_TRUE)); 1720eda14cbcSMatt Macy os = zfsvfs->z_os; 1721eda14cbcSMatt Macy 1722eda14cbcSMatt Macy /* 1723eda14cbcSMatt Macy * z_os will be NULL if there was an error in 1724eda14cbcSMatt Macy * attempting to reopen zfsvfs. 1725eda14cbcSMatt Macy */ 1726eda14cbcSMatt Macy if (os != NULL) { 1727eda14cbcSMatt Macy /* 1728eda14cbcSMatt Macy * Unset the objset user_ptr. 1729eda14cbcSMatt Macy */ 1730eda14cbcSMatt Macy mutex_enter(&os->os_user_ptr_lock); 1731eda14cbcSMatt Macy dmu_objset_set_user(os, NULL); 1732eda14cbcSMatt Macy mutex_exit(&os->os_user_ptr_lock); 1733eda14cbcSMatt Macy 1734eda14cbcSMatt Macy /* 1735eda14cbcSMatt Macy * Finally release the objset 1736eda14cbcSMatt Macy */ 1737eda14cbcSMatt Macy dmu_objset_disown(os, B_TRUE, zfsvfs); 1738eda14cbcSMatt Macy } 1739eda14cbcSMatt Macy 1740eda14cbcSMatt Macy /* 1741eda14cbcSMatt Macy * We can now safely destroy the '.zfs' directory node. 1742eda14cbcSMatt Macy */ 1743eda14cbcSMatt Macy if (zfsvfs->z_ctldir != NULL) 1744eda14cbcSMatt Macy zfsctl_destroy(zfsvfs); 1745eda14cbcSMatt Macy zfs_freevfs(vfsp); 1746eda14cbcSMatt Macy 1747eda14cbcSMatt Macy return (0); 1748eda14cbcSMatt Macy } 1749eda14cbcSMatt Macy 1750eda14cbcSMatt Macy static int 1751eda14cbcSMatt Macy zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp) 1752eda14cbcSMatt Macy { 1753eda14cbcSMatt Macy zfsvfs_t *zfsvfs = vfsp->vfs_data; 1754eda14cbcSMatt Macy znode_t *zp; 1755eda14cbcSMatt Macy int err; 1756eda14cbcSMatt Macy 1757eda14cbcSMatt Macy /* 1758eda14cbcSMatt Macy * zfs_zget() can't operate on virtual entries like .zfs/ or 1759eda14cbcSMatt Macy * .zfs/snapshot/ directories, that's why we return EOPNOTSUPP. 1760eda14cbcSMatt Macy * This will make NFS to switch to LOOKUP instead of using VGET. 1761eda14cbcSMatt Macy */ 1762eda14cbcSMatt Macy if (ino == ZFSCTL_INO_ROOT || ino == ZFSCTL_INO_SNAPDIR || 1763eda14cbcSMatt Macy (zfsvfs->z_shares_dir != 0 && ino == zfsvfs->z_shares_dir)) 1764eda14cbcSMatt Macy return (EOPNOTSUPP); 1765eda14cbcSMatt Macy 1766c7046f76SMartin Matuska if ((err = zfs_enter(zfsvfs, FTAG)) != 0) 1767c7046f76SMartin Matuska return (err); 1768eda14cbcSMatt Macy err = zfs_zget(zfsvfs, ino, &zp); 1769eda14cbcSMatt Macy if (err == 0 && zp->z_unlinked) { 1770eda14cbcSMatt Macy vrele(ZTOV(zp)); 1771eda14cbcSMatt Macy err = EINVAL; 1772eda14cbcSMatt Macy } 1773eda14cbcSMatt Macy if (err == 0) 1774eda14cbcSMatt Macy *vpp = ZTOV(zp); 1775c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 1776eda14cbcSMatt Macy if (err == 0) { 1777eda14cbcSMatt Macy err = vn_lock(*vpp, flags); 1778eda14cbcSMatt Macy if (err != 0) 1779eda14cbcSMatt Macy vrele(*vpp); 1780eda14cbcSMatt Macy } 1781eda14cbcSMatt Macy if (err != 0) 1782eda14cbcSMatt Macy *vpp = NULL; 1783eda14cbcSMatt Macy return (err); 1784eda14cbcSMatt Macy } 1785eda14cbcSMatt Macy 1786eda14cbcSMatt Macy static int 1787eda14cbcSMatt Macy zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, uint64_t *extflagsp, 1788eda14cbcSMatt Macy struct ucred **credanonp, int *numsecflavors, int *secflavors) 1789eda14cbcSMatt Macy { 1790eda14cbcSMatt Macy zfsvfs_t *zfsvfs = vfsp->vfs_data; 1791eda14cbcSMatt Macy 1792eda14cbcSMatt Macy /* 1793eda14cbcSMatt Macy * If this is regular file system vfsp is the same as 1794eda14cbcSMatt Macy * zfsvfs->z_parent->z_vfs, but if it is snapshot, 1795eda14cbcSMatt Macy * zfsvfs->z_parent->z_vfs represents parent file system 1796eda14cbcSMatt Macy * which we have to use here, because only this file system 1797eda14cbcSMatt Macy * has mnt_export configured. 1798eda14cbcSMatt Macy */ 1799eda14cbcSMatt Macy return (vfs_stdcheckexp(zfsvfs->z_parent->z_vfs, nam, extflagsp, 1800eda14cbcSMatt Macy credanonp, numsecflavors, secflavors)); 1801eda14cbcSMatt Macy } 1802eda14cbcSMatt Macy 1803c03c5b1cSMartin Matuska _Static_assert(sizeof (struct fid) >= SHORT_FID_LEN, 1804c03c5b1cSMartin Matuska "struct fid bigger than SHORT_FID_LEN"); 1805c03c5b1cSMartin Matuska _Static_assert(sizeof (struct fid) >= LONG_FID_LEN, 1806c03c5b1cSMartin Matuska "struct fid bigger than LONG_FID_LEN"); 1807eda14cbcSMatt Macy 1808eda14cbcSMatt Macy static int 1809eda14cbcSMatt Macy zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp) 1810eda14cbcSMatt Macy { 1811eda14cbcSMatt Macy struct componentname cn; 1812eda14cbcSMatt Macy zfsvfs_t *zfsvfs = vfsp->vfs_data; 1813eda14cbcSMatt Macy znode_t *zp; 1814eda14cbcSMatt Macy vnode_t *dvp; 1815eda14cbcSMatt Macy uint64_t object = 0; 1816eda14cbcSMatt Macy uint64_t fid_gen = 0; 1817e92ffd9bSMartin Matuska uint64_t setgen = 0; 1818eda14cbcSMatt Macy uint64_t gen_mask; 1819eda14cbcSMatt Macy uint64_t zp_gen; 1820eda14cbcSMatt Macy int i, err; 1821eda14cbcSMatt Macy 1822eda14cbcSMatt Macy *vpp = NULL; 1823eda14cbcSMatt Macy 1824c7046f76SMartin Matuska if ((err = zfs_enter(zfsvfs, FTAG)) != 0) 1825c7046f76SMartin Matuska return (err); 1826eda14cbcSMatt Macy 1827eda14cbcSMatt Macy /* 1828eda14cbcSMatt Macy * On FreeBSD we can get snapshot's mount point or its parent file 1829eda14cbcSMatt Macy * system mount point depending if snapshot is already mounted or not. 1830eda14cbcSMatt Macy */ 1831eda14cbcSMatt Macy if (zfsvfs->z_parent == zfsvfs && fidp->fid_len == LONG_FID_LEN) { 1832eda14cbcSMatt Macy zfid_long_t *zlfid = (zfid_long_t *)fidp; 1833eda14cbcSMatt Macy uint64_t objsetid = 0; 1834eda14cbcSMatt Macy 1835eda14cbcSMatt Macy for (i = 0; i < sizeof (zlfid->zf_setid); i++) 1836eda14cbcSMatt Macy objsetid |= ((uint64_t)zlfid->zf_setid[i]) << (8 * i); 1837eda14cbcSMatt Macy 1838eda14cbcSMatt Macy for (i = 0; i < sizeof (zlfid->zf_setgen); i++) 1839eda14cbcSMatt Macy setgen |= ((uint64_t)zlfid->zf_setgen[i]) << (8 * i); 1840eda14cbcSMatt Macy 1841c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 1842eda14cbcSMatt Macy 1843eda14cbcSMatt Macy err = zfsctl_lookup_objset(vfsp, objsetid, &zfsvfs); 1844eda14cbcSMatt Macy if (err) 1845eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 1846c7046f76SMartin Matuska if ((err = zfs_enter(zfsvfs, FTAG)) != 0) 1847c7046f76SMartin Matuska return (err); 1848eda14cbcSMatt Macy } 1849eda14cbcSMatt Macy 1850eda14cbcSMatt Macy if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) { 1851eda14cbcSMatt Macy zfid_short_t *zfid = (zfid_short_t *)fidp; 1852eda14cbcSMatt Macy 1853eda14cbcSMatt Macy for (i = 0; i < sizeof (zfid->zf_object); i++) 1854eda14cbcSMatt Macy object |= ((uint64_t)zfid->zf_object[i]) << (8 * i); 1855eda14cbcSMatt Macy 1856eda14cbcSMatt Macy for (i = 0; i < sizeof (zfid->zf_gen); i++) 1857eda14cbcSMatt Macy fid_gen |= ((uint64_t)zfid->zf_gen[i]) << (8 * i); 1858eda14cbcSMatt Macy } else { 1859c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 1860eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 1861eda14cbcSMatt Macy } 1862eda14cbcSMatt Macy 18636fe0a6c8SMark Johnston if (fidp->fid_len == LONG_FID_LEN && setgen != 0) { 18646fe0a6c8SMark Johnston zfs_exit(zfsvfs, FTAG); 1865e92ffd9bSMartin Matuska dprintf("snapdir fid: fid_gen (%llu) and setgen (%llu)\n", 1866e92ffd9bSMartin Matuska (u_longlong_t)fid_gen, (u_longlong_t)setgen); 1867e92ffd9bSMartin Matuska return (SET_ERROR(EINVAL)); 1868e92ffd9bSMartin Matuska } 1869e92ffd9bSMartin Matuska 1870eda14cbcSMatt Macy /* 1871eda14cbcSMatt Macy * A zero fid_gen means we are in .zfs or the .zfs/snapshot 1872eda14cbcSMatt Macy * directory tree. If the object == zfsvfs->z_shares_dir, then 1873eda14cbcSMatt Macy * we are in the .zfs/shares directory tree. 1874eda14cbcSMatt Macy */ 1875eda14cbcSMatt Macy if ((fid_gen == 0 && 1876eda14cbcSMatt Macy (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) || 1877eda14cbcSMatt Macy (zfsvfs->z_shares_dir != 0 && object == zfsvfs->z_shares_dir)) { 1878c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 1879eda14cbcSMatt Macy VERIFY0(zfsctl_root(zfsvfs, LK_SHARED, &dvp)); 1880eda14cbcSMatt Macy if (object == ZFSCTL_INO_SNAPDIR) { 1881eda14cbcSMatt Macy cn.cn_nameptr = "snapshot"; 1882eda14cbcSMatt Macy cn.cn_namelen = strlen(cn.cn_nameptr); 1883eda14cbcSMatt Macy cn.cn_nameiop = LOOKUP; 1884eda14cbcSMatt Macy cn.cn_flags = ISLASTCN | LOCKLEAF; 1885eda14cbcSMatt Macy cn.cn_lkflags = flags; 1886eda14cbcSMatt Macy VERIFY0(VOP_LOOKUP(dvp, vpp, &cn)); 1887eda14cbcSMatt Macy vput(dvp); 1888eda14cbcSMatt Macy } else if (object == zfsvfs->z_shares_dir) { 1889eda14cbcSMatt Macy /* 1890eda14cbcSMatt Macy * XXX This branch must not be taken, 1891eda14cbcSMatt Macy * if it is, then the lookup below will 1892eda14cbcSMatt Macy * explode. 1893eda14cbcSMatt Macy */ 1894eda14cbcSMatt Macy cn.cn_nameptr = "shares"; 1895eda14cbcSMatt Macy cn.cn_namelen = strlen(cn.cn_nameptr); 1896eda14cbcSMatt Macy cn.cn_nameiop = LOOKUP; 1897eda14cbcSMatt Macy cn.cn_flags = ISLASTCN; 1898eda14cbcSMatt Macy cn.cn_lkflags = flags; 1899eda14cbcSMatt Macy VERIFY0(VOP_LOOKUP(dvp, vpp, &cn)); 1900eda14cbcSMatt Macy vput(dvp); 1901eda14cbcSMatt Macy } else { 1902eda14cbcSMatt Macy *vpp = dvp; 1903eda14cbcSMatt Macy } 1904eda14cbcSMatt Macy return (err); 1905eda14cbcSMatt Macy } 1906eda14cbcSMatt Macy 1907eda14cbcSMatt Macy gen_mask = -1ULL >> (64 - 8 * i); 1908eda14cbcSMatt Macy 190933b8c039SMartin Matuska dprintf("getting %llu [%llu mask %llx]\n", (u_longlong_t)object, 191033b8c039SMartin Matuska (u_longlong_t)fid_gen, 191133b8c039SMartin Matuska (u_longlong_t)gen_mask); 1912eda14cbcSMatt Macy if ((err = zfs_zget(zfsvfs, object, &zp))) { 1913c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 1914eda14cbcSMatt Macy return (err); 1915eda14cbcSMatt Macy } 1916eda14cbcSMatt Macy (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &zp_gen, 1917eda14cbcSMatt Macy sizeof (uint64_t)); 1918eda14cbcSMatt Macy zp_gen = zp_gen & gen_mask; 1919eda14cbcSMatt Macy if (zp_gen == 0) 1920eda14cbcSMatt Macy zp_gen = 1; 1921eda14cbcSMatt Macy if (zp->z_unlinked || zp_gen != fid_gen) { 192233b8c039SMartin Matuska dprintf("znode gen (%llu) != fid gen (%llu)\n", 192333b8c039SMartin Matuska (u_longlong_t)zp_gen, (u_longlong_t)fid_gen); 1924eda14cbcSMatt Macy vrele(ZTOV(zp)); 1925c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 1926eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 1927eda14cbcSMatt Macy } 1928eda14cbcSMatt Macy 1929eda14cbcSMatt Macy *vpp = ZTOV(zp); 1930c7046f76SMartin Matuska zfs_exit(zfsvfs, FTAG); 1931eda14cbcSMatt Macy err = vn_lock(*vpp, flags); 1932eda14cbcSMatt Macy if (err == 0) 1933eda14cbcSMatt Macy vnode_create_vobject(*vpp, zp->z_size, curthread); 1934eda14cbcSMatt Macy else 1935eda14cbcSMatt Macy *vpp = NULL; 1936eda14cbcSMatt Macy return (err); 1937eda14cbcSMatt Macy } 1938eda14cbcSMatt Macy 1939eda14cbcSMatt Macy /* 1940eda14cbcSMatt Macy * Block out VOPs and close zfsvfs_t::z_os 1941eda14cbcSMatt Macy * 1942eda14cbcSMatt Macy * Note, if successful, then we return with the 'z_teardown_lock' and 1943eda14cbcSMatt Macy * 'z_teardown_inactive_lock' write held. We leave ownership of the underlying 1944eda14cbcSMatt Macy * dataset and objset intact so that they can be atomically handed off during 1945eda14cbcSMatt Macy * a subsequent rollback or recv operation and the resume thereafter. 1946eda14cbcSMatt Macy */ 1947eda14cbcSMatt Macy int 1948eda14cbcSMatt Macy zfs_suspend_fs(zfsvfs_t *zfsvfs) 1949eda14cbcSMatt Macy { 1950eda14cbcSMatt Macy int error; 1951eda14cbcSMatt Macy 1952eda14cbcSMatt Macy if ((error = zfsvfs_teardown(zfsvfs, B_FALSE)) != 0) 1953eda14cbcSMatt Macy return (error); 1954eda14cbcSMatt Macy 1955eda14cbcSMatt Macy return (0); 1956eda14cbcSMatt Macy } 1957eda14cbcSMatt Macy 1958eda14cbcSMatt Macy /* 1959eda14cbcSMatt Macy * Rebuild SA and release VOPs. Note that ownership of the underlying dataset 1960eda14cbcSMatt Macy * is an invariant across any of the operations that can be performed while the 1961eda14cbcSMatt Macy * filesystem was suspended. Whether it succeeded or failed, the preconditions 1962eda14cbcSMatt Macy * are the same: the relevant objset and associated dataset are owned by 1963eda14cbcSMatt Macy * zfsvfs, held, and long held on entry. 1964eda14cbcSMatt Macy */ 1965eda14cbcSMatt Macy int 1966eda14cbcSMatt Macy zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds) 1967eda14cbcSMatt Macy { 1968eda14cbcSMatt Macy int err; 1969eda14cbcSMatt Macy znode_t *zp; 1970eda14cbcSMatt Macy 19714008dd45SMateusz Guzik ASSERT(ZFS_TEARDOWN_WRITE_HELD(zfsvfs)); 1972ae5642a6SMateusz Guzik ASSERT(ZFS_TEARDOWN_INACTIVE_WRITE_HELD(zfsvfs)); 1973eda14cbcSMatt Macy 1974eda14cbcSMatt Macy /* 1975eda14cbcSMatt Macy * We already own this, so just update the objset_t, as the one we 1976eda14cbcSMatt Macy * had before may have been evicted. 1977eda14cbcSMatt Macy */ 1978eda14cbcSMatt Macy objset_t *os; 1979eda14cbcSMatt Macy VERIFY3P(ds->ds_owner, ==, zfsvfs); 1980eda14cbcSMatt Macy VERIFY(dsl_dataset_long_held(ds)); 1981eda14cbcSMatt Macy dsl_pool_t *dp = spa_get_dsl(dsl_dataset_get_spa(ds)); 1982eda14cbcSMatt Macy dsl_pool_config_enter(dp, FTAG); 1983eda14cbcSMatt Macy VERIFY0(dmu_objset_from_ds(ds, &os)); 1984eda14cbcSMatt Macy dsl_pool_config_exit(dp, FTAG); 1985eda14cbcSMatt Macy 1986eda14cbcSMatt Macy err = zfsvfs_init(zfsvfs, os); 1987eda14cbcSMatt Macy if (err != 0) 1988eda14cbcSMatt Macy goto bail; 1989eda14cbcSMatt Macy 1990eda14cbcSMatt Macy ds->ds_dir->dd_activity_cancelled = B_FALSE; 199116038816SMartin Matuska VERIFY0(zfsvfs_setup(zfsvfs, B_FALSE)); 1992eda14cbcSMatt Macy 1993eda14cbcSMatt Macy zfs_set_fuid_feature(zfsvfs); 1994eda14cbcSMatt Macy 1995eda14cbcSMatt Macy /* 1996eda14cbcSMatt Macy * Attempt to re-establish all the active znodes with 1997eda14cbcSMatt Macy * their dbufs. If a zfs_rezget() fails, then we'll let 1998c7046f76SMartin Matuska * any potential callers discover that via zfs_enter_verify_zp 1999eda14cbcSMatt Macy * when they try to use their znode. 2000eda14cbcSMatt Macy */ 2001eda14cbcSMatt Macy mutex_enter(&zfsvfs->z_znodes_lock); 2002eda14cbcSMatt Macy for (zp = list_head(&zfsvfs->z_all_znodes); zp; 2003eda14cbcSMatt Macy zp = list_next(&zfsvfs->z_all_znodes, zp)) { 2004eda14cbcSMatt Macy (void) zfs_rezget(zp); 2005eda14cbcSMatt Macy } 2006eda14cbcSMatt Macy mutex_exit(&zfsvfs->z_znodes_lock); 2007eda14cbcSMatt Macy 2008eda14cbcSMatt Macy bail: 2009eda14cbcSMatt Macy /* release the VOPs */ 2010ae5642a6SMateusz Guzik ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs); 20114008dd45SMateusz Guzik ZFS_TEARDOWN_EXIT(zfsvfs, FTAG); 2012eda14cbcSMatt Macy 2013eda14cbcSMatt Macy if (err) { 2014eda14cbcSMatt Macy /* 2015eda14cbcSMatt Macy * Since we couldn't setup the sa framework, try to force 2016eda14cbcSMatt Macy * unmount this file system. 2017eda14cbcSMatt Macy */ 2018eda14cbcSMatt Macy if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0) { 2019eda14cbcSMatt Macy vfs_ref(zfsvfs->z_vfs); 2020eda14cbcSMatt Macy (void) dounmount(zfsvfs->z_vfs, MS_FORCE, curthread); 2021eda14cbcSMatt Macy } 2022eda14cbcSMatt Macy } 2023eda14cbcSMatt Macy return (err); 2024eda14cbcSMatt Macy } 2025eda14cbcSMatt Macy 2026eda14cbcSMatt Macy static void 2027eda14cbcSMatt Macy zfs_freevfs(vfs_t *vfsp) 2028eda14cbcSMatt Macy { 2029eda14cbcSMatt Macy zfsvfs_t *zfsvfs = vfsp->vfs_data; 2030eda14cbcSMatt Macy 2031eda14cbcSMatt Macy zfsvfs_free(zfsvfs); 2032eda14cbcSMatt Macy 2033eda14cbcSMatt Macy atomic_dec_32(&zfs_active_fs_count); 2034eda14cbcSMatt Macy } 2035eda14cbcSMatt Macy 2036eda14cbcSMatt Macy #ifdef __i386__ 2037eda14cbcSMatt Macy static int desiredvnodes_backup; 2038eda14cbcSMatt Macy #include <sys/vmmeter.h> 2039eda14cbcSMatt Macy 2040eda14cbcSMatt Macy 2041eda14cbcSMatt Macy #include <vm/vm_page.h> 2042eda14cbcSMatt Macy #include <vm/vm_object.h> 2043eda14cbcSMatt Macy #include <vm/vm_kern.h> 2044eda14cbcSMatt Macy #include <vm/vm_map.h> 2045eda14cbcSMatt Macy #endif 2046eda14cbcSMatt Macy 2047eda14cbcSMatt Macy static void 2048eda14cbcSMatt Macy zfs_vnodes_adjust(void) 2049eda14cbcSMatt Macy { 2050eda14cbcSMatt Macy #ifdef __i386__ 2051eda14cbcSMatt Macy int newdesiredvnodes; 2052eda14cbcSMatt Macy 2053eda14cbcSMatt Macy desiredvnodes_backup = desiredvnodes; 2054eda14cbcSMatt Macy 2055eda14cbcSMatt Macy /* 2056eda14cbcSMatt Macy * We calculate newdesiredvnodes the same way it is done in 2057eda14cbcSMatt Macy * vntblinit(). If it is equal to desiredvnodes, it means that 2058eda14cbcSMatt Macy * it wasn't tuned by the administrator and we can tune it down. 2059eda14cbcSMatt Macy */ 2060eda14cbcSMatt Macy newdesiredvnodes = min(maxproc + vm_cnt.v_page_count / 4, 2 * 2061eda14cbcSMatt Macy vm_kmem_size / (5 * (sizeof (struct vm_object) + 2062eda14cbcSMatt Macy sizeof (struct vnode)))); 2063eda14cbcSMatt Macy if (newdesiredvnodes == desiredvnodes) 2064eda14cbcSMatt Macy desiredvnodes = (3 * newdesiredvnodes) / 4; 2065eda14cbcSMatt Macy #endif 2066eda14cbcSMatt Macy } 2067eda14cbcSMatt Macy 2068eda14cbcSMatt Macy static void 2069eda14cbcSMatt Macy zfs_vnodes_adjust_back(void) 2070eda14cbcSMatt Macy { 2071eda14cbcSMatt Macy 2072eda14cbcSMatt Macy #ifdef __i386__ 2073eda14cbcSMatt Macy desiredvnodes = desiredvnodes_backup; 2074eda14cbcSMatt Macy #endif 2075eda14cbcSMatt Macy } 2076eda14cbcSMatt Macy 2077f8b1db88SMartin Matuska static struct sx zfs_vnlru_lock; 2078f8b1db88SMartin Matuska static struct vnode *zfs_vnlru_marker; 2079f8b1db88SMartin Matuska static arc_prune_t *zfs_prune; 2080f8b1db88SMartin Matuska 2081f8b1db88SMartin Matuska static void 2082f8b1db88SMartin Matuska zfs_prune_task(uint64_t nr_to_scan, void *arg __unused) 2083f8b1db88SMartin Matuska { 2084f8b1db88SMartin Matuska if (nr_to_scan > INT_MAX) 2085f8b1db88SMartin Matuska nr_to_scan = INT_MAX; 2086f8b1db88SMartin Matuska sx_xlock(&zfs_vnlru_lock); 2087f8b1db88SMartin Matuska vnlru_free_vfsops(nr_to_scan, &zfs_vfsops, zfs_vnlru_marker); 2088f8b1db88SMartin Matuska sx_xunlock(&zfs_vnlru_lock); 2089f8b1db88SMartin Matuska } 2090f8b1db88SMartin Matuska 2091eda14cbcSMatt Macy void 2092eda14cbcSMatt Macy zfs_init(void) 2093eda14cbcSMatt Macy { 2094eda14cbcSMatt Macy 2095eda14cbcSMatt Macy printf("ZFS filesystem version: " ZPL_VERSION_STRING "\n"); 2096eda14cbcSMatt Macy 2097eda14cbcSMatt Macy /* 2098eda14cbcSMatt Macy * Initialize .zfs directory structures 2099eda14cbcSMatt Macy */ 2100eda14cbcSMatt Macy zfsctl_init(); 2101eda14cbcSMatt Macy 2102eda14cbcSMatt Macy /* 2103eda14cbcSMatt Macy * Initialize znode cache, vnode ops, etc... 2104eda14cbcSMatt Macy */ 2105eda14cbcSMatt Macy zfs_znode_init(); 2106eda14cbcSMatt Macy 2107eda14cbcSMatt Macy /* 2108eda14cbcSMatt Macy * Reduce number of vnodes. Originally number of vnodes is calculated 2109eda14cbcSMatt Macy * with UFS inode in mind. We reduce it here, because it's too big for 2110eda14cbcSMatt Macy * ZFS/i386. 2111eda14cbcSMatt Macy */ 2112eda14cbcSMatt Macy zfs_vnodes_adjust(); 2113eda14cbcSMatt Macy 2114eda14cbcSMatt Macy dmu_objset_register_type(DMU_OST_ZFS, zpl_get_file_info); 2115eda14cbcSMatt Macy 2116eda14cbcSMatt Macy zfsvfs_taskq = taskq_create("zfsvfs", 1, minclsyspri, 0, 0, 0); 2117f8b1db88SMartin Matuska 2118f8b1db88SMartin Matuska zfs_vnlru_marker = vnlru_alloc_marker(); 2119f8b1db88SMartin Matuska sx_init(&zfs_vnlru_lock, "zfs vnlru lock"); 2120f8b1db88SMartin Matuska zfs_prune = arc_add_prune_callback(zfs_prune_task, NULL); 2121eda14cbcSMatt Macy } 2122eda14cbcSMatt Macy 2123eda14cbcSMatt Macy void 2124eda14cbcSMatt Macy zfs_fini(void) 2125eda14cbcSMatt Macy { 2126f8b1db88SMartin Matuska arc_remove_prune_callback(zfs_prune); 2127f8b1db88SMartin Matuska vnlru_free_marker(zfs_vnlru_marker); 2128f8b1db88SMartin Matuska sx_destroy(&zfs_vnlru_lock); 2129f8b1db88SMartin Matuska 2130eda14cbcSMatt Macy taskq_destroy(zfsvfs_taskq); 2131eda14cbcSMatt Macy zfsctl_fini(); 2132eda14cbcSMatt Macy zfs_znode_fini(); 2133eda14cbcSMatt Macy zfs_vnodes_adjust_back(); 2134eda14cbcSMatt Macy } 2135eda14cbcSMatt Macy 2136eda14cbcSMatt Macy int 2137eda14cbcSMatt Macy zfs_busy(void) 2138eda14cbcSMatt Macy { 2139eda14cbcSMatt Macy return (zfs_active_fs_count != 0); 2140eda14cbcSMatt Macy } 2141eda14cbcSMatt Macy 2142eda14cbcSMatt Macy /* 2143eda14cbcSMatt Macy * Release VOPs and unmount a suspended filesystem. 2144eda14cbcSMatt Macy */ 2145eda14cbcSMatt Macy int 2146eda14cbcSMatt Macy zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds) 2147eda14cbcSMatt Macy { 21484008dd45SMateusz Guzik ASSERT(ZFS_TEARDOWN_WRITE_HELD(zfsvfs)); 2149ae5642a6SMateusz Guzik ASSERT(ZFS_TEARDOWN_INACTIVE_WRITE_HELD(zfsvfs)); 2150eda14cbcSMatt Macy 2151eda14cbcSMatt Macy /* 2152eda14cbcSMatt Macy * We already own this, so just hold and rele it to update the 2153eda14cbcSMatt Macy * objset_t, as the one we had before may have been evicted. 2154eda14cbcSMatt Macy */ 2155eda14cbcSMatt Macy objset_t *os; 2156eda14cbcSMatt Macy VERIFY3P(ds->ds_owner, ==, zfsvfs); 2157eda14cbcSMatt Macy VERIFY(dsl_dataset_long_held(ds)); 2158eda14cbcSMatt Macy dsl_pool_t *dp = spa_get_dsl(dsl_dataset_get_spa(ds)); 2159eda14cbcSMatt Macy dsl_pool_config_enter(dp, FTAG); 2160eda14cbcSMatt Macy VERIFY0(dmu_objset_from_ds(ds, &os)); 2161eda14cbcSMatt Macy dsl_pool_config_exit(dp, FTAG); 2162eda14cbcSMatt Macy zfsvfs->z_os = os; 2163eda14cbcSMatt Macy 2164eda14cbcSMatt Macy /* release the VOPs */ 2165ae5642a6SMateusz Guzik ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs); 21664008dd45SMateusz Guzik ZFS_TEARDOWN_EXIT(zfsvfs, FTAG); 2167eda14cbcSMatt Macy 2168eda14cbcSMatt Macy /* 2169eda14cbcSMatt Macy * Try to force unmount this file system. 2170eda14cbcSMatt Macy */ 2171eda14cbcSMatt Macy (void) zfs_umount(zfsvfs->z_vfs, 0); 2172eda14cbcSMatt Macy zfsvfs->z_unmounted = B_TRUE; 2173eda14cbcSMatt Macy return (0); 2174eda14cbcSMatt Macy } 2175eda14cbcSMatt Macy 2176eda14cbcSMatt Macy int 2177eda14cbcSMatt Macy zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers) 2178eda14cbcSMatt Macy { 2179eda14cbcSMatt Macy int error; 2180eda14cbcSMatt Macy objset_t *os = zfsvfs->z_os; 2181eda14cbcSMatt Macy dmu_tx_t *tx; 2182eda14cbcSMatt Macy 2183eda14cbcSMatt Macy if (newvers < ZPL_VERSION_INITIAL || newvers > ZPL_VERSION) 2184eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 2185eda14cbcSMatt Macy 2186eda14cbcSMatt Macy if (newvers < zfsvfs->z_version) 2187eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 2188eda14cbcSMatt Macy 2189eda14cbcSMatt Macy if (zfs_spa_version_map(newvers) > 2190eda14cbcSMatt Macy spa_version(dmu_objset_spa(zfsvfs->z_os))) 2191eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 2192eda14cbcSMatt Macy 2193eda14cbcSMatt Macy tx = dmu_tx_create(os); 2194eda14cbcSMatt Macy dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_FALSE, ZPL_VERSION_STR); 2195eda14cbcSMatt Macy if (newvers >= ZPL_VERSION_SA && !zfsvfs->z_use_sa) { 2196eda14cbcSMatt Macy dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE, 2197eda14cbcSMatt Macy ZFS_SA_ATTRS); 2198eda14cbcSMatt Macy dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL); 2199eda14cbcSMatt Macy } 2200eda14cbcSMatt Macy error = dmu_tx_assign(tx, TXG_WAIT); 2201eda14cbcSMatt Macy if (error) { 2202eda14cbcSMatt Macy dmu_tx_abort(tx); 2203eda14cbcSMatt Macy return (error); 2204eda14cbcSMatt Macy } 2205eda14cbcSMatt Macy 2206eda14cbcSMatt Macy error = zap_update(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 2207eda14cbcSMatt Macy 8, 1, &newvers, tx); 2208eda14cbcSMatt Macy 2209eda14cbcSMatt Macy if (error) { 2210eda14cbcSMatt Macy dmu_tx_commit(tx); 2211eda14cbcSMatt Macy return (error); 2212eda14cbcSMatt Macy } 2213eda14cbcSMatt Macy 2214eda14cbcSMatt Macy if (newvers >= ZPL_VERSION_SA && !zfsvfs->z_use_sa) { 2215eda14cbcSMatt Macy uint64_t sa_obj; 2216eda14cbcSMatt Macy 2217eda14cbcSMatt Macy ASSERT3U(spa_version(dmu_objset_spa(zfsvfs->z_os)), >=, 2218eda14cbcSMatt Macy SPA_VERSION_SA); 2219eda14cbcSMatt Macy sa_obj = zap_create(os, DMU_OT_SA_MASTER_NODE, 2220eda14cbcSMatt Macy DMU_OT_NONE, 0, tx); 2221eda14cbcSMatt Macy 2222eda14cbcSMatt Macy error = zap_add(os, MASTER_NODE_OBJ, 2223eda14cbcSMatt Macy ZFS_SA_ATTRS, 8, 1, &sa_obj, tx); 2224eda14cbcSMatt Macy ASSERT0(error); 2225eda14cbcSMatt Macy 222616038816SMartin Matuska VERIFY0(sa_set_sa_object(os, sa_obj)); 2227eda14cbcSMatt Macy sa_register_update_callback(os, zfs_sa_upgrade); 2228eda14cbcSMatt Macy } 2229eda14cbcSMatt Macy 2230eda14cbcSMatt Macy spa_history_log_internal_ds(dmu_objset_ds(os), "upgrade", tx, 2231eda14cbcSMatt Macy "from %ju to %ju", (uintmax_t)zfsvfs->z_version, 2232eda14cbcSMatt Macy (uintmax_t)newvers); 2233eda14cbcSMatt Macy dmu_tx_commit(tx); 2234eda14cbcSMatt Macy 2235eda14cbcSMatt Macy zfsvfs->z_version = newvers; 2236eda14cbcSMatt Macy os->os_version = newvers; 2237eda14cbcSMatt Macy 2238eda14cbcSMatt Macy zfs_set_fuid_feature(zfsvfs); 2239eda14cbcSMatt Macy 2240eda14cbcSMatt Macy return (0); 2241eda14cbcSMatt Macy } 2242eda14cbcSMatt Macy 2243eda14cbcSMatt Macy /* 2244eda14cbcSMatt Macy * Return true if the corresponding vfs's unmounted flag is set. 2245eda14cbcSMatt Macy * Otherwise return false. 2246eda14cbcSMatt Macy * If this function returns true we know VFS unmount has been initiated. 2247eda14cbcSMatt Macy */ 2248eda14cbcSMatt Macy boolean_t 2249eda14cbcSMatt Macy zfs_get_vfs_flag_unmounted(objset_t *os) 2250eda14cbcSMatt Macy { 2251eda14cbcSMatt Macy zfsvfs_t *zfvp; 2252eda14cbcSMatt Macy boolean_t unmounted = B_FALSE; 2253eda14cbcSMatt Macy 225416038816SMartin Matuska ASSERT3U(dmu_objset_type(os), ==, DMU_OST_ZFS); 2255eda14cbcSMatt Macy 2256eda14cbcSMatt Macy mutex_enter(&os->os_user_ptr_lock); 2257eda14cbcSMatt Macy zfvp = dmu_objset_get_user(os); 2258eda14cbcSMatt Macy if (zfvp != NULL && zfvp->z_vfs != NULL && 2259eda14cbcSMatt Macy (zfvp->z_vfs->mnt_kern_flag & MNTK_UNMOUNT)) 2260eda14cbcSMatt Macy unmounted = B_TRUE; 2261eda14cbcSMatt Macy mutex_exit(&os->os_user_ptr_lock); 2262eda14cbcSMatt Macy 2263eda14cbcSMatt Macy return (unmounted); 2264eda14cbcSMatt Macy } 2265eda14cbcSMatt Macy 2266eda14cbcSMatt Macy #ifdef _KERNEL 2267eda14cbcSMatt Macy void 2268eda14cbcSMatt Macy zfsvfs_update_fromname(const char *oldname, const char *newname) 2269eda14cbcSMatt Macy { 2270eda14cbcSMatt Macy char tmpbuf[MAXPATHLEN]; 2271eda14cbcSMatt Macy struct mount *mp; 2272eda14cbcSMatt Macy char *fromname; 2273eda14cbcSMatt Macy size_t oldlen; 2274eda14cbcSMatt Macy 2275eda14cbcSMatt Macy oldlen = strlen(oldname); 2276eda14cbcSMatt Macy 2277eda14cbcSMatt Macy mtx_lock(&mountlist_mtx); 2278eda14cbcSMatt Macy TAILQ_FOREACH(mp, &mountlist, mnt_list) { 2279eda14cbcSMatt Macy fromname = mp->mnt_stat.f_mntfromname; 2280eda14cbcSMatt Macy if (strcmp(fromname, oldname) == 0) { 2281eda14cbcSMatt Macy (void) strlcpy(fromname, newname, 2282eda14cbcSMatt Macy sizeof (mp->mnt_stat.f_mntfromname)); 2283eda14cbcSMatt Macy continue; 2284eda14cbcSMatt Macy } 2285eda14cbcSMatt Macy if (strncmp(fromname, oldname, oldlen) == 0 && 2286eda14cbcSMatt Macy (fromname[oldlen] == '/' || fromname[oldlen] == '@')) { 2287eda14cbcSMatt Macy (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s%s", 2288eda14cbcSMatt Macy newname, fromname + oldlen); 2289eda14cbcSMatt Macy (void) strlcpy(fromname, tmpbuf, 2290eda14cbcSMatt Macy sizeof (mp->mnt_stat.f_mntfromname)); 2291eda14cbcSMatt Macy continue; 2292eda14cbcSMatt Macy } 2293eda14cbcSMatt Macy } 2294eda14cbcSMatt Macy mtx_unlock(&mountlist_mtx); 2295eda14cbcSMatt Macy } 2296eda14cbcSMatt Macy #endif 2297dbd5678dSMartin Matuska 2298dbd5678dSMartin Matuska /* 2299dbd5678dSMartin Matuska * Find a prison with ZFS info. 2300dbd5678dSMartin Matuska * Return the ZFS info and the (locked) prison. 2301dbd5678dSMartin Matuska */ 2302dbd5678dSMartin Matuska static struct zfs_jailparam * 2303dbd5678dSMartin Matuska zfs_jailparam_find(struct prison *spr, struct prison **prp) 2304dbd5678dSMartin Matuska { 2305dbd5678dSMartin Matuska struct prison *pr; 2306dbd5678dSMartin Matuska struct zfs_jailparam *zjp; 2307dbd5678dSMartin Matuska 2308dbd5678dSMartin Matuska for (pr = spr; ; pr = pr->pr_parent) { 2309dbd5678dSMartin Matuska mtx_lock(&pr->pr_mtx); 2310dbd5678dSMartin Matuska if (pr == &prison0) { 2311dbd5678dSMartin Matuska zjp = &zfs_jailparam0; 2312dbd5678dSMartin Matuska break; 2313dbd5678dSMartin Matuska } 2314dbd5678dSMartin Matuska zjp = osd_jail_get(pr, zfs_jailparam_slot); 2315dbd5678dSMartin Matuska if (zjp != NULL) 2316dbd5678dSMartin Matuska break; 2317dbd5678dSMartin Matuska mtx_unlock(&pr->pr_mtx); 2318dbd5678dSMartin Matuska } 2319dbd5678dSMartin Matuska *prp = pr; 2320dbd5678dSMartin Matuska 2321dbd5678dSMartin Matuska return (zjp); 2322dbd5678dSMartin Matuska } 2323dbd5678dSMartin Matuska 2324dbd5678dSMartin Matuska /* 2325dbd5678dSMartin Matuska * Ensure a prison has its own ZFS info. If zjpp is non-null, point it to the 2326dbd5678dSMartin Matuska * ZFS info and lock the prison. 2327dbd5678dSMartin Matuska */ 2328dbd5678dSMartin Matuska static void 2329dbd5678dSMartin Matuska zfs_jailparam_alloc(struct prison *pr, struct zfs_jailparam **zjpp) 2330dbd5678dSMartin Matuska { 2331dbd5678dSMartin Matuska struct prison *ppr; 2332dbd5678dSMartin Matuska struct zfs_jailparam *zjp, *nzjp; 2333dbd5678dSMartin Matuska void **rsv; 2334dbd5678dSMartin Matuska 2335dbd5678dSMartin Matuska /* If this prison already has ZFS info, return that. */ 2336dbd5678dSMartin Matuska zjp = zfs_jailparam_find(pr, &ppr); 2337dbd5678dSMartin Matuska if (ppr == pr) 2338dbd5678dSMartin Matuska goto done; 2339dbd5678dSMartin Matuska 2340dbd5678dSMartin Matuska /* 2341dbd5678dSMartin Matuska * Allocate a new info record. Then check again, in case something 2342dbd5678dSMartin Matuska * changed during the allocation. 2343dbd5678dSMartin Matuska */ 2344dbd5678dSMartin Matuska mtx_unlock(&ppr->pr_mtx); 2345dbd5678dSMartin Matuska nzjp = malloc(sizeof (struct zfs_jailparam), M_PRISON, M_WAITOK); 2346dbd5678dSMartin Matuska rsv = osd_reserve(zfs_jailparam_slot); 2347dbd5678dSMartin Matuska zjp = zfs_jailparam_find(pr, &ppr); 2348dbd5678dSMartin Matuska if (ppr == pr) { 2349dbd5678dSMartin Matuska free(nzjp, M_PRISON); 2350dbd5678dSMartin Matuska osd_free_reserved(rsv); 2351dbd5678dSMartin Matuska goto done; 2352dbd5678dSMartin Matuska } 2353dbd5678dSMartin Matuska /* Inherit the initial values from the ancestor. */ 2354dbd5678dSMartin Matuska mtx_lock(&pr->pr_mtx); 2355dbd5678dSMartin Matuska (void) osd_jail_set_reserved(pr, zfs_jailparam_slot, rsv, nzjp); 2356dbd5678dSMartin Matuska (void) memcpy(nzjp, zjp, sizeof (*zjp)); 2357dbd5678dSMartin Matuska zjp = nzjp; 2358dbd5678dSMartin Matuska mtx_unlock(&ppr->pr_mtx); 2359dbd5678dSMartin Matuska done: 2360dbd5678dSMartin Matuska if (zjpp != NULL) 2361dbd5678dSMartin Matuska *zjpp = zjp; 2362dbd5678dSMartin Matuska else 2363dbd5678dSMartin Matuska mtx_unlock(&pr->pr_mtx); 2364dbd5678dSMartin Matuska } 2365dbd5678dSMartin Matuska 2366dbd5678dSMartin Matuska /* 2367dbd5678dSMartin Matuska * Jail OSD methods for ZFS VFS info. 2368dbd5678dSMartin Matuska */ 2369dbd5678dSMartin Matuska static int 2370dbd5678dSMartin Matuska zfs_jailparam_create(void *obj, void *data) 2371dbd5678dSMartin Matuska { 2372dbd5678dSMartin Matuska struct prison *pr = obj; 2373dbd5678dSMartin Matuska struct vfsoptlist *opts = data; 2374dbd5678dSMartin Matuska int jsys; 2375dbd5678dSMartin Matuska 2376dbd5678dSMartin Matuska if (vfs_copyopt(opts, "zfs", &jsys, sizeof (jsys)) == 0 && 2377dbd5678dSMartin Matuska jsys == JAIL_SYS_INHERIT) 2378dbd5678dSMartin Matuska return (0); 2379dbd5678dSMartin Matuska /* 2380dbd5678dSMartin Matuska * Inherit a prison's initial values from its parent 2381dbd5678dSMartin Matuska * (different from JAIL_SYS_INHERIT which also inherits changes). 2382dbd5678dSMartin Matuska */ 2383dbd5678dSMartin Matuska zfs_jailparam_alloc(pr, NULL); 2384dbd5678dSMartin Matuska return (0); 2385dbd5678dSMartin Matuska } 2386dbd5678dSMartin Matuska 2387dbd5678dSMartin Matuska static int 2388dbd5678dSMartin Matuska zfs_jailparam_get(void *obj, void *data) 2389dbd5678dSMartin Matuska { 2390dbd5678dSMartin Matuska struct prison *ppr, *pr = obj; 2391dbd5678dSMartin Matuska struct vfsoptlist *opts = data; 2392dbd5678dSMartin Matuska struct zfs_jailparam *zjp; 2393dbd5678dSMartin Matuska int jsys, error; 2394dbd5678dSMartin Matuska 2395dbd5678dSMartin Matuska zjp = zfs_jailparam_find(pr, &ppr); 2396dbd5678dSMartin Matuska jsys = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT; 2397dbd5678dSMartin Matuska error = vfs_setopt(opts, "zfs", &jsys, sizeof (jsys)); 2398dbd5678dSMartin Matuska if (error != 0 && error != ENOENT) 2399dbd5678dSMartin Matuska goto done; 2400dbd5678dSMartin Matuska if (jsys == JAIL_SYS_NEW) { 2401dbd5678dSMartin Matuska error = vfs_setopt(opts, "zfs.mount_snapshot", 2402dbd5678dSMartin Matuska &zjp->mount_snapshot, sizeof (zjp->mount_snapshot)); 2403dbd5678dSMartin Matuska if (error != 0 && error != ENOENT) 2404dbd5678dSMartin Matuska goto done; 2405dbd5678dSMartin Matuska } else { 2406dbd5678dSMartin Matuska /* 2407dbd5678dSMartin Matuska * If this prison is inheriting its ZFS info, report 2408dbd5678dSMartin Matuska * empty/zero parameters. 2409dbd5678dSMartin Matuska */ 2410dbd5678dSMartin Matuska static int mount_snapshot = 0; 2411dbd5678dSMartin Matuska 2412dbd5678dSMartin Matuska error = vfs_setopt(opts, "zfs.mount_snapshot", 2413dbd5678dSMartin Matuska &mount_snapshot, sizeof (mount_snapshot)); 2414dbd5678dSMartin Matuska if (error != 0 && error != ENOENT) 2415dbd5678dSMartin Matuska goto done; 2416dbd5678dSMartin Matuska } 2417dbd5678dSMartin Matuska error = 0; 2418dbd5678dSMartin Matuska done: 2419dbd5678dSMartin Matuska mtx_unlock(&ppr->pr_mtx); 2420dbd5678dSMartin Matuska return (error); 2421dbd5678dSMartin Matuska } 2422dbd5678dSMartin Matuska 2423dbd5678dSMartin Matuska static int 2424dbd5678dSMartin Matuska zfs_jailparam_set(void *obj, void *data) 2425dbd5678dSMartin Matuska { 2426dbd5678dSMartin Matuska struct prison *pr = obj; 2427dbd5678dSMartin Matuska struct prison *ppr; 2428dbd5678dSMartin Matuska struct vfsoptlist *opts = data; 2429dbd5678dSMartin Matuska int error, jsys, mount_snapshot; 2430dbd5678dSMartin Matuska 2431dbd5678dSMartin Matuska /* Set the parameters, which should be correct. */ 2432dbd5678dSMartin Matuska error = vfs_copyopt(opts, "zfs", &jsys, sizeof (jsys)); 2433dbd5678dSMartin Matuska if (error == ENOENT) 2434dbd5678dSMartin Matuska jsys = -1; 2435dbd5678dSMartin Matuska error = vfs_copyopt(opts, "zfs.mount_snapshot", &mount_snapshot, 2436dbd5678dSMartin Matuska sizeof (mount_snapshot)); 2437dbd5678dSMartin Matuska if (error == ENOENT) 2438dbd5678dSMartin Matuska mount_snapshot = -1; 2439dbd5678dSMartin Matuska else 2440dbd5678dSMartin Matuska jsys = JAIL_SYS_NEW; 24418b04c1cbSAllan Jude switch (jsys) { 24428b04c1cbSAllan Jude case JAIL_SYS_NEW: 24438b04c1cbSAllan Jude { 2444dbd5678dSMartin Matuska /* "zfs=new" or "zfs.*": the prison gets its own ZFS info. */ 2445dbd5678dSMartin Matuska struct zfs_jailparam *zjp; 2446dbd5678dSMartin Matuska 2447dbd5678dSMartin Matuska /* 2448dbd5678dSMartin Matuska * A child jail cannot have more permissions than its parent 2449dbd5678dSMartin Matuska */ 2450dbd5678dSMartin Matuska if (pr->pr_parent != &prison0) { 2451dbd5678dSMartin Matuska zjp = zfs_jailparam_find(pr->pr_parent, &ppr); 2452dbd5678dSMartin Matuska mtx_unlock(&ppr->pr_mtx); 2453dbd5678dSMartin Matuska if (zjp->mount_snapshot < mount_snapshot) { 2454dbd5678dSMartin Matuska return (EPERM); 2455dbd5678dSMartin Matuska } 2456dbd5678dSMartin Matuska } 2457dbd5678dSMartin Matuska zfs_jailparam_alloc(pr, &zjp); 2458dbd5678dSMartin Matuska if (mount_snapshot != -1) 2459dbd5678dSMartin Matuska zjp->mount_snapshot = mount_snapshot; 2460dbd5678dSMartin Matuska mtx_unlock(&pr->pr_mtx); 24618b04c1cbSAllan Jude break; 24628b04c1cbSAllan Jude } 24638b04c1cbSAllan Jude case JAIL_SYS_INHERIT: 2464dbd5678dSMartin Matuska /* "zfs=inherit": inherit the parent's ZFS info. */ 2465dbd5678dSMartin Matuska mtx_lock(&pr->pr_mtx); 2466dbd5678dSMartin Matuska osd_jail_del(pr, zfs_jailparam_slot); 2467dbd5678dSMartin Matuska mtx_unlock(&pr->pr_mtx); 24688b04c1cbSAllan Jude break; 24698b04c1cbSAllan Jude case -1: 24708b04c1cbSAllan Jude /* 24718b04c1cbSAllan Jude * If the setting being changed is not ZFS related 24728b04c1cbSAllan Jude * then do nothing. 24738b04c1cbSAllan Jude */ 24748b04c1cbSAllan Jude break; 2475dbd5678dSMartin Matuska } 24768b04c1cbSAllan Jude 2477dbd5678dSMartin Matuska return (0); 2478dbd5678dSMartin Matuska } 2479dbd5678dSMartin Matuska 2480dbd5678dSMartin Matuska static int 2481dbd5678dSMartin Matuska zfs_jailparam_check(void *obj __unused, void *data) 2482dbd5678dSMartin Matuska { 2483dbd5678dSMartin Matuska struct vfsoptlist *opts = data; 2484dbd5678dSMartin Matuska int error, jsys, mount_snapshot; 2485dbd5678dSMartin Matuska 2486dbd5678dSMartin Matuska /* Check that the parameters are correct. */ 2487dbd5678dSMartin Matuska error = vfs_copyopt(opts, "zfs", &jsys, sizeof (jsys)); 2488dbd5678dSMartin Matuska if (error != ENOENT) { 2489dbd5678dSMartin Matuska if (error != 0) 2490dbd5678dSMartin Matuska return (error); 2491dbd5678dSMartin Matuska if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT) 2492dbd5678dSMartin Matuska return (EINVAL); 2493dbd5678dSMartin Matuska } 2494dbd5678dSMartin Matuska error = vfs_copyopt(opts, "zfs.mount_snapshot", &mount_snapshot, 2495dbd5678dSMartin Matuska sizeof (mount_snapshot)); 2496dbd5678dSMartin Matuska if (error != ENOENT) { 2497dbd5678dSMartin Matuska if (error != 0) 2498dbd5678dSMartin Matuska return (error); 2499dbd5678dSMartin Matuska if (mount_snapshot != 0 && mount_snapshot != 1) 2500dbd5678dSMartin Matuska return (EINVAL); 2501dbd5678dSMartin Matuska } 2502dbd5678dSMartin Matuska return (0); 2503dbd5678dSMartin Matuska } 2504dbd5678dSMartin Matuska 2505dbd5678dSMartin Matuska static void 2506dbd5678dSMartin Matuska zfs_jailparam_destroy(void *data) 2507dbd5678dSMartin Matuska { 2508dbd5678dSMartin Matuska 2509dbd5678dSMartin Matuska free(data, M_PRISON); 2510dbd5678dSMartin Matuska } 2511dbd5678dSMartin Matuska 2512dbd5678dSMartin Matuska static void 2513dbd5678dSMartin Matuska zfs_jailparam_sysinit(void *arg __unused) 2514dbd5678dSMartin Matuska { 2515dbd5678dSMartin Matuska struct prison *pr; 2516dbd5678dSMartin Matuska osd_method_t methods[PR_MAXMETHOD] = { 2517dbd5678dSMartin Matuska [PR_METHOD_CREATE] = zfs_jailparam_create, 2518dbd5678dSMartin Matuska [PR_METHOD_GET] = zfs_jailparam_get, 2519dbd5678dSMartin Matuska [PR_METHOD_SET] = zfs_jailparam_set, 2520dbd5678dSMartin Matuska [PR_METHOD_CHECK] = zfs_jailparam_check, 2521dbd5678dSMartin Matuska }; 2522dbd5678dSMartin Matuska 2523dbd5678dSMartin Matuska zfs_jailparam_slot = osd_jail_register(zfs_jailparam_destroy, methods); 2524dbd5678dSMartin Matuska /* Copy the defaults to any existing prisons. */ 2525dbd5678dSMartin Matuska sx_slock(&allprison_lock); 2526dbd5678dSMartin Matuska TAILQ_FOREACH(pr, &allprison, pr_list) 2527dbd5678dSMartin Matuska zfs_jailparam_alloc(pr, NULL); 2528dbd5678dSMartin Matuska sx_sunlock(&allprison_lock); 2529dbd5678dSMartin Matuska } 2530dbd5678dSMartin Matuska 2531dbd5678dSMartin Matuska static void 2532dbd5678dSMartin Matuska zfs_jailparam_sysuninit(void *arg __unused) 2533dbd5678dSMartin Matuska { 2534dbd5678dSMartin Matuska 2535dbd5678dSMartin Matuska osd_jail_deregister(zfs_jailparam_slot); 2536dbd5678dSMartin Matuska } 2537dbd5678dSMartin Matuska 2538dbd5678dSMartin Matuska SYSINIT(zfs_jailparam_sysinit, SI_SUB_DRIVERS, SI_ORDER_ANY, 2539dbd5678dSMartin Matuska zfs_jailparam_sysinit, NULL); 2540dbd5678dSMartin Matuska SYSUNINIT(zfs_jailparam_sysuninit, SI_SUB_DRIVERS, SI_ORDER_ANY, 2541dbd5678dSMartin Matuska zfs_jailparam_sysuninit, NULL); 2542