zfs_vfsops.c revision 215260
1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22209962Smm * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23168404Spjd * Use is subject to license terms. 24168404Spjd */ 25168404Spjd 26168404Spjd#include <sys/types.h> 27168404Spjd#include <sys/param.h> 28168404Spjd#include <sys/systm.h> 29168404Spjd#include <sys/kernel.h> 30168404Spjd#include <sys/sysmacros.h> 31168404Spjd#include <sys/kmem.h> 32168404Spjd#include <sys/acl.h> 33168404Spjd#include <sys/vnode.h> 34168404Spjd#include <sys/vfs.h> 35168404Spjd#include <sys/mntent.h> 36168404Spjd#include <sys/mount.h> 37168404Spjd#include <sys/cmn_err.h> 38168404Spjd#include <sys/zfs_znode.h> 39168404Spjd#include <sys/zfs_dir.h> 40168404Spjd#include <sys/zil.h> 41168404Spjd#include <sys/fs/zfs.h> 42168404Spjd#include <sys/dmu.h> 43168404Spjd#include <sys/dsl_prop.h> 44168404Spjd#include <sys/dsl_dataset.h> 45185029Spjd#include <sys/dsl_deleg.h> 46168404Spjd#include <sys/spa.h> 47168404Spjd#include <sys/zap.h> 48168404Spjd#include <sys/varargs.h> 49168962Spjd#include <sys/policy.h> 50168404Spjd#include <sys/atomic.h> 51168404Spjd#include <sys/zfs_ioctl.h> 52168404Spjd#include <sys/zfs_ctldir.h> 53185029Spjd#include <sys/zfs_fuid.h> 54168962Spjd#include <sys/sunddi.h> 55168404Spjd#include <sys/dnlc.h> 56185029Spjd#include <sys/dmu_objset.h> 57185029Spjd#include <sys/spa_boot.h> 58168404Spjd 59168404Spjdstruct mtx zfs_debug_mtx; 60168404SpjdMTX_SYSINIT(zfs_debug_mtx, &zfs_debug_mtx, "zfs_debug", MTX_DEF); 61185029Spjd 62168404SpjdSYSCTL_NODE(_vfs, OID_AUTO, zfs, CTLFLAG_RW, 0, "ZFS file system"); 63185029Spjd 64185029Spjdint zfs_super_owner = 0; 65185029SpjdSYSCTL_INT(_vfs_zfs, OID_AUTO, super_owner, CTLFLAG_RW, &zfs_super_owner, 0, 66185029Spjd "File system owner can perform privileged operation on his file systems"); 67185029Spjd 68168404Spjdint zfs_debug_level = 0; 69168713SpjdTUNABLE_INT("vfs.zfs.debug", &zfs_debug_level); 70168404SpjdSYSCTL_INT(_vfs_zfs, OID_AUTO, debug, CTLFLAG_RW, &zfs_debug_level, 0, 71168404Spjd "Debug level"); 72168404Spjd 73185029SpjdSYSCTL_NODE(_vfs_zfs, OID_AUTO, version, CTLFLAG_RD, 0, "ZFS versions"); 74185029Spjdstatic int zfs_version_acl = ZFS_ACL_VERSION; 75185029SpjdSYSCTL_INT(_vfs_zfs_version, OID_AUTO, acl, CTLFLAG_RD, &zfs_version_acl, 0, 76185029Spjd "ZFS_ACL_VERSION"); 77185029Spjdstatic int zfs_version_dmu_backup_header = DMU_BACKUP_HEADER_VERSION; 78185029SpjdSYSCTL_INT(_vfs_zfs_version, OID_AUTO, dmu_backup_header, CTLFLAG_RD, 79185029Spjd &zfs_version_dmu_backup_header, 0, "DMU_BACKUP_HEADER_VERSION"); 80185029Spjdstatic int zfs_version_dmu_backup_stream = DMU_BACKUP_STREAM_VERSION; 81185029SpjdSYSCTL_INT(_vfs_zfs_version, OID_AUTO, dmu_backup_stream, CTLFLAG_RD, 82185029Spjd &zfs_version_dmu_backup_stream, 0, "DMU_BACKUP_STREAM_VERSION"); 83185029Spjdstatic int zfs_version_spa = SPA_VERSION; 84185029SpjdSYSCTL_INT(_vfs_zfs_version, OID_AUTO, spa, CTLFLAG_RD, &zfs_version_spa, 0, 85185029Spjd "SPA_VERSION"); 86185029Spjdstatic int zfs_version_zpl = ZPL_VERSION; 87185029SpjdSYSCTL_INT(_vfs_zfs_version, OID_AUTO, zpl, CTLFLAG_RD, &zfs_version_zpl, 0, 88185029Spjd "ZPL_VERSION"); 89185029Spjd 90191990Sattiliostatic int zfs_mount(vfs_t *vfsp); 91191990Sattiliostatic int zfs_umount(vfs_t *vfsp, int fflag); 92191990Sattiliostatic int zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp); 93191990Sattiliostatic int zfs_statfs(vfs_t *vfsp, struct statfs *statp); 94168404Spjdstatic int zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp); 95191990Sattiliostatic int zfs_sync(vfs_t *vfsp, int waitfor); 96196982Spjdstatic int zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, int *extflagsp, 97196982Spjd struct ucred **credanonp, int *numsecflavors, int **secflavors); 98168404Spjdstatic int zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp); 99168404Spjdstatic void zfs_objset_close(zfsvfs_t *zfsvfs); 100168404Spjdstatic void zfs_freevfs(vfs_t *vfsp); 101168404Spjd 102168404Spjdstatic struct vfsops zfs_vfsops = { 103168404Spjd .vfs_mount = zfs_mount, 104168404Spjd .vfs_unmount = zfs_umount, 105168404Spjd .vfs_root = zfs_root, 106168404Spjd .vfs_statfs = zfs_statfs, 107168404Spjd .vfs_vget = zfs_vget, 108168404Spjd .vfs_sync = zfs_sync, 109196982Spjd .vfs_checkexp = zfs_checkexp, 110168404Spjd .vfs_fhtovp = zfs_fhtovp, 111168404Spjd}; 112168404Spjd 113185029SpjdVFS_SET(zfs_vfsops, zfs, VFCF_JAIL | VFCF_DELEGADMIN); 114168404Spjd 115168404Spjd/* 116168404Spjd * We need to keep a count of active fs's. 117168404Spjd * This is necessary to prevent our module 118168404Spjd * from being unloaded after a umount -f 119168404Spjd */ 120168404Spjdstatic uint32_t zfs_active_fs_count = 0; 121168404Spjd 122168404Spjd/*ARGSUSED*/ 123168404Spjdstatic int 124191990Sattiliozfs_sync(vfs_t *vfsp, int waitfor) 125168404Spjd{ 126168404Spjd 127168404Spjd /* 128168404Spjd * Data integrity is job one. We don't want a compromised kernel 129168404Spjd * writing to the storage pool, so we never sync during panic. 130168404Spjd */ 131168404Spjd if (panicstr) 132168404Spjd return (0); 133168404Spjd 134168404Spjd if (vfsp != NULL) { 135168404Spjd /* 136168404Spjd * Sync a specific filesystem. 137168404Spjd */ 138168404Spjd zfsvfs_t *zfsvfs = vfsp->vfs_data; 139209962Smm dsl_pool_t *dp; 140168404Spjd int error; 141168404Spjd 142191990Sattilio error = vfs_stdsync(vfsp, waitfor); 143168404Spjd if (error != 0) 144168404Spjd return (error); 145168404Spjd 146168404Spjd ZFS_ENTER(zfsvfs); 147209962Smm dp = dmu_objset_pool(zfsvfs->z_os); 148209962Smm 149209962Smm /* 150209962Smm * If the system is shutting down, then skip any 151209962Smm * filesystems which may exist on a suspended pool. 152209962Smm */ 153209962Smm if (sys_shutdown && spa_suspended(dp->dp_spa)) { 154209962Smm ZFS_EXIT(zfsvfs); 155209962Smm return (0); 156209962Smm } 157209962Smm 158168404Spjd if (zfsvfs->z_log != NULL) 159168404Spjd zil_commit(zfsvfs->z_log, UINT64_MAX, 0); 160168404Spjd else 161209962Smm txg_wait_synced(dp, 0); 162168404Spjd ZFS_EXIT(zfsvfs); 163168404Spjd } else { 164168404Spjd /* 165168404Spjd * Sync all ZFS filesystems. This is what happens when you 166168404Spjd * run sync(1M). Unlike other filesystems, ZFS honors the 167168404Spjd * request by waiting for all pools to commit all dirty data. 168168404Spjd */ 169168404Spjd spa_sync_allpools(); 170168404Spjd } 171168404Spjd 172168404Spjd return (0); 173168404Spjd} 174168404Spjd 175168404Spjdstatic void 176168404Spjdatime_changed_cb(void *arg, uint64_t newval) 177168404Spjd{ 178168404Spjd zfsvfs_t *zfsvfs = arg; 179168404Spjd 180168404Spjd if (newval == TRUE) { 181168404Spjd zfsvfs->z_atime = TRUE; 182168404Spjd zfsvfs->z_vfs->vfs_flag &= ~MNT_NOATIME; 183168404Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME); 184168404Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_ATIME, NULL, 0); 185168404Spjd } else { 186168404Spjd zfsvfs->z_atime = FALSE; 187168404Spjd zfsvfs->z_vfs->vfs_flag |= MNT_NOATIME; 188168404Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_ATIME); 189168404Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME, NULL, 0); 190168404Spjd } 191168404Spjd} 192168404Spjd 193168404Spjdstatic void 194168404Spjdxattr_changed_cb(void *arg, uint64_t newval) 195168404Spjd{ 196168404Spjd zfsvfs_t *zfsvfs = arg; 197168404Spjd 198168404Spjd if (newval == TRUE) { 199168404Spjd /* XXX locking on vfs_flag? */ 200168404Spjd#ifdef TODO 201168404Spjd zfsvfs->z_vfs->vfs_flag |= VFS_XATTR; 202168404Spjd#endif 203168404Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR); 204168404Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_XATTR, NULL, 0); 205168404Spjd } else { 206168404Spjd /* XXX locking on vfs_flag? */ 207168404Spjd#ifdef TODO 208168404Spjd zfsvfs->z_vfs->vfs_flag &= ~VFS_XATTR; 209168404Spjd#endif 210168404Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_XATTR); 211168404Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR, NULL, 0); 212168404Spjd } 213168404Spjd} 214168404Spjd 215168404Spjdstatic void 216168404Spjdblksz_changed_cb(void *arg, uint64_t newval) 217168404Spjd{ 218168404Spjd zfsvfs_t *zfsvfs = arg; 219168404Spjd 220168404Spjd if (newval < SPA_MINBLOCKSIZE || 221168404Spjd newval > SPA_MAXBLOCKSIZE || !ISP2(newval)) 222168404Spjd newval = SPA_MAXBLOCKSIZE; 223168404Spjd 224168404Spjd zfsvfs->z_max_blksz = newval; 225204101Spjd zfsvfs->z_vfs->mnt_stat.f_iosize = newval; 226168404Spjd} 227168404Spjd 228168404Spjdstatic void 229168404Spjdreadonly_changed_cb(void *arg, uint64_t newval) 230168404Spjd{ 231168404Spjd zfsvfs_t *zfsvfs = arg; 232168404Spjd 233168404Spjd if (newval) { 234168404Spjd /* XXX locking on vfs_flag? */ 235168404Spjd zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY; 236168404Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RW); 237168404Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RO, NULL, 0); 238168404Spjd } else { 239168404Spjd /* XXX locking on vfs_flag? */ 240168404Spjd zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 241168404Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RO); 242168404Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RW, NULL, 0); 243168404Spjd } 244168404Spjd} 245168404Spjd 246168404Spjdstatic void 247168404Spjdsetuid_changed_cb(void *arg, uint64_t newval) 248168404Spjd{ 249168404Spjd zfsvfs_t *zfsvfs = arg; 250168404Spjd 251168404Spjd if (newval == FALSE) { 252168404Spjd zfsvfs->z_vfs->vfs_flag |= VFS_NOSETUID; 253168404Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_SETUID); 254168404Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID, NULL, 0); 255168404Spjd } else { 256168404Spjd zfsvfs->z_vfs->vfs_flag &= ~VFS_NOSETUID; 257168404Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID); 258168404Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_SETUID, NULL, 0); 259168404Spjd } 260168404Spjd} 261168404Spjd 262168404Spjdstatic void 263168404Spjdexec_changed_cb(void *arg, uint64_t newval) 264168404Spjd{ 265168404Spjd zfsvfs_t *zfsvfs = arg; 266168404Spjd 267168404Spjd if (newval == FALSE) { 268168404Spjd zfsvfs->z_vfs->vfs_flag |= VFS_NOEXEC; 269168404Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_EXEC); 270168404Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC, NULL, 0); 271168404Spjd } else { 272168404Spjd zfsvfs->z_vfs->vfs_flag &= ~VFS_NOEXEC; 273168404Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC); 274168404Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_EXEC, NULL, 0); 275168404Spjd } 276168404Spjd} 277168404Spjd 278185029Spjd/* 279185029Spjd * The nbmand mount option can be changed at mount time. 280185029Spjd * We can't allow it to be toggled on live file systems or incorrect 281185029Spjd * behavior may be seen from cifs clients 282185029Spjd * 283185029Spjd * This property isn't registered via dsl_prop_register(), but this callback 284185029Spjd * will be called when a file system is first mounted 285185029Spjd */ 286168404Spjdstatic void 287185029Spjdnbmand_changed_cb(void *arg, uint64_t newval) 288185029Spjd{ 289185029Spjd zfsvfs_t *zfsvfs = arg; 290185029Spjd if (newval == FALSE) { 291185029Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND); 292185029Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND, NULL, 0); 293185029Spjd } else { 294185029Spjd vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND); 295185029Spjd vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND, NULL, 0); 296185029Spjd } 297185029Spjd} 298185029Spjd 299185029Spjdstatic void 300168404Spjdsnapdir_changed_cb(void *arg, uint64_t newval) 301168404Spjd{ 302168404Spjd zfsvfs_t *zfsvfs = arg; 303168404Spjd 304168404Spjd zfsvfs->z_show_ctldir = newval; 305168404Spjd} 306168404Spjd 307168404Spjdstatic void 308185029Spjdvscan_changed_cb(void *arg, uint64_t newval) 309185029Spjd{ 310185029Spjd zfsvfs_t *zfsvfs = arg; 311185029Spjd 312185029Spjd zfsvfs->z_vscan = newval; 313185029Spjd} 314185029Spjd 315185029Spjdstatic void 316168404Spjdacl_mode_changed_cb(void *arg, uint64_t newval) 317168404Spjd{ 318168404Spjd zfsvfs_t *zfsvfs = arg; 319168404Spjd 320168404Spjd zfsvfs->z_acl_mode = newval; 321168404Spjd} 322168404Spjd 323168404Spjdstatic void 324168404Spjdacl_inherit_changed_cb(void *arg, uint64_t newval) 325168404Spjd{ 326168404Spjd zfsvfs_t *zfsvfs = arg; 327168404Spjd 328168404Spjd zfsvfs->z_acl_inherit = newval; 329168404Spjd} 330168404Spjd 331168404Spjdstatic int 332168404Spjdzfs_register_callbacks(vfs_t *vfsp) 333168404Spjd{ 334168404Spjd struct dsl_dataset *ds = NULL; 335168404Spjd objset_t *os = NULL; 336168404Spjd zfsvfs_t *zfsvfs = NULL; 337185029Spjd uint64_t nbmand; 338168404Spjd int readonly, do_readonly = FALSE; 339168404Spjd int setuid, do_setuid = FALSE; 340168404Spjd int exec, do_exec = FALSE; 341168404Spjd int xattr, do_xattr = FALSE; 342185029Spjd int atime, do_atime = FALSE; 343168404Spjd int error = 0; 344168404Spjd 345168404Spjd ASSERT(vfsp); 346168404Spjd zfsvfs = vfsp->vfs_data; 347168404Spjd ASSERT(zfsvfs); 348168404Spjd os = zfsvfs->z_os; 349168404Spjd 350168404Spjd /* 351196965Spjd * This function can be called for a snapshot when we update snapshot's 352196965Spjd * mount point, which isn't really supported. 353196965Spjd */ 354196965Spjd if (dmu_objset_is_snapshot(os)) 355196965Spjd return (EOPNOTSUPP); 356196965Spjd 357196965Spjd /* 358168404Spjd * The act of registering our callbacks will destroy any mount 359168404Spjd * options we may have. In order to enable temporary overrides 360168404Spjd * of mount options, we stash away the current values and 361168404Spjd * restore them after we register the callbacks. 362168404Spjd */ 363168404Spjd if (vfs_optionisset(vfsp, MNTOPT_RO, NULL)) { 364168404Spjd readonly = B_TRUE; 365168404Spjd do_readonly = B_TRUE; 366168404Spjd } else if (vfs_optionisset(vfsp, MNTOPT_RW, NULL)) { 367168404Spjd readonly = B_FALSE; 368168404Spjd do_readonly = B_TRUE; 369168404Spjd } 370168404Spjd if (vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL)) { 371168404Spjd setuid = B_FALSE; 372168404Spjd do_setuid = B_TRUE; 373168404Spjd } else { 374168404Spjd if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) { 375168404Spjd setuid = B_FALSE; 376168404Spjd do_setuid = B_TRUE; 377168404Spjd } else if (vfs_optionisset(vfsp, MNTOPT_SETUID, NULL)) { 378168404Spjd setuid = B_TRUE; 379168404Spjd do_setuid = B_TRUE; 380168404Spjd } 381168404Spjd } 382168404Spjd if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) { 383168404Spjd exec = B_FALSE; 384168404Spjd do_exec = B_TRUE; 385168404Spjd } else if (vfs_optionisset(vfsp, MNTOPT_EXEC, NULL)) { 386168404Spjd exec = B_TRUE; 387168404Spjd do_exec = B_TRUE; 388168404Spjd } 389168404Spjd if (vfs_optionisset(vfsp, MNTOPT_NOXATTR, NULL)) { 390168404Spjd xattr = B_FALSE; 391168404Spjd do_xattr = B_TRUE; 392168404Spjd } else if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) { 393168404Spjd xattr = B_TRUE; 394168404Spjd do_xattr = B_TRUE; 395168404Spjd } 396185029Spjd if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) { 397185029Spjd atime = B_FALSE; 398185029Spjd do_atime = B_TRUE; 399185029Spjd } else if (vfs_optionisset(vfsp, MNTOPT_ATIME, NULL)) { 400185029Spjd atime = B_TRUE; 401185029Spjd do_atime = B_TRUE; 402185029Spjd } 403168404Spjd 404168404Spjd /* 405185029Spjd * nbmand is a special property. It can only be changed at 406185029Spjd * mount time. 407185029Spjd * 408185029Spjd * This is weird, but it is documented to only be changeable 409185029Spjd * at mount time. 410185029Spjd */ 411185029Spjd if (vfs_optionisset(vfsp, MNTOPT_NONBMAND, NULL)) { 412185029Spjd nbmand = B_FALSE; 413185029Spjd } else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) { 414185029Spjd nbmand = B_TRUE; 415185029Spjd } else { 416185029Spjd char osname[MAXNAMELEN]; 417185029Spjd 418185029Spjd dmu_objset_name(os, osname); 419185029Spjd if (error = dsl_prop_get_integer(osname, "nbmand", &nbmand, 420185029Spjd NULL)) { 421185029Spjd return (error); 422185029Spjd } 423185029Spjd } 424185029Spjd 425185029Spjd /* 426168404Spjd * Register property callbacks. 427168404Spjd * 428168404Spjd * It would probably be fine to just check for i/o error from 429168404Spjd * the first prop_register(), but I guess I like to go 430168404Spjd * overboard... 431168404Spjd */ 432168404Spjd ds = dmu_objset_ds(os); 433168404Spjd error = dsl_prop_register(ds, "atime", atime_changed_cb, zfsvfs); 434168404Spjd error = error ? error : dsl_prop_register(ds, 435168404Spjd "xattr", xattr_changed_cb, zfsvfs); 436168404Spjd error = error ? error : dsl_prop_register(ds, 437168404Spjd "recordsize", blksz_changed_cb, zfsvfs); 438168404Spjd error = error ? error : dsl_prop_register(ds, 439168404Spjd "readonly", readonly_changed_cb, zfsvfs); 440168404Spjd error = error ? error : dsl_prop_register(ds, 441168404Spjd "setuid", setuid_changed_cb, zfsvfs); 442168404Spjd error = error ? error : dsl_prop_register(ds, 443168404Spjd "exec", exec_changed_cb, zfsvfs); 444168404Spjd error = error ? error : dsl_prop_register(ds, 445168404Spjd "snapdir", snapdir_changed_cb, zfsvfs); 446168404Spjd error = error ? error : dsl_prop_register(ds, 447168404Spjd "aclmode", acl_mode_changed_cb, zfsvfs); 448168404Spjd error = error ? error : dsl_prop_register(ds, 449168404Spjd "aclinherit", acl_inherit_changed_cb, zfsvfs); 450185029Spjd error = error ? error : dsl_prop_register(ds, 451185029Spjd "vscan", vscan_changed_cb, zfsvfs); 452168404Spjd if (error) 453168404Spjd goto unregister; 454168404Spjd 455168404Spjd /* 456168404Spjd * Invoke our callbacks to restore temporary mount options. 457168404Spjd */ 458168404Spjd if (do_readonly) 459168404Spjd readonly_changed_cb(zfsvfs, readonly); 460168404Spjd if (do_setuid) 461168404Spjd setuid_changed_cb(zfsvfs, setuid); 462168404Spjd if (do_exec) 463168404Spjd exec_changed_cb(zfsvfs, exec); 464168404Spjd if (do_xattr) 465168404Spjd xattr_changed_cb(zfsvfs, xattr); 466185029Spjd if (do_atime) 467185029Spjd atime_changed_cb(zfsvfs, atime); 468168404Spjd 469185029Spjd nbmand_changed_cb(zfsvfs, nbmand); 470185029Spjd 471168404Spjd return (0); 472168404Spjd 473168404Spjdunregister: 474168404Spjd /* 475168404Spjd * We may attempt to unregister some callbacks that are not 476168404Spjd * registered, but this is OK; it will simply return ENOMSG, 477168404Spjd * which we will ignore. 478168404Spjd */ 479168404Spjd (void) dsl_prop_unregister(ds, "atime", atime_changed_cb, zfsvfs); 480168404Spjd (void) dsl_prop_unregister(ds, "xattr", xattr_changed_cb, zfsvfs); 481168404Spjd (void) dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, zfsvfs); 482168404Spjd (void) dsl_prop_unregister(ds, "readonly", readonly_changed_cb, zfsvfs); 483168404Spjd (void) dsl_prop_unregister(ds, "setuid", setuid_changed_cb, zfsvfs); 484168404Spjd (void) dsl_prop_unregister(ds, "exec", exec_changed_cb, zfsvfs); 485168404Spjd (void) dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, zfsvfs); 486168404Spjd (void) dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, zfsvfs); 487168404Spjd (void) dsl_prop_unregister(ds, "aclinherit", acl_inherit_changed_cb, 488168404Spjd zfsvfs); 489185029Spjd (void) dsl_prop_unregister(ds, "vscan", vscan_changed_cb, zfsvfs); 490168404Spjd return (error); 491168404Spjd 492168404Spjd} 493168404Spjd 494209962Smmstatic void 495209962Smmuidacct(objset_t *os, boolean_t isgroup, uint64_t fuid, 496209962Smm int64_t delta, dmu_tx_t *tx) 497209962Smm{ 498209962Smm uint64_t used = 0; 499209962Smm char buf[32]; 500209962Smm int err; 501209962Smm uint64_t obj = isgroup ? DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT; 502209962Smm 503209962Smm if (delta == 0) 504209962Smm return; 505209962Smm 506209962Smm (void) snprintf(buf, sizeof (buf), "%llx", (longlong_t)fuid); 507209962Smm err = zap_lookup(os, obj, buf, 8, 1, &used); 508209962Smm ASSERT(err == 0 || err == ENOENT); 509209962Smm /* no underflow/overflow */ 510209962Smm ASSERT(delta > 0 || used >= -delta); 511209962Smm ASSERT(delta < 0 || used + delta > used); 512209962Smm used += delta; 513209962Smm if (used == 0) 514209962Smm err = zap_remove(os, obj, buf, tx); 515209962Smm else 516209962Smm err = zap_update(os, obj, buf, 8, 1, &used, tx); 517209962Smm ASSERT(err == 0); 518209962Smm} 519209962Smm 520209962Smmstatic void 521209962Smmzfs_space_delta_cb(objset_t *os, dmu_object_type_t bonustype, 522209962Smm void *oldbonus, void *newbonus, 523209962Smm uint64_t oldused, uint64_t newused, dmu_tx_t *tx) 524209962Smm{ 525209962Smm znode_phys_t *oldznp = oldbonus; 526209962Smm znode_phys_t *newznp = newbonus; 527209962Smm 528209962Smm if (bonustype != DMU_OT_ZNODE) 529209962Smm return; 530209962Smm 531209962Smm /* We charge 512 for the dnode (if it's allocated). */ 532209962Smm if (oldznp->zp_gen != 0) 533209962Smm oldused += DNODE_SIZE; 534209962Smm if (newznp->zp_gen != 0) 535209962Smm newused += DNODE_SIZE; 536209962Smm 537209962Smm if (oldznp->zp_uid == newznp->zp_uid) { 538209962Smm uidacct(os, B_FALSE, oldznp->zp_uid, newused-oldused, tx); 539209962Smm } else { 540209962Smm uidacct(os, B_FALSE, oldznp->zp_uid, -oldused, tx); 541209962Smm uidacct(os, B_FALSE, newznp->zp_uid, newused, tx); 542209962Smm } 543209962Smm 544209962Smm if (oldznp->zp_gid == newznp->zp_gid) { 545209962Smm uidacct(os, B_TRUE, oldznp->zp_gid, newused-oldused, tx); 546209962Smm } else { 547209962Smm uidacct(os, B_TRUE, oldznp->zp_gid, -oldused, tx); 548209962Smm uidacct(os, B_TRUE, newznp->zp_gid, newused, tx); 549209962Smm } 550209962Smm} 551209962Smm 552209962Smmstatic void 553209962Smmfuidstr_to_sid(zfsvfs_t *zfsvfs, const char *fuidstr, 554209962Smm char *domainbuf, int buflen, uid_t *ridp) 555209962Smm{ 556209962Smm uint64_t fuid; 557209962Smm const char *domain; 558209962Smm 559209962Smm fuid = strtonum(fuidstr, NULL); 560209962Smm 561209962Smm domain = zfs_fuid_find_by_idx(zfsvfs, FUID_INDEX(fuid)); 562209962Smm if (domain) 563209962Smm (void) strlcpy(domainbuf, domain, buflen); 564209962Smm else 565209962Smm domainbuf[0] = '\0'; 566209962Smm *ridp = FUID_RID(fuid); 567209962Smm} 568209962Smm 569209962Smmstatic uint64_t 570209962Smmzfs_userquota_prop_to_obj(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type) 571209962Smm{ 572209962Smm switch (type) { 573209962Smm case ZFS_PROP_USERUSED: 574209962Smm return (DMU_USERUSED_OBJECT); 575209962Smm case ZFS_PROP_GROUPUSED: 576209962Smm return (DMU_GROUPUSED_OBJECT); 577209962Smm case ZFS_PROP_USERQUOTA: 578209962Smm return (zfsvfs->z_userquota_obj); 579209962Smm case ZFS_PROP_GROUPQUOTA: 580209962Smm return (zfsvfs->z_groupquota_obj); 581209962Smm } 582209962Smm return (0); 583209962Smm} 584209962Smm 585209962Smmint 586209962Smmzfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 587209962Smm uint64_t *cookiep, void *vbuf, uint64_t *bufsizep) 588209962Smm{ 589209962Smm int error; 590209962Smm zap_cursor_t zc; 591209962Smm zap_attribute_t za; 592209962Smm zfs_useracct_t *buf = vbuf; 593209962Smm uint64_t obj; 594209962Smm 595209962Smm if (!dmu_objset_userspace_present(zfsvfs->z_os)) 596209962Smm return (ENOTSUP); 597209962Smm 598209962Smm obj = zfs_userquota_prop_to_obj(zfsvfs, type); 599209962Smm if (obj == 0) { 600209962Smm *bufsizep = 0; 601209962Smm return (0); 602209962Smm } 603209962Smm 604209962Smm for (zap_cursor_init_serialized(&zc, zfsvfs->z_os, obj, *cookiep); 605209962Smm (error = zap_cursor_retrieve(&zc, &za)) == 0; 606209962Smm zap_cursor_advance(&zc)) { 607209962Smm if ((uintptr_t)buf - (uintptr_t)vbuf + sizeof (zfs_useracct_t) > 608209962Smm *bufsizep) 609209962Smm break; 610209962Smm 611209962Smm fuidstr_to_sid(zfsvfs, za.za_name, 612209962Smm buf->zu_domain, sizeof (buf->zu_domain), &buf->zu_rid); 613209962Smm 614209962Smm buf->zu_space = za.za_first_integer; 615209962Smm buf++; 616209962Smm } 617209962Smm if (error == ENOENT) 618209962Smm error = 0; 619209962Smm 620209962Smm ASSERT3U((uintptr_t)buf - (uintptr_t)vbuf, <=, *bufsizep); 621209962Smm *bufsizep = (uintptr_t)buf - (uintptr_t)vbuf; 622209962Smm *cookiep = zap_cursor_serialize(&zc); 623209962Smm zap_cursor_fini(&zc); 624209962Smm return (error); 625209962Smm} 626209962Smm 627209962Smm/* 628209962Smm * buf must be big enough (eg, 32 bytes) 629209962Smm */ 630168404Spjdstatic int 631209962Smmid_to_fuidstr(zfsvfs_t *zfsvfs, const char *domain, uid_t rid, 632209962Smm char *buf, boolean_t addok) 633209962Smm{ 634209962Smm uint64_t fuid; 635209962Smm int domainid = 0; 636209962Smm 637209962Smm if (domain && domain[0]) { 638209962Smm domainid = zfs_fuid_find_by_domain(zfsvfs, domain, NULL, addok); 639209962Smm if (domainid == -1) 640209962Smm return (ENOENT); 641209962Smm } 642209962Smm fuid = FUID_ENCODE(domainid, rid); 643209962Smm (void) sprintf(buf, "%llx", (longlong_t)fuid); 644209962Smm return (0); 645209962Smm} 646209962Smm 647209962Smmint 648209962Smmzfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 649209962Smm const char *domain, uint64_t rid, uint64_t *valp) 650209962Smm{ 651209962Smm char buf[32]; 652209962Smm int err; 653209962Smm uint64_t obj; 654209962Smm 655209962Smm *valp = 0; 656209962Smm 657209962Smm if (!dmu_objset_userspace_present(zfsvfs->z_os)) 658209962Smm return (ENOTSUP); 659209962Smm 660209962Smm obj = zfs_userquota_prop_to_obj(zfsvfs, type); 661209962Smm if (obj == 0) 662209962Smm return (0); 663209962Smm 664209962Smm err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_FALSE); 665209962Smm if (err) 666209962Smm return (err); 667209962Smm 668209962Smm err = zap_lookup(zfsvfs->z_os, obj, buf, 8, 1, valp); 669209962Smm if (err == ENOENT) 670209962Smm err = 0; 671209962Smm return (err); 672209962Smm} 673209962Smm 674209962Smmint 675209962Smmzfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 676209962Smm const char *domain, uint64_t rid, uint64_t quota) 677209962Smm{ 678209962Smm char buf[32]; 679209962Smm int err; 680209962Smm dmu_tx_t *tx; 681209962Smm uint64_t *objp; 682209962Smm boolean_t fuid_dirtied; 683209962Smm 684209962Smm if (type != ZFS_PROP_USERQUOTA && type != ZFS_PROP_GROUPQUOTA) 685209962Smm return (EINVAL); 686209962Smm 687209962Smm if (zfsvfs->z_version < ZPL_VERSION_USERSPACE) 688209962Smm return (ENOTSUP); 689209962Smm 690209962Smm objp = (type == ZFS_PROP_USERQUOTA) ? &zfsvfs->z_userquota_obj : 691209962Smm &zfsvfs->z_groupquota_obj; 692209962Smm 693209962Smm err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_TRUE); 694209962Smm if (err) 695209962Smm return (err); 696209962Smm fuid_dirtied = zfsvfs->z_fuid_dirty; 697209962Smm 698209962Smm tx = dmu_tx_create(zfsvfs->z_os); 699209962Smm dmu_tx_hold_zap(tx, *objp ? *objp : DMU_NEW_OBJECT, B_TRUE, NULL); 700209962Smm if (*objp == 0) { 701209962Smm dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE, 702209962Smm zfs_userquota_prop_prefixes[type]); 703209962Smm } 704209962Smm if (fuid_dirtied) 705209962Smm zfs_fuid_txhold(zfsvfs, tx); 706209962Smm err = dmu_tx_assign(tx, TXG_WAIT); 707209962Smm if (err) { 708209962Smm dmu_tx_abort(tx); 709209962Smm return (err); 710209962Smm } 711209962Smm 712209962Smm mutex_enter(&zfsvfs->z_lock); 713209962Smm if (*objp == 0) { 714209962Smm *objp = zap_create(zfsvfs->z_os, DMU_OT_USERGROUP_QUOTA, 715209962Smm DMU_OT_NONE, 0, tx); 716209962Smm VERIFY(0 == zap_add(zfsvfs->z_os, MASTER_NODE_OBJ, 717209962Smm zfs_userquota_prop_prefixes[type], 8, 1, objp, tx)); 718209962Smm } 719209962Smm mutex_exit(&zfsvfs->z_lock); 720209962Smm 721209962Smm if (quota == 0) { 722209962Smm err = zap_remove(zfsvfs->z_os, *objp, buf, tx); 723209962Smm if (err == ENOENT) 724209962Smm err = 0; 725209962Smm } else { 726209962Smm err = zap_update(zfsvfs->z_os, *objp, buf, 8, 1, "a, tx); 727209962Smm } 728209962Smm ASSERT(err == 0); 729209962Smm if (fuid_dirtied) 730209962Smm zfs_fuid_sync(zfsvfs, tx); 731209962Smm dmu_tx_commit(tx); 732209962Smm return (err); 733209962Smm} 734209962Smm 735209962Smmboolean_t 736209962Smmzfs_usergroup_overquota(zfsvfs_t *zfsvfs, boolean_t isgroup, uint64_t fuid) 737209962Smm{ 738209962Smm char buf[32]; 739209962Smm uint64_t used, quota, usedobj, quotaobj; 740209962Smm int err; 741209962Smm 742209962Smm usedobj = isgroup ? DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT; 743209962Smm quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj; 744209962Smm 745209962Smm if (quotaobj == 0 || zfsvfs->z_replay) 746209962Smm return (B_FALSE); 747209962Smm 748209962Smm (void) sprintf(buf, "%llx", (longlong_t)fuid); 749209962Smm err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); 750209962Smm if (err != 0) 751209962Smm return (B_FALSE); 752209962Smm 753209962Smm err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used); 754209962Smm if (err != 0) 755209962Smm return (B_FALSE); 756209962Smm return (used >= quota); 757209962Smm} 758209962Smm 759209962Smmint 760209962Smmzfsvfs_create(const char *osname, int mode, zfsvfs_t **zvp) 761209962Smm{ 762209962Smm objset_t *os; 763209962Smm zfsvfs_t *zfsvfs; 764209962Smm uint64_t zval; 765209962Smm int i, error; 766209962Smm 767209962Smm if (error = dsl_prop_get_integer(osname, "readonly", &zval, NULL)) 768209962Smm return (error); 769209962Smm if (zval) 770209962Smm mode |= DS_MODE_READONLY; 771209962Smm 772209962Smm error = dmu_objset_open(osname, DMU_OST_ZFS, mode, &os); 773209962Smm if (error == EROFS) { 774209962Smm mode |= DS_MODE_READONLY; 775209962Smm error = dmu_objset_open(osname, DMU_OST_ZFS, mode, &os); 776209962Smm } 777209962Smm if (error) 778209962Smm return (error); 779209962Smm 780209962Smm /* 781209962Smm * Initialize the zfs-specific filesystem structure. 782209962Smm * Should probably make this a kmem cache, shuffle fields, 783209962Smm * and just bzero up to z_hold_mtx[]. 784209962Smm */ 785209962Smm zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); 786209962Smm zfsvfs->z_vfs = NULL; 787209962Smm zfsvfs->z_parent = zfsvfs; 788209962Smm zfsvfs->z_max_blksz = SPA_MAXBLOCKSIZE; 789209962Smm zfsvfs->z_show_ctldir = ZFS_SNAPDIR_VISIBLE; 790209962Smm zfsvfs->z_os = os; 791209962Smm 792209962Smm error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zfsvfs->z_version); 793209962Smm if (error) { 794209962Smm goto out; 795209962Smm } else if (zfsvfs->z_version > ZPL_VERSION) { 796209962Smm (void) printf("Mismatched versions: File system " 797209962Smm "is version %llu on-disk format, which is " 798209962Smm "incompatible with this software version %lld!", 799209962Smm (u_longlong_t)zfsvfs->z_version, ZPL_VERSION); 800209962Smm error = ENOTSUP; 801209962Smm goto out; 802209962Smm } 803209962Smm 804209962Smm if ((error = zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &zval)) != 0) 805209962Smm goto out; 806209962Smm zfsvfs->z_norm = (int)zval; 807209962Smm 808209962Smm if ((error = zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &zval)) != 0) 809209962Smm goto out; 810209962Smm zfsvfs->z_utf8 = (zval != 0); 811209962Smm 812209962Smm if ((error = zfs_get_zplprop(os, ZFS_PROP_CASE, &zval)) != 0) 813209962Smm goto out; 814209962Smm zfsvfs->z_case = (uint_t)zval; 815209962Smm 816209962Smm /* 817209962Smm * Fold case on file systems that are always or sometimes case 818209962Smm * insensitive. 819209962Smm */ 820209962Smm if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE || 821209962Smm zfsvfs->z_case == ZFS_CASE_MIXED) 822209962Smm zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER; 823209962Smm 824209962Smm zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os); 825209962Smm 826209962Smm error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, 827209962Smm &zfsvfs->z_root); 828209962Smm if (error) 829209962Smm goto out; 830209962Smm ASSERT(zfsvfs->z_root != 0); 831209962Smm 832209962Smm error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET, 8, 1, 833209962Smm &zfsvfs->z_unlinkedobj); 834209962Smm if (error) 835209962Smm goto out; 836209962Smm 837209962Smm error = zap_lookup(os, MASTER_NODE_OBJ, 838209962Smm zfs_userquota_prop_prefixes[ZFS_PROP_USERQUOTA], 839209962Smm 8, 1, &zfsvfs->z_userquota_obj); 840209962Smm if (error && error != ENOENT) 841209962Smm goto out; 842209962Smm 843209962Smm error = zap_lookup(os, MASTER_NODE_OBJ, 844209962Smm zfs_userquota_prop_prefixes[ZFS_PROP_GROUPQUOTA], 845209962Smm 8, 1, &zfsvfs->z_groupquota_obj); 846209962Smm if (error && error != ENOENT) 847209962Smm goto out; 848209962Smm 849209962Smm error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES, 8, 1, 850209962Smm &zfsvfs->z_fuid_obj); 851209962Smm if (error && error != ENOENT) 852209962Smm goto out; 853209962Smm 854209962Smm error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SHARES_DIR, 8, 1, 855209962Smm &zfsvfs->z_shares_dir); 856209962Smm if (error && error != ENOENT) 857209962Smm goto out; 858209962Smm 859209962Smm mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); 860209962Smm mutex_init(&zfsvfs->z_online_recv_lock, NULL, MUTEX_DEFAULT, NULL); 861209962Smm mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL); 862209962Smm list_create(&zfsvfs->z_all_znodes, sizeof (znode_t), 863209962Smm offsetof(znode_t, z_link_node)); 864209962Smm rrw_init(&zfsvfs->z_teardown_lock); 865209962Smm rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL); 866209962Smm rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL); 867209962Smm for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) 868209962Smm mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); 869209962Smm 870209962Smm *zvp = zfsvfs; 871209962Smm return (0); 872209962Smm 873209962Smmout: 874209962Smm dmu_objset_close(os); 875209962Smm *zvp = NULL; 876209962Smm kmem_free(zfsvfs, sizeof (zfsvfs_t)); 877209962Smm return (error); 878209962Smm} 879209962Smm 880209962Smmstatic int 881185029Spjdzfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) 882168404Spjd{ 883185029Spjd int error; 884185029Spjd 885185029Spjd error = zfs_register_callbacks(zfsvfs->z_vfs); 886185029Spjd if (error) 887185029Spjd return (error); 888185029Spjd 889185029Spjd /* 890185029Spjd * Set the objset user_ptr to track its zfsvfs. 891185029Spjd */ 892185029Spjd mutex_enter(&zfsvfs->z_os->os->os_user_ptr_lock); 893185029Spjd dmu_objset_set_user(zfsvfs->z_os, zfsvfs); 894185029Spjd mutex_exit(&zfsvfs->z_os->os->os_user_ptr_lock); 895185029Spjd 896208689Smm zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data); 897208689Smm if (zil_disable) { 898208689Smm zil_destroy(zfsvfs->z_log, B_FALSE); 899208689Smm zfsvfs->z_log = NULL; 900208689Smm } 901208689Smm 902185029Spjd /* 903185029Spjd * If we are not mounting (ie: online recv), then we don't 904185029Spjd * have to worry about replaying the log as we blocked all 905185029Spjd * operations out since we closed the ZIL. 906185029Spjd */ 907185029Spjd if (mounting) { 908185029Spjd boolean_t readonly; 909185029Spjd 910185029Spjd /* 911185029Spjd * During replay we remove the read only flag to 912185029Spjd * allow replays to succeed. 913185029Spjd */ 914185029Spjd readonly = zfsvfs->z_vfs->vfs_flag & VFS_RDONLY; 915208689Smm if (readonly != 0) 916208689Smm zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 917208689Smm else 918208689Smm zfs_unlinked_drain(zfsvfs); 919185029Spjd 920208689Smm if (zfsvfs->z_log) { 921208689Smm /* 922208689Smm * Parse and replay the intent log. 923208689Smm * 924208689Smm * Because of ziltest, this must be done after 925208689Smm * zfs_unlinked_drain(). (Further note: ziltest 926208689Smm * doesn't use readonly mounts, where 927208689Smm * zfs_unlinked_drain() isn't called.) This is because 928208689Smm * ziltest causes spa_sync() to think it's committed, 929208689Smm * but actually it is not, so the intent log contains 930208689Smm * many txg's worth of changes. 931208689Smm * 932208689Smm * In particular, if object N is in the unlinked set in 933208689Smm * the last txg to actually sync, then it could be 934208689Smm * actually freed in a later txg and then reallocated 935208689Smm * in a yet later txg. This would write a "create 936208689Smm * object N" record to the intent log. Normally, this 937208689Smm * would be fine because the spa_sync() would have 938208689Smm * written out the fact that object N is free, before 939208689Smm * we could write the "create object N" intent log 940208689Smm * record. 941208689Smm * 942208689Smm * But when we are in ziltest mode, we advance the "open 943208689Smm * txg" without actually spa_sync()-ing the changes to 944208689Smm * disk. So we would see that object N is still 945208689Smm * allocated and in the unlinked set, and there is an 946208689Smm * intent log record saying to allocate it. 947208689Smm */ 948209962Smm zfsvfs->z_replay = B_TRUE; 949209962Smm zil_replay(zfsvfs->z_os, zfsvfs, zfs_replay_vector); 950209962Smm zfsvfs->z_replay = B_FALSE; 951208689Smm } 952185029Spjd zfsvfs->z_vfs->vfs_flag |= readonly; /* restore readonly bit */ 953185029Spjd } 954185029Spjd 955185029Spjd return (0); 956185029Spjd} 957185029Spjd 958210470Smmextern krwlock_t zfsvfs_lock; /* in zfs_znode.c */ 959210470Smm 960209962Smmvoid 961209962Smmzfsvfs_free(zfsvfs_t *zfsvfs) 962185029Spjd{ 963209962Smm int i; 964209962Smm 965210470Smm /* 966210470Smm * This is a barrier to prevent the filesystem from going away in 967210470Smm * zfs_znode_move() until we can safely ensure that the filesystem is 968210470Smm * not unmounted. We consider the filesystem valid before the barrier 969210470Smm * and invalid after the barrier. 970210470Smm */ 971210470Smm rw_enter(&zfsvfs_lock, RW_READER); 972210470Smm rw_exit(&zfsvfs_lock); 973210470Smm 974209962Smm zfs_fuid_destroy(zfsvfs); 975209962Smm 976185029Spjd mutex_destroy(&zfsvfs->z_znodes_lock); 977185029Spjd mutex_destroy(&zfsvfs->z_online_recv_lock); 978209962Smm mutex_destroy(&zfsvfs->z_lock); 979185029Spjd list_destroy(&zfsvfs->z_all_znodes); 980185029Spjd rrw_destroy(&zfsvfs->z_teardown_lock); 981185029Spjd rw_destroy(&zfsvfs->z_teardown_inactive_lock); 982185029Spjd rw_destroy(&zfsvfs->z_fuid_lock); 983209962Smm for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) 984209962Smm mutex_destroy(&zfsvfs->z_hold_mtx[i]); 985185029Spjd kmem_free(zfsvfs, sizeof (zfsvfs_t)); 986185029Spjd} 987185029Spjd 988209962Smmstatic void 989209962Smmzfs_set_fuid_feature(zfsvfs_t *zfsvfs) 990209962Smm{ 991209962Smm zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os); 992209962Smm if (zfsvfs->z_use_fuids && zfsvfs->z_vfs) { 993209962Smm vfs_set_feature(zfsvfs->z_vfs, VFSFT_XVATTR); 994209962Smm vfs_set_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS); 995209962Smm vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS); 996209962Smm vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE); 997211932Smm vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER); 998209962Smm } 999209962Smm} 1000209962Smm 1001185029Spjdstatic int 1002185029Spjdzfs_domount(vfs_t *vfsp, char *osname) 1003185029Spjd{ 1004209962Smm uint64_t recordsize, fsid_guid; 1005168404Spjd int error = 0; 1006168404Spjd zfsvfs_t *zfsvfs; 1007209962Smm vnode_t *vp; 1008168404Spjd 1009168404Spjd ASSERT(vfsp); 1010168404Spjd ASSERT(osname); 1011168404Spjd 1012209962Smm error = zfsvfs_create(osname, DS_MODE_OWNER, &zfsvfs); 1013209962Smm if (error) 1014209962Smm return (error); 1015168404Spjd zfsvfs->z_vfs = vfsp; 1016168404Spjd 1017168404Spjd if (error = dsl_prop_get_integer(osname, "recordsize", &recordsize, 1018168404Spjd NULL)) 1019168404Spjd goto out; 1020204101Spjd zfsvfs->z_vfs->vfs_bsize = SPA_MINBLOCKSIZE; 1021204101Spjd zfsvfs->z_vfs->mnt_stat.f_iosize = recordsize; 1022168404Spjd 1023168404Spjd vfsp->vfs_data = zfsvfs; 1024168404Spjd vfsp->mnt_flag |= MNT_LOCAL; 1025168404Spjd vfsp->mnt_kern_flag |= MNTK_MPSAFE; 1026168404Spjd vfsp->mnt_kern_flag |= MNTK_LOOKUP_SHARED; 1027193440Sps vfsp->mnt_kern_flag |= MNTK_SHARED_WRITES; 1028168404Spjd 1029168404Spjd 1030209962Smm /* 1031209962Smm * The fsid is 64 bits, composed of an 8-bit fs type, which 1032209962Smm * separates our fsid from any other filesystem types, and a 1033209962Smm * 56-bit objset unique ID. The objset unique ID is unique to 1034209962Smm * all objsets open on this system, provided by unique_create(). 1035209962Smm * The 8-bit fs type must be put in the low bits of fsid[1] 1036209962Smm * because that's where other Solaris filesystems put it. 1037209962Smm */ 1038209962Smm fsid_guid = dmu_objset_fsid_guid(zfsvfs->z_os); 1039209962Smm ASSERT((fsid_guid & ~((1ULL<<56)-1)) == 0); 1040209962Smm vfsp->vfs_fsid.val[0] = fsid_guid; 1041209962Smm vfsp->vfs_fsid.val[1] = ((fsid_guid>>32) << 8) | 1042209962Smm vfsp->mnt_vfc->vfc_typenum & 0xFF; 1043168404Spjd 1044185029Spjd /* 1045185029Spjd * Set features for file system. 1046185029Spjd */ 1047209962Smm zfs_set_fuid_feature(zfsvfs); 1048185029Spjd if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) { 1049185029Spjd vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS); 1050185029Spjd vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE); 1051185029Spjd vfs_set_feature(vfsp, VFSFT_NOCASESENSITIVE); 1052185029Spjd } else if (zfsvfs->z_case == ZFS_CASE_MIXED) { 1053185029Spjd vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS); 1054185029Spjd vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE); 1055185029Spjd } 1056185029Spjd 1057168404Spjd if (dmu_objset_is_snapshot(zfsvfs->z_os)) { 1058185029Spjd uint64_t pval; 1059168404Spjd 1060168404Spjd atime_changed_cb(zfsvfs, B_FALSE); 1061168404Spjd readonly_changed_cb(zfsvfs, B_TRUE); 1062185029Spjd if (error = dsl_prop_get_integer(osname, "xattr", &pval, NULL)) 1063168404Spjd goto out; 1064185029Spjd xattr_changed_cb(zfsvfs, pval); 1065168404Spjd zfsvfs->z_issnap = B_TRUE; 1066209962Smm 1067209962Smm mutex_enter(&zfsvfs->z_os->os->os_user_ptr_lock); 1068209962Smm dmu_objset_set_user(zfsvfs->z_os, zfsvfs); 1069209962Smm mutex_exit(&zfsvfs->z_os->os->os_user_ptr_lock); 1070168404Spjd } else { 1071185029Spjd error = zfsvfs_setup(zfsvfs, B_TRUE); 1072168404Spjd } 1073168404Spjd 1074168404Spjd vfs_mountedfrom(vfsp, osname); 1075209962Smm /* Grab extra reference. */ 1076209962Smm VERIFY(VFS_ROOT(vfsp, LK_EXCLUSIVE, &vp) == 0); 1077209962Smm VOP_UNLOCK(vp, 0); 1078168404Spjd 1079168404Spjd if (!zfsvfs->z_issnap) 1080168404Spjd zfsctl_create(zfsvfs); 1081168404Spjdout: 1082168404Spjd if (error) { 1083209962Smm dmu_objset_close(zfsvfs->z_os); 1084209962Smm zfsvfs_free(zfsvfs); 1085168404Spjd } else { 1086168404Spjd atomic_add_32(&zfs_active_fs_count, 1); 1087168404Spjd } 1088168404Spjd 1089168404Spjd return (error); 1090168404Spjd} 1091168404Spjd 1092168404Spjdvoid 1093168404Spjdzfs_unregister_callbacks(zfsvfs_t *zfsvfs) 1094168404Spjd{ 1095168404Spjd objset_t *os = zfsvfs->z_os; 1096168404Spjd struct dsl_dataset *ds; 1097168404Spjd 1098168404Spjd /* 1099168404Spjd * Unregister properties. 1100168404Spjd */ 1101168404Spjd if (!dmu_objset_is_snapshot(os)) { 1102168404Spjd ds = dmu_objset_ds(os); 1103168404Spjd VERIFY(dsl_prop_unregister(ds, "atime", atime_changed_cb, 1104168404Spjd zfsvfs) == 0); 1105168404Spjd 1106168404Spjd VERIFY(dsl_prop_unregister(ds, "xattr", xattr_changed_cb, 1107168404Spjd zfsvfs) == 0); 1108168404Spjd 1109168404Spjd VERIFY(dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, 1110168404Spjd zfsvfs) == 0); 1111168404Spjd 1112168404Spjd VERIFY(dsl_prop_unregister(ds, "readonly", readonly_changed_cb, 1113168404Spjd zfsvfs) == 0); 1114168404Spjd 1115168404Spjd VERIFY(dsl_prop_unregister(ds, "setuid", setuid_changed_cb, 1116168404Spjd zfsvfs) == 0); 1117168404Spjd 1118168404Spjd VERIFY(dsl_prop_unregister(ds, "exec", exec_changed_cb, 1119168404Spjd zfsvfs) == 0); 1120168404Spjd 1121168404Spjd VERIFY(dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, 1122168404Spjd zfsvfs) == 0); 1123168404Spjd 1124168404Spjd VERIFY(dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, 1125168404Spjd zfsvfs) == 0); 1126168404Spjd 1127168404Spjd VERIFY(dsl_prop_unregister(ds, "aclinherit", 1128168404Spjd acl_inherit_changed_cb, zfsvfs) == 0); 1129185029Spjd 1130185029Spjd VERIFY(dsl_prop_unregister(ds, "vscan", 1131185029Spjd vscan_changed_cb, zfsvfs) == 0); 1132168404Spjd } 1133168404Spjd} 1134168404Spjd 1135168404Spjd/*ARGSUSED*/ 1136168404Spjdstatic int 1137191990Sattiliozfs_mount(vfs_t *vfsp) 1138168404Spjd{ 1139191990Sattilio kthread_t *td = curthread; 1140185029Spjd vnode_t *mvp = vfsp->mnt_vnodecovered; 1141185029Spjd cred_t *cr = td->td_ucred; 1142185029Spjd char *osname; 1143185029Spjd int error = 0; 1144185029Spjd int canwrite; 1145168404Spjd 1146185029Spjd if (vfs_getopt(vfsp->mnt_optnew, "from", (void **)&osname, NULL)) 1147185029Spjd return (EINVAL); 1148185029Spjd 1149168404Spjd /* 1150185029Spjd * If full-owner-access is enabled and delegated administration is 1151185029Spjd * turned on, we must set nosuid. 1152185029Spjd */ 1153185029Spjd if (zfs_super_owner && 1154185029Spjd dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) != ECANCELED) { 1155185029Spjd secpolicy_fs_mount_clearopts(cr, vfsp); 1156185029Spjd } 1157185029Spjd 1158185029Spjd /* 1159185029Spjd * Check for mount privilege? 1160185029Spjd * 1161185029Spjd * If we don't have privilege then see if 1162185029Spjd * we have local permission to allow it 1163185029Spjd */ 1164185029Spjd error = secpolicy_fs_mount(cr, mvp, vfsp); 1165185029Spjd if (error) { 1166212694Smm if (dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) != 0) 1167196944Spjd goto out; 1168196944Spjd 1169196944Spjd if (!(vfsp->vfs_flag & MS_REMOUNT)) { 1170185029Spjd vattr_t vattr; 1171185029Spjd 1172185029Spjd /* 1173185029Spjd * Make sure user is the owner of the mount point 1174185029Spjd * or has sufficient privileges. 1175185029Spjd */ 1176185029Spjd 1177185029Spjd vattr.va_mask = AT_UID; 1178185029Spjd 1179196662Spjd vn_lock(mvp, LK_SHARED | LK_RETRY); 1180212694Smm if (VOP_GETATTR(mvp, &vattr, cr)) { 1181196662Spjd VOP_UNLOCK(mvp, 0); 1182185029Spjd goto out; 1183185029Spjd } 1184185029Spjd 1185185029Spjd if (secpolicy_vnode_owner(mvp, cr, vattr.va_uid) != 0 && 1186185029Spjd VOP_ACCESS(mvp, VWRITE, cr, td) != 0) { 1187196662Spjd VOP_UNLOCK(mvp, 0); 1188185029Spjd goto out; 1189185029Spjd } 1190196662Spjd VOP_UNLOCK(mvp, 0); 1191196944Spjd } 1192185029Spjd 1193196944Spjd secpolicy_fs_mount_clearopts(cr, vfsp); 1194185029Spjd } 1195185029Spjd 1196185029Spjd /* 1197185029Spjd * Refuse to mount a filesystem if we are in a local zone and the 1198185029Spjd * dataset is not visible. 1199185029Spjd */ 1200185029Spjd if (!INGLOBALZONE(curthread) && 1201185029Spjd (!zone_dataset_visible(osname, &canwrite) || !canwrite)) { 1202185029Spjd error = EPERM; 1203185029Spjd goto out; 1204185029Spjd } 1205185029Spjd 1206185029Spjd /* 1207168404Spjd * When doing a remount, we simply refresh our temporary properties 1208168404Spjd * according to those options set in the current VFS options. 1209168404Spjd */ 1210185029Spjd if (vfsp->vfs_flag & MS_REMOUNT) { 1211185029Spjd /* refresh mount options */ 1212185029Spjd zfs_unregister_callbacks(vfsp->vfs_data); 1213185029Spjd error = zfs_register_callbacks(vfsp); 1214185029Spjd goto out; 1215185029Spjd } 1216168404Spjd 1217168510Spjd DROP_GIANT(); 1218185029Spjd error = zfs_domount(vfsp, osname); 1219168510Spjd PICKUP_GIANT(); 1220209962Smm 1221215260Smm#ifdef sun 1222209962Smm /* 1223209962Smm * Add an extra VFS_HOLD on our parent vfs so that it can't 1224209962Smm * disappear due to a forced unmount. 1225209962Smm */ 1226209962Smm if (error == 0 && ((zfsvfs_t *)vfsp->vfs_data)->z_issnap) 1227209962Smm VFS_HOLD(mvp->v_vfsp); 1228215260Smm#endif /* sun */ 1229209962Smm 1230185029Spjdout: 1231168510Spjd return (error); 1232168404Spjd} 1233168404Spjd 1234168404Spjdstatic int 1235191990Sattiliozfs_statfs(vfs_t *vfsp, struct statfs *statp) 1236169170Spjd{ 1237168404Spjd zfsvfs_t *zfsvfs = vfsp->vfs_data; 1238168404Spjd uint64_t refdbytes, availbytes, usedobjs, availobjs; 1239168404Spjd 1240168404Spjd statp->f_version = STATFS_VERSION; 1241168404Spjd 1242168404Spjd ZFS_ENTER(zfsvfs); 1243168404Spjd 1244168404Spjd dmu_objset_space(zfsvfs->z_os, 1245168404Spjd &refdbytes, &availbytes, &usedobjs, &availobjs); 1246168404Spjd 1247168404Spjd /* 1248168404Spjd * The underlying storage pool actually uses multiple block sizes. 1249168404Spjd * We report the fragsize as the smallest block size we support, 1250168404Spjd * and we report our blocksize as the filesystem's maximum blocksize. 1251168404Spjd */ 1252204101Spjd statp->f_bsize = SPA_MINBLOCKSIZE; 1253204101Spjd statp->f_iosize = zfsvfs->z_vfs->mnt_stat.f_iosize; 1254168404Spjd 1255168404Spjd /* 1256168404Spjd * The following report "total" blocks of various kinds in the 1257168404Spjd * file system, but reported in terms of f_frsize - the 1258168404Spjd * "fragment" size. 1259168404Spjd */ 1260168404Spjd 1261204101Spjd statp->f_blocks = (refdbytes + availbytes) >> SPA_MINBLOCKSHIFT; 1262168404Spjd statp->f_bfree = availbytes / statp->f_bsize; 1263168404Spjd statp->f_bavail = statp->f_bfree; /* no root reservation */ 1264168404Spjd 1265168404Spjd /* 1266168404Spjd * statvfs() should really be called statufs(), because it assumes 1267168404Spjd * static metadata. ZFS doesn't preallocate files, so the best 1268168404Spjd * we can do is report the max that could possibly fit in f_files, 1269168404Spjd * and that minus the number actually used in f_ffree. 1270168404Spjd * For f_ffree, report the smaller of the number of object available 1271168404Spjd * and the number of blocks (each object will take at least a block). 1272168404Spjd */ 1273168404Spjd statp->f_ffree = MIN(availobjs, statp->f_bfree); 1274168404Spjd statp->f_files = statp->f_ffree + usedobjs; 1275168404Spjd 1276168404Spjd /* 1277168404Spjd * We're a zfs filesystem. 1278168404Spjd */ 1279168404Spjd (void) strlcpy(statp->f_fstypename, "zfs", sizeof(statp->f_fstypename)); 1280168404Spjd 1281168404Spjd strlcpy(statp->f_mntfromname, vfsp->mnt_stat.f_mntfromname, 1282168404Spjd sizeof(statp->f_mntfromname)); 1283168404Spjd strlcpy(statp->f_mntonname, vfsp->mnt_stat.f_mntonname, 1284168404Spjd sizeof(statp->f_mntonname)); 1285168404Spjd 1286168404Spjd statp->f_namemax = ZFS_MAXNAMELEN; 1287168404Spjd 1288168404Spjd ZFS_EXIT(zfsvfs); 1289168404Spjd return (0); 1290168404Spjd} 1291168404Spjd 1292168404Spjdstatic int 1293191990Sattiliozfs_root(vfs_t *vfsp, int flags, vnode_t **vpp) 1294168404Spjd{ 1295168404Spjd zfsvfs_t *zfsvfs = vfsp->vfs_data; 1296168404Spjd znode_t *rootzp; 1297168404Spjd int error; 1298168404Spjd 1299197459Spjd ZFS_ENTER_NOERROR(zfsvfs); 1300168404Spjd 1301168404Spjd error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); 1302206667Spjd 1303206667Spjd ZFS_EXIT(zfsvfs); 1304206667Spjd 1305168404Spjd if (error == 0) { 1306168404Spjd *vpp = ZTOV(rootzp); 1307175202Sattilio error = vn_lock(*vpp, flags); 1308168404Spjd (*vpp)->v_vflag |= VV_ROOT; 1309168404Spjd } 1310168404Spjd 1311168404Spjd return (error); 1312168404Spjd} 1313168404Spjd 1314185029Spjd/* 1315185029Spjd * Teardown the zfsvfs::z_os. 1316185029Spjd * 1317185029Spjd * Note, if 'unmounting' if FALSE, we return with the 'z_teardown_lock' 1318185029Spjd * and 'z_teardown_inactive_lock' held. 1319185029Spjd */ 1320185029Spjdstatic int 1321185029Spjdzfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting) 1322185029Spjd{ 1323185029Spjd znode_t *zp; 1324185029Spjd 1325185029Spjd rrw_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); 1326185029Spjd 1327185029Spjd if (!unmounting) { 1328185029Spjd /* 1329185029Spjd * We purge the parent filesystem's vfsp as the parent 1330185029Spjd * filesystem and all of its snapshots have their vnode's 1331185029Spjd * v_vfsp set to the parent's filesystem's vfsp. Note, 1332185029Spjd * 'z_parent' is self referential for non-snapshots. 1333185029Spjd */ 1334185029Spjd (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0); 1335197351Spjd#ifdef FREEBSD_NAMECACHE 1336197351Spjd cache_purgevfs(zfsvfs->z_parent->z_vfs); 1337197351Spjd#endif 1338185029Spjd } 1339185029Spjd 1340185029Spjd /* 1341185029Spjd * Close the zil. NB: Can't close the zil while zfs_inactive 1342185029Spjd * threads are blocked as zil_close can call zfs_inactive. 1343185029Spjd */ 1344185029Spjd if (zfsvfs->z_log) { 1345185029Spjd zil_close(zfsvfs->z_log); 1346185029Spjd zfsvfs->z_log = NULL; 1347185029Spjd } 1348185029Spjd 1349185029Spjd rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_WRITER); 1350185029Spjd 1351185029Spjd /* 1352185029Spjd * If we are not unmounting (ie: online recv) and someone already 1353185029Spjd * unmounted this file system while we were doing the switcheroo, 1354185029Spjd * or a reopen of z_os failed then just bail out now. 1355185029Spjd */ 1356185029Spjd if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) { 1357185029Spjd rw_exit(&zfsvfs->z_teardown_inactive_lock); 1358185029Spjd rrw_exit(&zfsvfs->z_teardown_lock, FTAG); 1359185029Spjd return (EIO); 1360185029Spjd } 1361185029Spjd 1362185029Spjd /* 1363185029Spjd * At this point there are no vops active, and any new vops will 1364185029Spjd * fail with EIO since we have z_teardown_lock for writer (only 1365185029Spjd * relavent for forced unmount). 1366185029Spjd * 1367185029Spjd * Release all holds on dbufs. 1368185029Spjd */ 1369185029Spjd mutex_enter(&zfsvfs->z_znodes_lock); 1370185029Spjd for (zp = list_head(&zfsvfs->z_all_znodes); zp != NULL; 1371185029Spjd zp = list_next(&zfsvfs->z_all_znodes, zp)) 1372185029Spjd if (zp->z_dbuf) { 1373196297Spjd ASSERT(ZTOV(zp)->v_count >= 0); 1374185029Spjd zfs_znode_dmu_fini(zp); 1375185029Spjd } 1376185029Spjd mutex_exit(&zfsvfs->z_znodes_lock); 1377185029Spjd 1378185029Spjd /* 1379185029Spjd * If we are unmounting, set the unmounted flag and let new vops 1380185029Spjd * unblock. zfs_inactive will have the unmounted behavior, and all 1381185029Spjd * other vops will fail with EIO. 1382185029Spjd */ 1383185029Spjd if (unmounting) { 1384185029Spjd zfsvfs->z_unmounted = B_TRUE; 1385185029Spjd rrw_exit(&zfsvfs->z_teardown_lock, FTAG); 1386185029Spjd rw_exit(&zfsvfs->z_teardown_inactive_lock); 1387197133Spjd 1388197133Spjd#ifdef __FreeBSD__ 1389197133Spjd /* 1390197133Spjd * Some znodes might not be fully reclaimed, wait for them. 1391197133Spjd */ 1392197133Spjd mutex_enter(&zfsvfs->z_znodes_lock); 1393197133Spjd while (list_head(&zfsvfs->z_all_znodes) != NULL) { 1394197133Spjd msleep(zfsvfs, &zfsvfs->z_znodes_lock, 0, 1395197133Spjd "zteardown", 0); 1396197133Spjd } 1397197133Spjd mutex_exit(&zfsvfs->z_znodes_lock); 1398197133Spjd#endif 1399185029Spjd } 1400185029Spjd 1401185029Spjd /* 1402185029Spjd * z_os will be NULL if there was an error in attempting to reopen 1403185029Spjd * zfsvfs, so just return as the properties had already been 1404185029Spjd * unregistered and cached data had been evicted before. 1405185029Spjd */ 1406185029Spjd if (zfsvfs->z_os == NULL) 1407185029Spjd return (0); 1408185029Spjd 1409185029Spjd /* 1410185029Spjd * Unregister properties. 1411185029Spjd */ 1412185029Spjd zfs_unregister_callbacks(zfsvfs); 1413185029Spjd 1414185029Spjd /* 1415185029Spjd * Evict cached data 1416185029Spjd */ 1417185029Spjd if (dmu_objset_evict_dbufs(zfsvfs->z_os)) { 1418185029Spjd txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0); 1419185029Spjd (void) dmu_objset_evict_dbufs(zfsvfs->z_os); 1420185029Spjd } 1421185029Spjd 1422185029Spjd return (0); 1423185029Spjd} 1424185029Spjd 1425168404Spjd/*ARGSUSED*/ 1426168404Spjdstatic int 1427191990Sattiliozfs_umount(vfs_t *vfsp, int fflag) 1428168404Spjd{ 1429209962Smm kthread_t *td = curthread; 1430168404Spjd zfsvfs_t *zfsvfs = vfsp->vfs_data; 1431185029Spjd objset_t *os; 1432209962Smm cred_t *cr = td->td_ucred; 1433168404Spjd int ret; 1434168404Spjd 1435185029Spjd ret = secpolicy_fs_unmount(cr, vfsp); 1436185029Spjd if (ret) { 1437212694Smm if (dsl_deleg_access((char *)refstr_value(vfsp->vfs_resource), 1438212694Smm ZFS_DELEG_PERM_MOUNT, cr)) 1439185029Spjd return (ret); 1440185029Spjd } 1441185029Spjd /* 1442185029Spjd * We purge the parent filesystem's vfsp as the parent filesystem 1443185029Spjd * and all of its snapshots have their vnode's v_vfsp set to the 1444185029Spjd * parent's filesystem's vfsp. Note, 'z_parent' is self 1445185029Spjd * referential for non-snapshots. 1446185029Spjd */ 1447185029Spjd (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0); 1448168404Spjd 1449168404Spjd /* 1450168404Spjd * Unmount any snapshots mounted under .zfs before unmounting the 1451168404Spjd * dataset itself. 1452168404Spjd */ 1453169170Spjd if (zfsvfs->z_ctldir != NULL) { 1454168404Spjd if ((ret = zfsctl_umount_snapshots(vfsp, fflag, cr)) != 0) 1455168404Spjd return (ret); 1456209962Smm ret = vflush(vfsp, 0, 0, td); 1457168404Spjd ASSERT(ret == EBUSY); 1458168404Spjd if (!(fflag & MS_FORCE)) { 1459168404Spjd if (zfsvfs->z_ctldir->v_count > 1) 1460168404Spjd return (EBUSY); 1461168404Spjd ASSERT(zfsvfs->z_ctldir->v_count == 1); 1462168404Spjd } 1463168404Spjd zfsctl_destroy(zfsvfs); 1464168404Spjd ASSERT(zfsvfs->z_ctldir == NULL); 1465168404Spjd } 1466168404Spjd 1467197459Spjd if (fflag & MS_FORCE) { 1468197459Spjd /* 1469197459Spjd * Mark file system as unmounted before calling 1470197459Spjd * vflush(FORCECLOSE). This way we ensure no future vnops 1471197459Spjd * will be called and risk operating on DOOMED vnodes. 1472197459Spjd */ 1473197459Spjd rrw_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); 1474197459Spjd zfsvfs->z_unmounted = B_TRUE; 1475197459Spjd rrw_exit(&zfsvfs->z_teardown_lock, FTAG); 1476197459Spjd } 1477197459Spjd 1478168404Spjd /* 1479168404Spjd * Flush all the files. 1480168404Spjd */ 1481209962Smm ret = vflush(vfsp, 1, (fflag & MS_FORCE) ? FORCECLOSE : 0, td); 1482168404Spjd if (ret != 0) { 1483168404Spjd if (!zfsvfs->z_issnap) { 1484168404Spjd zfsctl_create(zfsvfs); 1485168404Spjd ASSERT(zfsvfs->z_ctldir != NULL); 1486168404Spjd } 1487168404Spjd return (ret); 1488168404Spjd } 1489168404Spjd 1490185029Spjd if (!(fflag & MS_FORCE)) { 1491185029Spjd /* 1492185029Spjd * Check the number of active vnodes in the file system. 1493185029Spjd * Our count is maintained in the vfs structure, but the 1494185029Spjd * number is off by 1 to indicate a hold on the vfs 1495185029Spjd * structure itself. 1496185029Spjd * 1497185029Spjd * The '.zfs' directory maintains a reference of its 1498185029Spjd * own, and any active references underneath are 1499185029Spjd * reflected in the vnode count. 1500185029Spjd */ 1501185029Spjd if (zfsvfs->z_ctldir == NULL) { 1502185029Spjd if (vfsp->vfs_count > 1) 1503185029Spjd return (EBUSY); 1504185029Spjd } else { 1505185029Spjd if (vfsp->vfs_count > 2 || 1506185029Spjd zfsvfs->z_ctldir->v_count > 1) 1507185029Spjd return (EBUSY); 1508185029Spjd } 1509185029Spjd } else { 1510168404Spjd MNT_ILOCK(vfsp); 1511168404Spjd vfsp->mnt_kern_flag |= MNTK_UNMOUNTF; 1512168404Spjd MNT_IUNLOCK(vfsp); 1513185029Spjd } 1514168404Spjd 1515185029Spjd VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0); 1516185029Spjd os = zfsvfs->z_os; 1517185029Spjd 1518185029Spjd /* 1519185029Spjd * z_os will be NULL if there was an error in 1520185029Spjd * attempting to reopen zfsvfs. 1521185029Spjd */ 1522185029Spjd if (os != NULL) { 1523168404Spjd /* 1524185029Spjd * Unset the objset user_ptr. 1525168404Spjd */ 1526185029Spjd mutex_enter(&os->os->os_user_ptr_lock); 1527185029Spjd dmu_objset_set_user(os, NULL); 1528185029Spjd mutex_exit(&os->os->os_user_ptr_lock); 1529185029Spjd 1530185029Spjd /* 1531185029Spjd * Finally release the objset 1532185029Spjd */ 1533185029Spjd dmu_objset_close(os); 1534168404Spjd } 1535168404Spjd 1536185029Spjd /* 1537185029Spjd * We can now safely destroy the '.zfs' directory node. 1538185029Spjd */ 1539185029Spjd if (zfsvfs->z_ctldir != NULL) 1540185029Spjd zfsctl_destroy(zfsvfs); 1541185029Spjd if (zfsvfs->z_issnap) { 1542185029Spjd vnode_t *svp = vfsp->mnt_vnodecovered; 1543185029Spjd 1544197515Spjd if (svp->v_count >= 2) 1545192211Skmacy VN_RELE(svp); 1546185029Spjd } 1547168404Spjd zfs_freevfs(vfsp); 1548168404Spjd 1549168404Spjd return (0); 1550168404Spjd} 1551168404Spjd 1552168404Spjdstatic int 1553168404Spjdzfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp) 1554168404Spjd{ 1555168404Spjd zfsvfs_t *zfsvfs = vfsp->vfs_data; 1556168404Spjd znode_t *zp; 1557168404Spjd int err; 1558168404Spjd 1559197167Spjd /* 1560211855Spjd * zfs_zget() can't operate on virtual entires like .zfs/ or 1561211855Spjd * .zfs/snapshot/ directories, that's why we return EOPNOTSUPP. 1562211855Spjd * This will make NFS to switch to LOOKUP instead of using VGET. 1563197167Spjd */ 1564197167Spjd if (ino == ZFSCTL_INO_ROOT || ino == ZFSCTL_INO_SNAPDIR) 1565197167Spjd return (EOPNOTSUPP); 1566197167Spjd 1567168404Spjd ZFS_ENTER(zfsvfs); 1568168404Spjd err = zfs_zget(zfsvfs, ino, &zp); 1569168404Spjd if (err == 0 && zp->z_unlinked) { 1570168404Spjd VN_RELE(ZTOV(zp)); 1571168404Spjd err = EINVAL; 1572168404Spjd } 1573206667Spjd ZFS_EXIT(zfsvfs); 1574168404Spjd if (err != 0) 1575168404Spjd *vpp = NULL; 1576168404Spjd else { 1577168404Spjd *vpp = ZTOV(zp); 1578175202Sattilio vn_lock(*vpp, flags); 1579168404Spjd } 1580171063Sdfr return (err); 1581168404Spjd} 1582168404Spjd 1583168404Spjdstatic int 1584196982Spjdzfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, int *extflagsp, 1585196982Spjd struct ucred **credanonp, int *numsecflavors, int **secflavors) 1586196982Spjd{ 1587196982Spjd zfsvfs_t *zfsvfs = vfsp->vfs_data; 1588196982Spjd 1589196982Spjd /* 1590196982Spjd * If this is regular file system vfsp is the same as 1591196982Spjd * zfsvfs->z_parent->z_vfs, but if it is snapshot, 1592196982Spjd * zfsvfs->z_parent->z_vfs represents parent file system 1593196982Spjd * which we have to use here, because only this file system 1594196982Spjd * has mnt_export configured. 1595196982Spjd */ 1596196982Spjd return (vfs_stdcheckexp(zfsvfs->z_parent->z_vfs, nam, extflagsp, 1597196982Spjd credanonp, numsecflavors, secflavors)); 1598196982Spjd} 1599196982Spjd 1600197151SpjdCTASSERT(SHORT_FID_LEN <= sizeof(struct fid)); 1601197151SpjdCTASSERT(LONG_FID_LEN <= sizeof(struct fid)); 1602196982Spjd 1603196982Spjdstatic int 1604168404Spjdzfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp) 1605168404Spjd{ 1606168404Spjd zfsvfs_t *zfsvfs = vfsp->vfs_data; 1607168404Spjd znode_t *zp; 1608168404Spjd uint64_t object = 0; 1609168404Spjd uint64_t fid_gen = 0; 1610168404Spjd uint64_t gen_mask; 1611168404Spjd uint64_t zp_gen; 1612168404Spjd int i, err; 1613168404Spjd 1614168404Spjd *vpp = NULL; 1615168404Spjd 1616168404Spjd ZFS_ENTER(zfsvfs); 1617168404Spjd 1618196979Spjd /* 1619197177Spjd * On FreeBSD we can get snapshot's mount point or its parent file 1620197177Spjd * system mount point depending if snapshot is already mounted or not. 1621196979Spjd */ 1622197177Spjd if (zfsvfs->z_parent == zfsvfs && fidp->fid_len == LONG_FID_LEN) { 1623168404Spjd zfid_long_t *zlfid = (zfid_long_t *)fidp; 1624168404Spjd uint64_t objsetid = 0; 1625168404Spjd uint64_t setgen = 0; 1626168404Spjd 1627168404Spjd for (i = 0; i < sizeof (zlfid->zf_setid); i++) 1628168404Spjd objsetid |= ((uint64_t)zlfid->zf_setid[i]) << (8 * i); 1629168404Spjd 1630168404Spjd for (i = 0; i < sizeof (zlfid->zf_setgen); i++) 1631168404Spjd setgen |= ((uint64_t)zlfid->zf_setgen[i]) << (8 * i); 1632168404Spjd 1633168404Spjd ZFS_EXIT(zfsvfs); 1634168404Spjd 1635168404Spjd err = zfsctl_lookup_objset(vfsp, objsetid, &zfsvfs); 1636168404Spjd if (err) 1637168404Spjd return (EINVAL); 1638168404Spjd ZFS_ENTER(zfsvfs); 1639168404Spjd } 1640168404Spjd 1641168404Spjd if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) { 1642168404Spjd zfid_short_t *zfid = (zfid_short_t *)fidp; 1643168404Spjd 1644168404Spjd for (i = 0; i < sizeof (zfid->zf_object); i++) 1645168404Spjd object |= ((uint64_t)zfid->zf_object[i]) << (8 * i); 1646168404Spjd 1647168404Spjd for (i = 0; i < sizeof (zfid->zf_gen); i++) 1648168404Spjd fid_gen |= ((uint64_t)zfid->zf_gen[i]) << (8 * i); 1649168404Spjd } else { 1650168404Spjd ZFS_EXIT(zfsvfs); 1651168404Spjd return (EINVAL); 1652168404Spjd } 1653168404Spjd 1654168404Spjd /* A zero fid_gen means we are in the .zfs control directories */ 1655168404Spjd if (fid_gen == 0 && 1656168404Spjd (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) { 1657168404Spjd *vpp = zfsvfs->z_ctldir; 1658168404Spjd ASSERT(*vpp != NULL); 1659168404Spjd if (object == ZFSCTL_INO_SNAPDIR) { 1660168404Spjd VERIFY(zfsctl_root_lookup(*vpp, "snapshot", vpp, NULL, 1661185029Spjd 0, NULL, NULL, NULL, NULL, NULL) == 0); 1662168404Spjd } else { 1663168404Spjd VN_HOLD(*vpp); 1664168404Spjd } 1665206667Spjd ZFS_EXIT(zfsvfs); 1666196978Spjd vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 1667168404Spjd return (0); 1668168404Spjd } 1669168404Spjd 1670168404Spjd gen_mask = -1ULL >> (64 - 8 * i); 1671168404Spjd 1672168404Spjd dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask); 1673168404Spjd if (err = zfs_zget(zfsvfs, object, &zp)) { 1674168404Spjd ZFS_EXIT(zfsvfs); 1675168404Spjd return (err); 1676168404Spjd } 1677168404Spjd zp_gen = zp->z_phys->zp_gen & gen_mask; 1678168404Spjd if (zp_gen == 0) 1679168404Spjd zp_gen = 1; 1680168404Spjd if (zp->z_unlinked || zp_gen != fid_gen) { 1681168404Spjd dprintf("znode gen (%u) != fid gen (%u)\n", zp_gen, fid_gen); 1682168404Spjd VN_RELE(ZTOV(zp)); 1683168404Spjd ZFS_EXIT(zfsvfs); 1684168404Spjd return (EINVAL); 1685168404Spjd } 1686168404Spjd 1687206667Spjd ZFS_EXIT(zfsvfs); 1688206667Spjd 1689168404Spjd *vpp = ZTOV(zp); 1690175202Sattilio vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 1691185029Spjd vnode_create_vobject(*vpp, zp->z_phys->zp_size, curthread); 1692168404Spjd return (0); 1693168404Spjd} 1694168404Spjd 1695185029Spjd/* 1696185029Spjd * Block out VOPs and close zfsvfs_t::z_os 1697185029Spjd * 1698185029Spjd * Note, if successful, then we return with the 'z_teardown_lock' and 1699185029Spjd * 'z_teardown_inactive_lock' write held. 1700185029Spjd */ 1701185029Spjdint 1702209962Smmzfs_suspend_fs(zfsvfs_t *zfsvfs, char *name, int *modep) 1703168404Spjd{ 1704185029Spjd int error; 1705168404Spjd 1706185029Spjd if ((error = zfsvfs_teardown(zfsvfs, B_FALSE)) != 0) 1707185029Spjd return (error); 1708168404Spjd 1709209962Smm *modep = zfsvfs->z_os->os_mode; 1710209962Smm if (name) 1711209962Smm dmu_objset_name(zfsvfs->z_os, name); 1712185029Spjd dmu_objset_close(zfsvfs->z_os); 1713168404Spjd 1714185029Spjd return (0); 1715185029Spjd} 1716168404Spjd 1717185029Spjd/* 1718185029Spjd * Reopen zfsvfs_t::z_os and release VOPs. 1719185029Spjd */ 1720185029Spjdint 1721185029Spjdzfs_resume_fs(zfsvfs_t *zfsvfs, const char *osname, int mode) 1722185029Spjd{ 1723185029Spjd int err; 1724168404Spjd 1725185029Spjd ASSERT(RRW_WRITE_HELD(&zfsvfs->z_teardown_lock)); 1726185029Spjd ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock)); 1727185029Spjd 1728185029Spjd err = dmu_objset_open(osname, DMU_OST_ZFS, mode, &zfsvfs->z_os); 1729185029Spjd if (err) { 1730185029Spjd zfsvfs->z_os = NULL; 1731185029Spjd } else { 1732185029Spjd znode_t *zp; 1733185029Spjd 1734185029Spjd VERIFY(zfsvfs_setup(zfsvfs, B_FALSE) == 0); 1735185029Spjd 1736185029Spjd /* 1737185029Spjd * Attempt to re-establish all the active znodes with 1738185029Spjd * their dbufs. If a zfs_rezget() fails, then we'll let 1739185029Spjd * any potential callers discover that via ZFS_ENTER_VERIFY_VP 1740185029Spjd * when they try to use their znode. 1741185029Spjd */ 1742185029Spjd mutex_enter(&zfsvfs->z_znodes_lock); 1743185029Spjd for (zp = list_head(&zfsvfs->z_all_znodes); zp; 1744185029Spjd zp = list_next(&zfsvfs->z_all_znodes, zp)) { 1745185029Spjd (void) zfs_rezget(zp); 1746185029Spjd } 1747185029Spjd mutex_exit(&zfsvfs->z_znodes_lock); 1748185029Spjd 1749168404Spjd } 1750168404Spjd 1751185029Spjd /* release the VOPs */ 1752185029Spjd rw_exit(&zfsvfs->z_teardown_inactive_lock); 1753185029Spjd rrw_exit(&zfsvfs->z_teardown_lock, FTAG); 1754185029Spjd 1755185029Spjd if (err) { 1756185029Spjd /* 1757185029Spjd * Since we couldn't reopen zfsvfs::z_os, force 1758185029Spjd * unmount this file system. 1759185029Spjd */ 1760185029Spjd if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0) 1761185029Spjd (void) dounmount(zfsvfs->z_vfs, MS_FORCE, curthread); 1762168404Spjd } 1763185029Spjd return (err); 1764168404Spjd} 1765168404Spjd 1766168404Spjdstatic void 1767168404Spjdzfs_freevfs(vfs_t *vfsp) 1768168404Spjd{ 1769168404Spjd zfsvfs_t *zfsvfs = vfsp->vfs_data; 1770168404Spjd 1771215260Smm#ifdef sun 1772209962Smm /* 1773209962Smm * If this is a snapshot, we have an extra VFS_HOLD on our parent 1774209962Smm * from zfs_mount(). Release it here. 1775209962Smm */ 1776209962Smm if (zfsvfs->z_issnap) 1777209962Smm VFS_RELE(zfsvfs->z_parent->z_vfs); 1778215260Smm#endif /* sun */ 1779168404Spjd 1780209962Smm zfsvfs_free(zfsvfs); 1781185029Spjd 1782168404Spjd atomic_add_32(&zfs_active_fs_count, -1); 1783168404Spjd} 1784168404Spjd 1785172135Spjd#ifdef __i386__ 1786172135Spjdstatic int desiredvnodes_backup; 1787172135Spjd#endif 1788172135Spjd 1789172135Spjdstatic void 1790172135Spjdzfs_vnodes_adjust(void) 1791172135Spjd{ 1792172135Spjd#ifdef __i386__ 1793185029Spjd int newdesiredvnodes; 1794172135Spjd 1795172135Spjd desiredvnodes_backup = desiredvnodes; 1796172135Spjd 1797172135Spjd /* 1798172135Spjd * We calculate newdesiredvnodes the same way it is done in 1799172135Spjd * vntblinit(). If it is equal to desiredvnodes, it means that 1800172135Spjd * it wasn't tuned by the administrator and we can tune it down. 1801172135Spjd */ 1802185029Spjd newdesiredvnodes = min(maxproc + cnt.v_page_count / 4, 2 * 1803185029Spjd vm_kmem_size / (5 * (sizeof(struct vm_object) + 1804185029Spjd sizeof(struct vnode)))); 1805185029Spjd if (newdesiredvnodes == desiredvnodes) 1806185029Spjd desiredvnodes = (3 * newdesiredvnodes) / 4; 1807172135Spjd#endif 1808172135Spjd} 1809172135Spjd 1810172135Spjdstatic void 1811172135Spjdzfs_vnodes_adjust_back(void) 1812172135Spjd{ 1813172135Spjd 1814172135Spjd#ifdef __i386__ 1815172135Spjd desiredvnodes = desiredvnodes_backup; 1816172135Spjd#endif 1817172135Spjd} 1818172135Spjd 1819168404Spjdvoid 1820168404Spjdzfs_init(void) 1821168404Spjd{ 1822168404Spjd 1823202129Sdelphij printf("ZFS filesystem version " ZPL_VERSION_STRING "\n"); 1824168404Spjd 1825168404Spjd /* 1826185029Spjd * Initialize znode cache, vnode ops, etc... 1827168404Spjd */ 1828185029Spjd zfs_znode_init(); 1829168404Spjd 1830168404Spjd /* 1831185029Spjd * Initialize .zfs directory structures 1832168404Spjd */ 1833185029Spjd zfsctl_init(); 1834172135Spjd 1835172135Spjd /* 1836185029Spjd * Reduce number of vnode. Originally number of vnodes is calculated 1837172135Spjd * with UFS inode in mind. We reduce it here, because it's too big for 1838172135Spjd * ZFS/i386. 1839172135Spjd */ 1840172135Spjd zfs_vnodes_adjust(); 1841209962Smm 1842209962Smm dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb); 1843168404Spjd} 1844168404Spjd 1845168404Spjdvoid 1846168404Spjdzfs_fini(void) 1847168404Spjd{ 1848168404Spjd zfsctl_fini(); 1849168404Spjd zfs_znode_fini(); 1850172135Spjd zfs_vnodes_adjust_back(); 1851168404Spjd} 1852168404Spjd 1853168404Spjdint 1854168404Spjdzfs_busy(void) 1855168404Spjd{ 1856168404Spjd return (zfs_active_fs_count != 0); 1857168404Spjd} 1858185029Spjd 1859185029Spjdint 1860209962Smmzfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers) 1861185029Spjd{ 1862185029Spjd int error; 1863209962Smm objset_t *os = zfsvfs->z_os; 1864185029Spjd dmu_tx_t *tx; 1865185029Spjd 1866185029Spjd if (newvers < ZPL_VERSION_INITIAL || newvers > ZPL_VERSION) 1867185029Spjd return (EINVAL); 1868185029Spjd 1869209962Smm if (newvers < zfsvfs->z_version) 1870209962Smm return (EINVAL); 1871185029Spjd 1872185029Spjd tx = dmu_tx_create(os); 1873209962Smm dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_FALSE, ZPL_VERSION_STR); 1874185029Spjd error = dmu_tx_assign(tx, TXG_WAIT); 1875185029Spjd if (error) { 1876185029Spjd dmu_tx_abort(tx); 1877209962Smm return (error); 1878185029Spjd } 1879209962Smm error = zap_update(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 1880209962Smm 8, 1, &newvers, tx); 1881185029Spjd 1882209962Smm if (error) { 1883209962Smm dmu_tx_commit(tx); 1884209962Smm return (error); 1885209962Smm } 1886209962Smm 1887185029Spjd spa_history_internal_log(LOG_DS_UPGRADE, 1888185029Spjd dmu_objset_spa(os), tx, CRED(), 1889209962Smm "oldver=%llu newver=%llu dataset = %llu", 1890209962Smm zfsvfs->z_version, newvers, dmu_objset_id(os)); 1891209962Smm 1892185029Spjd dmu_tx_commit(tx); 1893185029Spjd 1894209962Smm zfsvfs->z_version = newvers; 1895209962Smm 1896209962Smm if (zfsvfs->z_version >= ZPL_VERSION_FUID) 1897209962Smm zfs_set_fuid_feature(zfsvfs); 1898209962Smm 1899209962Smm return (0); 1900185029Spjd} 1901185029Spjd/* 1902185029Spjd * Read a property stored within the master node. 1903185029Spjd */ 1904185029Spjdint 1905185029Spjdzfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value) 1906185029Spjd{ 1907185029Spjd const char *pname; 1908185029Spjd int error = ENOENT; 1909185029Spjd 1910185029Spjd /* 1911185029Spjd * Look up the file system's value for the property. For the 1912185029Spjd * version property, we look up a slightly different string. 1913185029Spjd */ 1914185029Spjd if (prop == ZFS_PROP_VERSION) 1915185029Spjd pname = ZPL_VERSION_STR; 1916185029Spjd else 1917185029Spjd pname = zfs_prop_to_name(prop); 1918185029Spjd 1919185029Spjd if (os != NULL) 1920185029Spjd error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value); 1921185029Spjd 1922185029Spjd if (error == ENOENT) { 1923185029Spjd /* No value set, use the default value */ 1924185029Spjd switch (prop) { 1925185029Spjd case ZFS_PROP_VERSION: 1926185029Spjd *value = ZPL_VERSION; 1927185029Spjd break; 1928185029Spjd case ZFS_PROP_NORMALIZE: 1929185029Spjd case ZFS_PROP_UTF8ONLY: 1930185029Spjd *value = 0; 1931185029Spjd break; 1932185029Spjd case ZFS_PROP_CASE: 1933185029Spjd *value = ZFS_CASE_SENSITIVE; 1934185029Spjd break; 1935185029Spjd default: 1936185029Spjd return (error); 1937185029Spjd } 1938185029Spjd error = 0; 1939185029Spjd } 1940185029Spjd return (error); 1941185029Spjd} 1942