1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5033f9833Sek * Common Development and Distribution License (the "License"). 6033f9833Sek * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 22dc7cd546SMark Shellenbaum * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 234445fffbSMatthew Ahrens * Copyright (c) 2012 by Delphix. All rights reserved. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 2655da60b9SMark J Musante /* Portions Copyright 2010 Robert Milkowski */ 2755da60b9SMark J Musante 28fa9e4066Sahrens #include <sys/types.h> 29fa9e4066Sahrens #include <sys/param.h> 30fa9e4066Sahrens #include <sys/systm.h> 31fa9e4066Sahrens #include <sys/sysmacros.h> 32fa9e4066Sahrens #include <sys/kmem.h> 33fa9e4066Sahrens #include <sys/pathname.h> 34fa9e4066Sahrens #include <sys/vnode.h> 35fa9e4066Sahrens #include <sys/vfs.h> 36aa59c4cbSrsb #include <sys/vfs_opreg.h> 37fa9e4066Sahrens #include <sys/mntent.h> 38fa9e4066Sahrens #include <sys/mount.h> 39fa9e4066Sahrens #include <sys/cmn_err.h> 40fa9e4066Sahrens #include "fs/fs_subr.h" 41fa9e4066Sahrens #include <sys/zfs_znode.h> 42893a6d32Sahrens #include <sys/zfs_dir.h> 43fa9e4066Sahrens #include <sys/zil.h> 44fa9e4066Sahrens #include <sys/fs/zfs.h> 45fa9e4066Sahrens #include <sys/dmu.h> 46fa9e4066Sahrens #include <sys/dsl_prop.h> 47b1b8ab34Slling #include <sys/dsl_dataset.h> 48ecd6cf80Smarks #include <sys/dsl_deleg.h> 49fa9e4066Sahrens #include <sys/spa.h> 50fa9e4066Sahrens #include <sys/zap.h> 510a586ceaSMark Shellenbaum #include <sys/sa.h> 52e828a46dSMatthew Ahrens #include <sys/sa_impl.h> 53fa9e4066Sahrens #include <sys/varargs.h> 54fa9e4066Sahrens #include <sys/policy.h> 55fa9e4066Sahrens #include <sys/atomic.h> 56fa9e4066Sahrens #include <sys/mkdev.h> 57fa9e4066Sahrens #include <sys/modctl.h> 58ecd6cf80Smarks #include <sys/refstr.h> 59fa9e4066Sahrens #include <sys/zfs_ioctl.h> 60fa9e4066Sahrens #include <sys/zfs_ctldir.h> 61da6c28aaSamw #include <sys/zfs_fuid.h> 62ea8dc4b6Seschrock #include <sys/bootconf.h> 63a0965f35Sbonwick #include <sys/sunddi.h> 64033f9833Sek #include <sys/dnlc.h> 65f18faf3fSek #include <sys/dmu_objset.h> 66e7cbe64fSgw #include <sys/spa_boot.h> 670a586ceaSMark Shellenbaum #include "zfs_comutil.h" 68fa9e4066Sahrens 69fa9e4066Sahrens int zfsfstype; 70fa9e4066Sahrens vfsops_t *zfs_vfsops = NULL; 71a0965f35Sbonwick static major_t zfs_major; 72fa9e4066Sahrens static minor_t zfs_minor; 73fa9e4066Sahrens static kmutex_t zfs_dev_mtx; 74fa9e4066Sahrens 7554d692b7SGeorge Wilson extern int sys_shutdown; 7654d692b7SGeorge Wilson 77fa9e4066Sahrens static int zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr); 78fa9e4066Sahrens static int zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr); 79ea8dc4b6Seschrock static int zfs_mountroot(vfs_t *vfsp, enum whymountroot); 80fa9e4066Sahrens static int zfs_root(vfs_t *vfsp, vnode_t **vpp); 81fa9e4066Sahrens static int zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp); 82fa9e4066Sahrens static int zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp); 83fa9e4066Sahrens static void zfs_freevfs(vfs_t *vfsp); 84fa9e4066Sahrens 85fa9e4066Sahrens static const fs_operation_def_t zfs_vfsops_template[] = { 86aa59c4cbSrsb VFSNAME_MOUNT, { .vfs_mount = zfs_mount }, 87aa59c4cbSrsb VFSNAME_MOUNTROOT, { .vfs_mountroot = zfs_mountroot }, 88aa59c4cbSrsb VFSNAME_UNMOUNT, { .vfs_unmount = zfs_umount }, 89aa59c4cbSrsb VFSNAME_ROOT, { .vfs_root = zfs_root }, 90aa59c4cbSrsb VFSNAME_STATVFS, { .vfs_statvfs = zfs_statvfs }, 91aa59c4cbSrsb VFSNAME_SYNC, { .vfs_sync = zfs_sync }, 92aa59c4cbSrsb VFSNAME_VGET, { .vfs_vget = zfs_vget }, 93aa59c4cbSrsb VFSNAME_FREEVFS, { .vfs_freevfs = zfs_freevfs }, 94aa59c4cbSrsb NULL, NULL 95fa9e4066Sahrens }; 96fa9e4066Sahrens 97fa9e4066Sahrens static const fs_operation_def_t zfs_vfsops_eio_template[] = { 98aa59c4cbSrsb VFSNAME_FREEVFS, { .vfs_freevfs = zfs_freevfs }, 99aa59c4cbSrsb NULL, NULL 100fa9e4066Sahrens }; 101fa9e4066Sahrens 102fa9e4066Sahrens /* 103fa9e4066Sahrens * We need to keep a count of active fs's. 104fa9e4066Sahrens * This is necessary to prevent our module 105fa9e4066Sahrens * from being unloaded after a umount -f 106fa9e4066Sahrens */ 107fa9e4066Sahrens static uint32_t zfs_active_fs_count = 0; 108fa9e4066Sahrens 109fa9e4066Sahrens static char *noatime_cancel[] = { MNTOPT_ATIME, NULL }; 110fa9e4066Sahrens static char *atime_cancel[] = { MNTOPT_NOATIME, NULL }; 1117b55fa8eSck static char *noxattr_cancel[] = { MNTOPT_XATTR, NULL }; 1127b55fa8eSck static char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL }; 113fa9e4066Sahrens 1147b55fa8eSck /* 115b510d378Slling * MO_DEFAULT is not used since the default value is determined 116b510d378Slling * by the equivalent property. 1177b55fa8eSck */ 118fa9e4066Sahrens static mntopt_t mntopts[] = { 1197b55fa8eSck { MNTOPT_NOXATTR, noxattr_cancel, NULL, 0, NULL }, 1207b55fa8eSck { MNTOPT_XATTR, xattr_cancel, NULL, 0, NULL }, 121b510d378Slling { MNTOPT_NOATIME, noatime_cancel, NULL, 0, NULL }, 122fa9e4066Sahrens { MNTOPT_ATIME, atime_cancel, NULL, 0, NULL } 123fa9e4066Sahrens }; 124fa9e4066Sahrens 125fa9e4066Sahrens static mntopts_t zfs_mntopts = { 126fa9e4066Sahrens sizeof (mntopts) / sizeof (mntopt_t), 127fa9e4066Sahrens mntopts 128fa9e4066Sahrens }; 129fa9e4066Sahrens 130fa9e4066Sahrens /*ARGSUSED*/ 131fa9e4066Sahrens int 132fa9e4066Sahrens zfs_sync(vfs_t *vfsp, short flag, cred_t *cr) 133fa9e4066Sahrens { 134fa9e4066Sahrens /* 135fa9e4066Sahrens * Data integrity is job one. We don't want a compromised kernel 136fa9e4066Sahrens * writing to the storage pool, so we never sync during panic. 137fa9e4066Sahrens */ 138fa9e4066Sahrens if (panicstr) 139fa9e4066Sahrens return (0); 140fa9e4066Sahrens 141fa9e4066Sahrens /* 142fa9e4066Sahrens * SYNC_ATTR is used by fsflush() to force old filesystems like UFS 143fa9e4066Sahrens * to sync metadata, which they would otherwise cache indefinitely. 144fa9e4066Sahrens * Semantically, the only requirement is that the sync be initiated. 145fa9e4066Sahrens * The DMU syncs out txgs frequently, so there's nothing to do. 146fa9e4066Sahrens */ 147fa9e4066Sahrens if (flag & SYNC_ATTR) 148fa9e4066Sahrens return (0); 149fa9e4066Sahrens 150fa9e4066Sahrens if (vfsp != NULL) { 151fa9e4066Sahrens /* 152fa9e4066Sahrens * Sync a specific filesystem. 153fa9e4066Sahrens */ 154fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 15554d692b7SGeorge Wilson dsl_pool_t *dp; 156fa9e4066Sahrens 157fa9e4066Sahrens ZFS_ENTER(zfsvfs); 15854d692b7SGeorge Wilson dp = dmu_objset_pool(zfsvfs->z_os); 15954d692b7SGeorge Wilson 16054d692b7SGeorge Wilson /* 16154d692b7SGeorge Wilson * If the system is shutting down, then skip any 16254d692b7SGeorge Wilson * filesystems which may exist on a suspended pool. 16354d692b7SGeorge Wilson */ 16454d692b7SGeorge Wilson if (sys_shutdown && spa_suspended(dp->dp_spa)) { 16554d692b7SGeorge Wilson ZFS_EXIT(zfsvfs); 16654d692b7SGeorge Wilson return (0); 16754d692b7SGeorge Wilson } 16854d692b7SGeorge Wilson 169fa9e4066Sahrens if (zfsvfs->z_log != NULL) 1705002558fSNeil Perrin zil_commit(zfsvfs->z_log, 0); 17155da60b9SMark J Musante 172fa9e4066Sahrens ZFS_EXIT(zfsvfs); 173fa9e4066Sahrens } else { 174fa9e4066Sahrens /* 175fa9e4066Sahrens * Sync all ZFS filesystems. This is what happens when you 176fa9e4066Sahrens * run sync(1M). Unlike other filesystems, ZFS honors the 177fa9e4066Sahrens * request by waiting for all pools to commit all dirty data. 178fa9e4066Sahrens */ 179fa9e4066Sahrens spa_sync_allpools(); 180fa9e4066Sahrens } 181fa9e4066Sahrens 182fa9e4066Sahrens return (0); 183fa9e4066Sahrens } 184fa9e4066Sahrens 185ea8dc4b6Seschrock static int 186ea8dc4b6Seschrock zfs_create_unique_device(dev_t *dev) 187ea8dc4b6Seschrock { 188ea8dc4b6Seschrock major_t new_major; 189ea8dc4b6Seschrock 190ea8dc4b6Seschrock do { 191ea8dc4b6Seschrock ASSERT3U(zfs_minor, <=, MAXMIN32); 192ea8dc4b6Seschrock minor_t start = zfs_minor; 193ea8dc4b6Seschrock do { 194ea8dc4b6Seschrock mutex_enter(&zfs_dev_mtx); 195ea8dc4b6Seschrock if (zfs_minor >= MAXMIN32) { 196ea8dc4b6Seschrock /* 197ea8dc4b6Seschrock * If we're still using the real major 198ea8dc4b6Seschrock * keep out of /dev/zfs and /dev/zvol minor 199ea8dc4b6Seschrock * number space. If we're using a getudev()'ed 200ea8dc4b6Seschrock * major number, we can use all of its minors. 201ea8dc4b6Seschrock */ 202ea8dc4b6Seschrock if (zfs_major == ddi_name_to_major(ZFS_DRIVER)) 203ea8dc4b6Seschrock zfs_minor = ZFS_MIN_MINOR; 204ea8dc4b6Seschrock else 205ea8dc4b6Seschrock zfs_minor = 0; 206ea8dc4b6Seschrock } else { 207ea8dc4b6Seschrock zfs_minor++; 208ea8dc4b6Seschrock } 209ea8dc4b6Seschrock *dev = makedevice(zfs_major, zfs_minor); 210ea8dc4b6Seschrock mutex_exit(&zfs_dev_mtx); 211ea8dc4b6Seschrock } while (vfs_devismounted(*dev) && zfs_minor != start); 212ea8dc4b6Seschrock if (zfs_minor == start) { 213ea8dc4b6Seschrock /* 214ea8dc4b6Seschrock * We are using all ~262,000 minor numbers for the 215ea8dc4b6Seschrock * current major number. Create a new major number. 216ea8dc4b6Seschrock */ 217ea8dc4b6Seschrock if ((new_major = getudev()) == (major_t)-1) { 218ea8dc4b6Seschrock cmn_err(CE_WARN, 219ea8dc4b6Seschrock "zfs_mount: Can't get unique major " 220ea8dc4b6Seschrock "device number."); 221ea8dc4b6Seschrock return (-1); 222ea8dc4b6Seschrock } 223ea8dc4b6Seschrock mutex_enter(&zfs_dev_mtx); 224ea8dc4b6Seschrock zfs_major = new_major; 225ea8dc4b6Seschrock zfs_minor = 0; 226ea8dc4b6Seschrock 227ea8dc4b6Seschrock mutex_exit(&zfs_dev_mtx); 228ea8dc4b6Seschrock } else { 229ea8dc4b6Seschrock break; 230ea8dc4b6Seschrock } 231ea8dc4b6Seschrock /* CONSTANTCONDITION */ 232ea8dc4b6Seschrock } while (1); 233ea8dc4b6Seschrock 234ea8dc4b6Seschrock return (0); 235ea8dc4b6Seschrock } 236ea8dc4b6Seschrock 237fa9e4066Sahrens static void 238fa9e4066Sahrens atime_changed_cb(void *arg, uint64_t newval) 239fa9e4066Sahrens { 240fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 241fa9e4066Sahrens 242fa9e4066Sahrens if (newval == TRUE) { 243fa9e4066Sahrens zfsvfs->z_atime = TRUE; 244fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME); 245fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_ATIME, NULL, 0); 246fa9e4066Sahrens } else { 247fa9e4066Sahrens zfsvfs->z_atime = FALSE; 248fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_ATIME); 249fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME, NULL, 0); 250fa9e4066Sahrens } 251fa9e4066Sahrens } 252fa9e4066Sahrens 2537b55fa8eSck static void 2547b55fa8eSck xattr_changed_cb(void *arg, uint64_t newval) 2557b55fa8eSck { 2567b55fa8eSck zfsvfs_t *zfsvfs = arg; 2577b55fa8eSck 2587b55fa8eSck if (newval == TRUE) { 2597b55fa8eSck /* XXX locking on vfs_flag? */ 2607b55fa8eSck zfsvfs->z_vfs->vfs_flag |= VFS_XATTR; 2617b55fa8eSck vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR); 2627b55fa8eSck vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_XATTR, NULL, 0); 2637b55fa8eSck } else { 2647b55fa8eSck /* XXX locking on vfs_flag? */ 2657b55fa8eSck zfsvfs->z_vfs->vfs_flag &= ~VFS_XATTR; 2667b55fa8eSck vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_XATTR); 2677b55fa8eSck vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR, NULL, 0); 2687b55fa8eSck } 2697b55fa8eSck } 2707b55fa8eSck 271fa9e4066Sahrens static void 272fa9e4066Sahrens blksz_changed_cb(void *arg, uint64_t newval) 273fa9e4066Sahrens { 274fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 275fa9e4066Sahrens 276fa9e4066Sahrens if (newval < SPA_MINBLOCKSIZE || 277fa9e4066Sahrens newval > SPA_MAXBLOCKSIZE || !ISP2(newval)) 278fa9e4066Sahrens newval = SPA_MAXBLOCKSIZE; 279fa9e4066Sahrens 280fa9e4066Sahrens zfsvfs->z_max_blksz = newval; 281fa9e4066Sahrens zfsvfs->z_vfs->vfs_bsize = newval; 282fa9e4066Sahrens } 283fa9e4066Sahrens 284fa9e4066Sahrens static void 285fa9e4066Sahrens readonly_changed_cb(void *arg, uint64_t newval) 286fa9e4066Sahrens { 287fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 288fa9e4066Sahrens 289fa9e4066Sahrens if (newval) { 290fa9e4066Sahrens /* XXX locking on vfs_flag? */ 291fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY; 292fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RW); 293fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RO, NULL, 0); 294fa9e4066Sahrens } else { 295fa9e4066Sahrens /* XXX locking on vfs_flag? */ 296fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 297fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RO); 298fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RW, NULL, 0); 299fa9e4066Sahrens } 300fa9e4066Sahrens } 301fa9e4066Sahrens 302fa9e4066Sahrens static void 303fa9e4066Sahrens devices_changed_cb(void *arg, uint64_t newval) 304fa9e4066Sahrens { 305fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 306fa9e4066Sahrens 307fa9e4066Sahrens if (newval == FALSE) { 308fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NODEVICES; 309fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES); 310fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES, NULL, 0); 311fa9e4066Sahrens } else { 312fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NODEVICES; 313fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES); 314fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES, NULL, 0); 315fa9e4066Sahrens } 316fa9e4066Sahrens } 317fa9e4066Sahrens 318fa9e4066Sahrens static void 319fa9e4066Sahrens setuid_changed_cb(void *arg, uint64_t newval) 320fa9e4066Sahrens { 321fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 322fa9e4066Sahrens 323fa9e4066Sahrens if (newval == FALSE) { 324fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NOSETUID; 325fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_SETUID); 326fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID, NULL, 0); 327fa9e4066Sahrens } else { 328fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NOSETUID; 329fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID); 330fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_SETUID, NULL, 0); 331fa9e4066Sahrens } 332fa9e4066Sahrens } 333fa9e4066Sahrens 334fa9e4066Sahrens static void 335fa9e4066Sahrens exec_changed_cb(void *arg, uint64_t newval) 336fa9e4066Sahrens { 337fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 338fa9e4066Sahrens 339fa9e4066Sahrens if (newval == FALSE) { 340fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NOEXEC; 341fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_EXEC); 342fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC, NULL, 0); 343fa9e4066Sahrens } else { 344fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NOEXEC; 345fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC); 346fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_EXEC, NULL, 0); 347fa9e4066Sahrens } 348fa9e4066Sahrens } 349fa9e4066Sahrens 350da6c28aaSamw /* 351da6c28aaSamw * The nbmand mount option can be changed at mount time. 352da6c28aaSamw * We can't allow it to be toggled on live file systems or incorrect 353da6c28aaSamw * behavior may be seen from cifs clients 354da6c28aaSamw * 355da6c28aaSamw * This property isn't registered via dsl_prop_register(), but this callback 356da6c28aaSamw * will be called when a file system is first mounted 357da6c28aaSamw */ 358da6c28aaSamw static void 359da6c28aaSamw nbmand_changed_cb(void *arg, uint64_t newval) 360da6c28aaSamw { 361da6c28aaSamw zfsvfs_t *zfsvfs = arg; 362da6c28aaSamw if (newval == FALSE) { 363da6c28aaSamw vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND); 364da6c28aaSamw vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND, NULL, 0); 365da6c28aaSamw } else { 366da6c28aaSamw vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND); 367da6c28aaSamw vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND, NULL, 0); 368da6c28aaSamw } 369da6c28aaSamw } 370da6c28aaSamw 371fa9e4066Sahrens static void 372fa9e4066Sahrens snapdir_changed_cb(void *arg, uint64_t newval) 373fa9e4066Sahrens { 374fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 375fa9e4066Sahrens 376fa9e4066Sahrens zfsvfs->z_show_ctldir = newval; 377fa9e4066Sahrens } 378fa9e4066Sahrens 379da6c28aaSamw static void 380da6c28aaSamw vscan_changed_cb(void *arg, uint64_t newval) 381da6c28aaSamw { 382da6c28aaSamw zfsvfs_t *zfsvfs = arg; 383da6c28aaSamw 384da6c28aaSamw zfsvfs->z_vscan = newval; 385da6c28aaSamw } 386da6c28aaSamw 387a3c49ce1SAlbert Lee static void 388a3c49ce1SAlbert Lee acl_mode_changed_cb(void *arg, uint64_t newval) 389a3c49ce1SAlbert Lee { 390a3c49ce1SAlbert Lee zfsvfs_t *zfsvfs = arg; 391a3c49ce1SAlbert Lee 392a3c49ce1SAlbert Lee zfsvfs->z_acl_mode = newval; 393a3c49ce1SAlbert Lee } 394a3c49ce1SAlbert Lee 395fa9e4066Sahrens static void 396fa9e4066Sahrens acl_inherit_changed_cb(void *arg, uint64_t newval) 397fa9e4066Sahrens { 398fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 399fa9e4066Sahrens 400fa9e4066Sahrens zfsvfs->z_acl_inherit = newval; 401fa9e4066Sahrens } 402fa9e4066Sahrens 403ea8dc4b6Seschrock static int 404ea8dc4b6Seschrock zfs_register_callbacks(vfs_t *vfsp) 405ea8dc4b6Seschrock { 406ea8dc4b6Seschrock struct dsl_dataset *ds = NULL; 407ea8dc4b6Seschrock objset_t *os = NULL; 408ea8dc4b6Seschrock zfsvfs_t *zfsvfs = NULL; 409da6c28aaSamw uint64_t nbmand; 410*d5285caeSGeorge Wilson boolean_t readonly = B_FALSE; 411*d5285caeSGeorge Wilson boolean_t do_readonly = B_FALSE; 412*d5285caeSGeorge Wilson boolean_t setuid = B_FALSE; 413*d5285caeSGeorge Wilson boolean_t do_setuid = B_FALSE; 414*d5285caeSGeorge Wilson boolean_t exec = B_FALSE; 415*d5285caeSGeorge Wilson boolean_t do_exec = B_FALSE; 416*d5285caeSGeorge Wilson boolean_t devices = B_FALSE; 417*d5285caeSGeorge Wilson boolean_t do_devices = B_FALSE; 418*d5285caeSGeorge Wilson boolean_t xattr = B_FALSE; 419*d5285caeSGeorge Wilson boolean_t do_xattr = B_FALSE; 420*d5285caeSGeorge Wilson boolean_t atime = B_FALSE; 421*d5285caeSGeorge Wilson boolean_t do_atime = B_FALSE; 422ea8dc4b6Seschrock int error = 0; 423ea8dc4b6Seschrock 424ea8dc4b6Seschrock ASSERT(vfsp); 425ea8dc4b6Seschrock zfsvfs = vfsp->vfs_data; 426ea8dc4b6Seschrock ASSERT(zfsvfs); 427ea8dc4b6Seschrock os = zfsvfs->z_os; 428fa9e4066Sahrens 429fa9e4066Sahrens /* 430ea8dc4b6Seschrock * The act of registering our callbacks will destroy any mount 431ea8dc4b6Seschrock * options we may have. In order to enable temporary overrides 4327b55fa8eSck * of mount options, we stash away the current values and 433ea8dc4b6Seschrock * restore them after we register the callbacks. 434fa9e4066Sahrens */ 435f9af39baSGeorge Wilson if (vfs_optionisset(vfsp, MNTOPT_RO, NULL) || 436f9af39baSGeorge Wilson !spa_writeable(dmu_objset_spa(os))) { 437ea8dc4b6Seschrock readonly = B_TRUE; 438ea8dc4b6Seschrock do_readonly = B_TRUE; 439ea8dc4b6Seschrock } else if (vfs_optionisset(vfsp, MNTOPT_RW, NULL)) { 440ea8dc4b6Seschrock readonly = B_FALSE; 441ea8dc4b6Seschrock do_readonly = B_TRUE; 442ea8dc4b6Seschrock } 443ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL)) { 444ea8dc4b6Seschrock devices = B_FALSE; 445ea8dc4b6Seschrock setuid = B_FALSE; 446ea8dc4b6Seschrock do_devices = B_TRUE; 447ea8dc4b6Seschrock do_setuid = B_TRUE; 448ea8dc4b6Seschrock } else { 449ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL)) { 450ea8dc4b6Seschrock devices = B_FALSE; 451ea8dc4b6Seschrock do_devices = B_TRUE; 452b1b8ab34Slling } else if (vfs_optionisset(vfsp, MNTOPT_DEVICES, NULL)) { 453ea8dc4b6Seschrock devices = B_TRUE; 454ea8dc4b6Seschrock do_devices = B_TRUE; 455fa9e4066Sahrens } 456fa9e4066Sahrens 457ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) { 458ea8dc4b6Seschrock setuid = B_FALSE; 459ea8dc4b6Seschrock do_setuid = B_TRUE; 460ea8dc4b6Seschrock } else if (vfs_optionisset(vfsp, MNTOPT_SETUID, NULL)) { 461ea8dc4b6Seschrock setuid = B_TRUE; 462ea8dc4b6Seschrock do_setuid = B_TRUE; 463fa9e4066Sahrens } 464ea8dc4b6Seschrock } 465ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) { 466ea8dc4b6Seschrock exec = B_FALSE; 467ea8dc4b6Seschrock do_exec = B_TRUE; 468ea8dc4b6Seschrock } else if (vfs_optionisset(vfsp, MNTOPT_EXEC, NULL)) { 469ea8dc4b6Seschrock exec = B_TRUE; 470ea8dc4b6Seschrock do_exec = B_TRUE; 471fa9e4066Sahrens } 4727b55fa8eSck if (vfs_optionisset(vfsp, MNTOPT_NOXATTR, NULL)) { 4737b55fa8eSck xattr = B_FALSE; 4747b55fa8eSck do_xattr = B_TRUE; 4757b55fa8eSck } else if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) { 4767b55fa8eSck xattr = B_TRUE; 4777b55fa8eSck do_xattr = B_TRUE; 4787b55fa8eSck } 479b510d378Slling if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) { 480b510d378Slling atime = B_FALSE; 481b510d378Slling do_atime = B_TRUE; 482b510d378Slling } else if (vfs_optionisset(vfsp, MNTOPT_ATIME, NULL)) { 483b510d378Slling atime = B_TRUE; 484b510d378Slling do_atime = B_TRUE; 485b510d378Slling } 486fa9e4066Sahrens 487da6c28aaSamw /* 488da6c28aaSamw * nbmand is a special property. It can only be changed at 489da6c28aaSamw * mount time. 490da6c28aaSamw * 491da6c28aaSamw * This is weird, but it is documented to only be changeable 492da6c28aaSamw * at mount time. 493da6c28aaSamw */ 494da6c28aaSamw if (vfs_optionisset(vfsp, MNTOPT_NONBMAND, NULL)) { 495da6c28aaSamw nbmand = B_FALSE; 496da6c28aaSamw } else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) { 497da6c28aaSamw nbmand = B_TRUE; 498da6c28aaSamw } else { 499da6c28aaSamw char osname[MAXNAMELEN]; 500da6c28aaSamw 501da6c28aaSamw dmu_objset_name(os, osname); 502da6c28aaSamw if (error = dsl_prop_get_integer(osname, "nbmand", &nbmand, 503bb0ade09Sahrens NULL)) { 504bb0ade09Sahrens return (error); 505bb0ade09Sahrens } 506da6c28aaSamw } 507da6c28aaSamw 508fa9e4066Sahrens /* 509ea8dc4b6Seschrock * Register property callbacks. 510ea8dc4b6Seschrock * 511ea8dc4b6Seschrock * It would probably be fine to just check for i/o error from 512ea8dc4b6Seschrock * the first prop_register(), but I guess I like to go 513ea8dc4b6Seschrock * overboard... 514fa9e4066Sahrens */ 515ea8dc4b6Seschrock ds = dmu_objset_ds(os); 516ea8dc4b6Seschrock error = dsl_prop_register(ds, "atime", atime_changed_cb, zfsvfs); 5177b55fa8eSck error = error ? error : dsl_prop_register(ds, 5187b55fa8eSck "xattr", xattr_changed_cb, zfsvfs); 519ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 520ea8dc4b6Seschrock "recordsize", blksz_changed_cb, zfsvfs); 521ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 522ea8dc4b6Seschrock "readonly", readonly_changed_cb, zfsvfs); 523ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 524ea8dc4b6Seschrock "devices", devices_changed_cb, zfsvfs); 525ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 526ea8dc4b6Seschrock "setuid", setuid_changed_cb, zfsvfs); 527ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 528ea8dc4b6Seschrock "exec", exec_changed_cb, zfsvfs); 529ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 530ea8dc4b6Seschrock "snapdir", snapdir_changed_cb, zfsvfs); 531a3c49ce1SAlbert Lee error = error ? error : dsl_prop_register(ds, 532a3c49ce1SAlbert Lee "aclmode", acl_mode_changed_cb, zfsvfs); 533ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 534ea8dc4b6Seschrock "aclinherit", acl_inherit_changed_cb, zfsvfs); 535da6c28aaSamw error = error ? error : dsl_prop_register(ds, 536da6c28aaSamw "vscan", vscan_changed_cb, zfsvfs); 537ea8dc4b6Seschrock if (error) 538ea8dc4b6Seschrock goto unregister; 539fa9e4066Sahrens 540ea8dc4b6Seschrock /* 541ea8dc4b6Seschrock * Invoke our callbacks to restore temporary mount options. 542ea8dc4b6Seschrock */ 543ea8dc4b6Seschrock if (do_readonly) 544ea8dc4b6Seschrock readonly_changed_cb(zfsvfs, readonly); 545ea8dc4b6Seschrock if (do_setuid) 546ea8dc4b6Seschrock setuid_changed_cb(zfsvfs, setuid); 547ea8dc4b6Seschrock if (do_exec) 548ea8dc4b6Seschrock exec_changed_cb(zfsvfs, exec); 549ea8dc4b6Seschrock if (do_devices) 550ea8dc4b6Seschrock devices_changed_cb(zfsvfs, devices); 5517b55fa8eSck if (do_xattr) 5527b55fa8eSck xattr_changed_cb(zfsvfs, xattr); 553b510d378Slling if (do_atime) 554b510d378Slling atime_changed_cb(zfsvfs, atime); 555fa9e4066Sahrens 556da6c28aaSamw nbmand_changed_cb(zfsvfs, nbmand); 557da6c28aaSamw 558ea8dc4b6Seschrock return (0); 559fa9e4066Sahrens 560ea8dc4b6Seschrock unregister: 561fa9e4066Sahrens /* 562ea8dc4b6Seschrock * We may attempt to unregister some callbacks that are not 563ea8dc4b6Seschrock * registered, but this is OK; it will simply return ENOMSG, 564ea8dc4b6Seschrock * which we will ignore. 565fa9e4066Sahrens */ 566ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "atime", atime_changed_cb, zfsvfs); 5677b55fa8eSck (void) dsl_prop_unregister(ds, "xattr", xattr_changed_cb, zfsvfs); 568ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, zfsvfs); 569ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "readonly", readonly_changed_cb, zfsvfs); 570ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "devices", devices_changed_cb, zfsvfs); 571ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "setuid", setuid_changed_cb, zfsvfs); 572ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "exec", exec_changed_cb, zfsvfs); 573ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, zfsvfs); 574a3c49ce1SAlbert Lee (void) dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, zfsvfs); 575ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "aclinherit", acl_inherit_changed_cb, 576ea8dc4b6Seschrock zfsvfs); 577da6c28aaSamw (void) dsl_prop_unregister(ds, "vscan", vscan_changed_cb, zfsvfs); 578ea8dc4b6Seschrock return (error); 579ea8dc4b6Seschrock 580ea8dc4b6Seschrock } 581ea8dc4b6Seschrock 5829966ca11SMatthew Ahrens static int 5830a586ceaSMark Shellenbaum zfs_space_delta_cb(dmu_object_type_t bonustype, void *data, 5849966ca11SMatthew Ahrens uint64_t *userp, uint64_t *groupp) 58514843421SMatthew Ahrens { 5860a586ceaSMark Shellenbaum int error = 0; 58714843421SMatthew Ahrens 58806e0070dSMark Shellenbaum /* 58906e0070dSMark Shellenbaum * Is it a valid type of object to track? 59006e0070dSMark Shellenbaum */ 5910a586ceaSMark Shellenbaum if (bonustype != DMU_OT_ZNODE && bonustype != DMU_OT_SA) 5929966ca11SMatthew Ahrens return (ENOENT); 59314843421SMatthew Ahrens 59406e0070dSMark Shellenbaum /* 59506e0070dSMark Shellenbaum * If we have a NULL data pointer 59606e0070dSMark Shellenbaum * then assume the id's aren't changing and 59706e0070dSMark Shellenbaum * return EEXIST to the dmu to let it know to 59806e0070dSMark Shellenbaum * use the same ids 59906e0070dSMark Shellenbaum */ 60006e0070dSMark Shellenbaum if (data == NULL) 60106e0070dSMark Shellenbaum return (EEXIST); 60206e0070dSMark Shellenbaum 6030a586ceaSMark Shellenbaum if (bonustype == DMU_OT_ZNODE) { 604e828a46dSMatthew Ahrens znode_phys_t *znp = data; 6050a586ceaSMark Shellenbaum *userp = znp->zp_uid; 6060a586ceaSMark Shellenbaum *groupp = znp->zp_gid; 6070a586ceaSMark Shellenbaum } else { 6080a586ceaSMark Shellenbaum int hdrsize; 609e828a46dSMatthew Ahrens sa_hdr_phys_t *sap = data; 610e828a46dSMatthew Ahrens sa_hdr_phys_t sa = *sap; 611e828a46dSMatthew Ahrens boolean_t swap = B_FALSE; 6120a586ceaSMark Shellenbaum 6130a586ceaSMark Shellenbaum ASSERT(bonustype == DMU_OT_SA); 6140a586ceaSMark Shellenbaum 615e828a46dSMatthew Ahrens if (sa.sa_magic == 0) { 61606e0070dSMark Shellenbaum /* 61706e0070dSMark Shellenbaum * This should only happen for newly created 61806e0070dSMark Shellenbaum * files that haven't had the znode data filled 61906e0070dSMark Shellenbaum * in yet. 62006e0070dSMark Shellenbaum */ 62106e0070dSMark Shellenbaum *userp = 0; 62206e0070dSMark Shellenbaum *groupp = 0; 623e828a46dSMatthew Ahrens return (0); 624e828a46dSMatthew Ahrens } 625e828a46dSMatthew Ahrens if (sa.sa_magic == BSWAP_32(SA_MAGIC)) { 626e828a46dSMatthew Ahrens sa.sa_magic = SA_MAGIC; 627e828a46dSMatthew Ahrens sa.sa_layout_info = BSWAP_16(sa.sa_layout_info); 628e828a46dSMatthew Ahrens swap = B_TRUE; 629e828a46dSMatthew Ahrens } else { 630e828a46dSMatthew Ahrens VERIFY3U(sa.sa_magic, ==, SA_MAGIC); 631e828a46dSMatthew Ahrens } 632e828a46dSMatthew Ahrens 633e828a46dSMatthew Ahrens hdrsize = sa_hdrsize(&sa); 634e828a46dSMatthew Ahrens VERIFY3U(hdrsize, >=, sizeof (sa_hdr_phys_t)); 635e828a46dSMatthew Ahrens *userp = *((uint64_t *)((uintptr_t)data + hdrsize + 636e828a46dSMatthew Ahrens SA_UID_OFFSET)); 637e828a46dSMatthew Ahrens *groupp = *((uint64_t *)((uintptr_t)data + hdrsize + 638e828a46dSMatthew Ahrens SA_GID_OFFSET)); 639e828a46dSMatthew Ahrens if (swap) { 640e828a46dSMatthew Ahrens *userp = BSWAP_64(*userp); 641e828a46dSMatthew Ahrens *groupp = BSWAP_64(*groupp); 6420a586ceaSMark Shellenbaum } 6430a586ceaSMark Shellenbaum } 6440a586ceaSMark Shellenbaum return (error); 64514843421SMatthew Ahrens } 64614843421SMatthew Ahrens 64714843421SMatthew Ahrens static void 64814843421SMatthew Ahrens fuidstr_to_sid(zfsvfs_t *zfsvfs, const char *fuidstr, 64914843421SMatthew Ahrens char *domainbuf, int buflen, uid_t *ridp) 65014843421SMatthew Ahrens { 65114843421SMatthew Ahrens uint64_t fuid; 65214843421SMatthew Ahrens const char *domain; 65314843421SMatthew Ahrens 65414843421SMatthew Ahrens fuid = strtonum(fuidstr, NULL); 65514843421SMatthew Ahrens 65614843421SMatthew Ahrens domain = zfs_fuid_find_by_idx(zfsvfs, FUID_INDEX(fuid)); 65714843421SMatthew Ahrens if (domain) 65814843421SMatthew Ahrens (void) strlcpy(domainbuf, domain, buflen); 65914843421SMatthew Ahrens else 66014843421SMatthew Ahrens domainbuf[0] = '\0'; 66114843421SMatthew Ahrens *ridp = FUID_RID(fuid); 66214843421SMatthew Ahrens } 66314843421SMatthew Ahrens 66414843421SMatthew Ahrens static uint64_t 66514843421SMatthew Ahrens zfs_userquota_prop_to_obj(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type) 66614843421SMatthew Ahrens { 66714843421SMatthew Ahrens switch (type) { 66814843421SMatthew Ahrens case ZFS_PROP_USERUSED: 66914843421SMatthew Ahrens return (DMU_USERUSED_OBJECT); 67014843421SMatthew Ahrens case ZFS_PROP_GROUPUSED: 67114843421SMatthew Ahrens return (DMU_GROUPUSED_OBJECT); 67214843421SMatthew Ahrens case ZFS_PROP_USERQUOTA: 67314843421SMatthew Ahrens return (zfsvfs->z_userquota_obj); 67414843421SMatthew Ahrens case ZFS_PROP_GROUPQUOTA: 67514843421SMatthew Ahrens return (zfsvfs->z_groupquota_obj); 67614843421SMatthew Ahrens } 67714843421SMatthew Ahrens return (0); 67814843421SMatthew Ahrens } 67914843421SMatthew Ahrens 68014843421SMatthew Ahrens int 68114843421SMatthew Ahrens zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 68214843421SMatthew Ahrens uint64_t *cookiep, void *vbuf, uint64_t *bufsizep) 68314843421SMatthew Ahrens { 68414843421SMatthew Ahrens int error; 68514843421SMatthew Ahrens zap_cursor_t zc; 68614843421SMatthew Ahrens zap_attribute_t za; 68714843421SMatthew Ahrens zfs_useracct_t *buf = vbuf; 68814843421SMatthew Ahrens uint64_t obj; 68914843421SMatthew Ahrens 69014843421SMatthew Ahrens if (!dmu_objset_userspace_present(zfsvfs->z_os)) 69114843421SMatthew Ahrens return (ENOTSUP); 69214843421SMatthew Ahrens 69314843421SMatthew Ahrens obj = zfs_userquota_prop_to_obj(zfsvfs, type); 69414843421SMatthew Ahrens if (obj == 0) { 69514843421SMatthew Ahrens *bufsizep = 0; 69614843421SMatthew Ahrens return (0); 69714843421SMatthew Ahrens } 69814843421SMatthew Ahrens 69914843421SMatthew Ahrens for (zap_cursor_init_serialized(&zc, zfsvfs->z_os, obj, *cookiep); 70014843421SMatthew Ahrens (error = zap_cursor_retrieve(&zc, &za)) == 0; 70114843421SMatthew Ahrens zap_cursor_advance(&zc)) { 70214843421SMatthew Ahrens if ((uintptr_t)buf - (uintptr_t)vbuf + sizeof (zfs_useracct_t) > 70314843421SMatthew Ahrens *bufsizep) 70414843421SMatthew Ahrens break; 70514843421SMatthew Ahrens 70614843421SMatthew Ahrens fuidstr_to_sid(zfsvfs, za.za_name, 70714843421SMatthew Ahrens buf->zu_domain, sizeof (buf->zu_domain), &buf->zu_rid); 70814843421SMatthew Ahrens 70914843421SMatthew Ahrens buf->zu_space = za.za_first_integer; 71014843421SMatthew Ahrens buf++; 71114843421SMatthew Ahrens } 71214843421SMatthew Ahrens if (error == ENOENT) 71314843421SMatthew Ahrens error = 0; 71414843421SMatthew Ahrens 71514843421SMatthew Ahrens ASSERT3U((uintptr_t)buf - (uintptr_t)vbuf, <=, *bufsizep); 71614843421SMatthew Ahrens *bufsizep = (uintptr_t)buf - (uintptr_t)vbuf; 71714843421SMatthew Ahrens *cookiep = zap_cursor_serialize(&zc); 71814843421SMatthew Ahrens zap_cursor_fini(&zc); 71914843421SMatthew Ahrens return (error); 72014843421SMatthew Ahrens } 72114843421SMatthew Ahrens 72214843421SMatthew Ahrens /* 72314843421SMatthew Ahrens * buf must be big enough (eg, 32 bytes) 72414843421SMatthew Ahrens */ 72514843421SMatthew Ahrens static int 72614843421SMatthew Ahrens id_to_fuidstr(zfsvfs_t *zfsvfs, const char *domain, uid_t rid, 72714843421SMatthew Ahrens char *buf, boolean_t addok) 72814843421SMatthew Ahrens { 72914843421SMatthew Ahrens uint64_t fuid; 73014843421SMatthew Ahrens int domainid = 0; 73114843421SMatthew Ahrens 73214843421SMatthew Ahrens if (domain && domain[0]) { 73314843421SMatthew Ahrens domainid = zfs_fuid_find_by_domain(zfsvfs, domain, NULL, addok); 73414843421SMatthew Ahrens if (domainid == -1) 73514843421SMatthew Ahrens return (ENOENT); 73614843421SMatthew Ahrens } 73714843421SMatthew Ahrens fuid = FUID_ENCODE(domainid, rid); 73814843421SMatthew Ahrens (void) sprintf(buf, "%llx", (longlong_t)fuid); 73914843421SMatthew Ahrens return (0); 74014843421SMatthew Ahrens } 74114843421SMatthew Ahrens 74214843421SMatthew Ahrens int 74314843421SMatthew Ahrens zfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 74414843421SMatthew Ahrens const char *domain, uint64_t rid, uint64_t *valp) 74514843421SMatthew Ahrens { 74614843421SMatthew Ahrens char buf[32]; 74714843421SMatthew Ahrens int err; 74814843421SMatthew Ahrens uint64_t obj; 74914843421SMatthew Ahrens 75014843421SMatthew Ahrens *valp = 0; 75114843421SMatthew Ahrens 75214843421SMatthew Ahrens if (!dmu_objset_userspace_present(zfsvfs->z_os)) 75314843421SMatthew Ahrens return (ENOTSUP); 75414843421SMatthew Ahrens 75514843421SMatthew Ahrens obj = zfs_userquota_prop_to_obj(zfsvfs, type); 75614843421SMatthew Ahrens if (obj == 0) 75714843421SMatthew Ahrens return (0); 75814843421SMatthew Ahrens 75914843421SMatthew Ahrens err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_FALSE); 76014843421SMatthew Ahrens if (err) 76114843421SMatthew Ahrens return (err); 76214843421SMatthew Ahrens 76314843421SMatthew Ahrens err = zap_lookup(zfsvfs->z_os, obj, buf, 8, 1, valp); 76414843421SMatthew Ahrens if (err == ENOENT) 76514843421SMatthew Ahrens err = 0; 76614843421SMatthew Ahrens return (err); 76714843421SMatthew Ahrens } 76814843421SMatthew Ahrens 76914843421SMatthew Ahrens int 77014843421SMatthew Ahrens zfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 77114843421SMatthew Ahrens const char *domain, uint64_t rid, uint64_t quota) 77214843421SMatthew Ahrens { 77314843421SMatthew Ahrens char buf[32]; 77414843421SMatthew Ahrens int err; 77514843421SMatthew Ahrens dmu_tx_t *tx; 77614843421SMatthew Ahrens uint64_t *objp; 77714843421SMatthew Ahrens boolean_t fuid_dirtied; 77814843421SMatthew Ahrens 77914843421SMatthew Ahrens if (type != ZFS_PROP_USERQUOTA && type != ZFS_PROP_GROUPQUOTA) 78014843421SMatthew Ahrens return (EINVAL); 78114843421SMatthew Ahrens 78214843421SMatthew Ahrens if (zfsvfs->z_version < ZPL_VERSION_USERSPACE) 78314843421SMatthew Ahrens return (ENOTSUP); 78414843421SMatthew Ahrens 78514843421SMatthew Ahrens objp = (type == ZFS_PROP_USERQUOTA) ? &zfsvfs->z_userquota_obj : 78614843421SMatthew Ahrens &zfsvfs->z_groupquota_obj; 78714843421SMatthew Ahrens 78814843421SMatthew Ahrens err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_TRUE); 78914843421SMatthew Ahrens if (err) 79014843421SMatthew Ahrens return (err); 79114843421SMatthew Ahrens fuid_dirtied = zfsvfs->z_fuid_dirty; 79214843421SMatthew Ahrens 79314843421SMatthew Ahrens tx = dmu_tx_create(zfsvfs->z_os); 79414843421SMatthew Ahrens dmu_tx_hold_zap(tx, *objp ? *objp : DMU_NEW_OBJECT, B_TRUE, NULL); 79514843421SMatthew Ahrens if (*objp == 0) { 79614843421SMatthew Ahrens dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE, 79714843421SMatthew Ahrens zfs_userquota_prop_prefixes[type]); 79814843421SMatthew Ahrens } 79914843421SMatthew Ahrens if (fuid_dirtied) 80014843421SMatthew Ahrens zfs_fuid_txhold(zfsvfs, tx); 80114843421SMatthew Ahrens err = dmu_tx_assign(tx, TXG_WAIT); 80214843421SMatthew Ahrens if (err) { 80314843421SMatthew Ahrens dmu_tx_abort(tx); 80414843421SMatthew Ahrens return (err); 80514843421SMatthew Ahrens } 80614843421SMatthew Ahrens 80714843421SMatthew Ahrens mutex_enter(&zfsvfs->z_lock); 80814843421SMatthew Ahrens if (*objp == 0) { 80914843421SMatthew Ahrens *objp = zap_create(zfsvfs->z_os, DMU_OT_USERGROUP_QUOTA, 81014843421SMatthew Ahrens DMU_OT_NONE, 0, tx); 81114843421SMatthew Ahrens VERIFY(0 == zap_add(zfsvfs->z_os, MASTER_NODE_OBJ, 81214843421SMatthew Ahrens zfs_userquota_prop_prefixes[type], 8, 1, objp, tx)); 81314843421SMatthew Ahrens } 81414843421SMatthew Ahrens mutex_exit(&zfsvfs->z_lock); 81514843421SMatthew Ahrens 81614843421SMatthew Ahrens if (quota == 0) { 81714843421SMatthew Ahrens err = zap_remove(zfsvfs->z_os, *objp, buf, tx); 81814843421SMatthew Ahrens if (err == ENOENT) 81914843421SMatthew Ahrens err = 0; 82014843421SMatthew Ahrens } else { 82114843421SMatthew Ahrens err = zap_update(zfsvfs->z_os, *objp, buf, 8, 1, "a, tx); 82214843421SMatthew Ahrens } 82314843421SMatthew Ahrens ASSERT(err == 0); 82414843421SMatthew Ahrens if (fuid_dirtied) 82514843421SMatthew Ahrens zfs_fuid_sync(zfsvfs, tx); 82614843421SMatthew Ahrens dmu_tx_commit(tx); 82714843421SMatthew Ahrens return (err); 82814843421SMatthew Ahrens } 82914843421SMatthew Ahrens 83014843421SMatthew Ahrens boolean_t 8310a586ceaSMark Shellenbaum zfs_fuid_overquota(zfsvfs_t *zfsvfs, boolean_t isgroup, uint64_t fuid) 83214843421SMatthew Ahrens { 83314843421SMatthew Ahrens char buf[32]; 83414843421SMatthew Ahrens uint64_t used, quota, usedobj, quotaobj; 83514843421SMatthew Ahrens int err; 83614843421SMatthew Ahrens 83714843421SMatthew Ahrens usedobj = isgroup ? DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT; 83814843421SMatthew Ahrens quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj; 83914843421SMatthew Ahrens 84014843421SMatthew Ahrens if (quotaobj == 0 || zfsvfs->z_replay) 84114843421SMatthew Ahrens return (B_FALSE); 84214843421SMatthew Ahrens 84314843421SMatthew Ahrens (void) sprintf(buf, "%llx", (longlong_t)fuid); 84414843421SMatthew Ahrens err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); 84514843421SMatthew Ahrens if (err != 0) 84614843421SMatthew Ahrens return (B_FALSE); 84714843421SMatthew Ahrens 84814843421SMatthew Ahrens err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used); 84914843421SMatthew Ahrens if (err != 0) 85014843421SMatthew Ahrens return (B_FALSE); 85114843421SMatthew Ahrens return (used >= quota); 85214843421SMatthew Ahrens } 85314843421SMatthew Ahrens 8540a586ceaSMark Shellenbaum boolean_t 8550a586ceaSMark Shellenbaum zfs_owner_overquota(zfsvfs_t *zfsvfs, znode_t *zp, boolean_t isgroup) 8560a586ceaSMark Shellenbaum { 8570a586ceaSMark Shellenbaum uint64_t fuid; 8580a586ceaSMark Shellenbaum uint64_t quotaobj; 8590a586ceaSMark Shellenbaum 8600a586ceaSMark Shellenbaum quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj; 8610a586ceaSMark Shellenbaum 862f1696b23SMark Shellenbaum fuid = isgroup ? zp->z_gid : zp->z_uid; 8630a586ceaSMark Shellenbaum 8640a586ceaSMark Shellenbaum if (quotaobj == 0 || zfsvfs->z_replay) 8650a586ceaSMark Shellenbaum return (B_FALSE); 8660a586ceaSMark Shellenbaum 8670a586ceaSMark Shellenbaum return (zfs_fuid_overquota(zfsvfs, isgroup, fuid)); 8680a586ceaSMark Shellenbaum } 8690a586ceaSMark Shellenbaum 87014843421SMatthew Ahrens int 871af4c679fSSean McEnroe zfsvfs_create(const char *osname, zfsvfs_t **zfvp) 87214843421SMatthew Ahrens { 87314843421SMatthew Ahrens objset_t *os; 87414843421SMatthew Ahrens zfsvfs_t *zfsvfs; 87514843421SMatthew Ahrens uint64_t zval; 87614843421SMatthew Ahrens int i, error; 8770a586ceaSMark Shellenbaum uint64_t sa_obj; 87814843421SMatthew Ahrens 879503ad85cSMatthew Ahrens zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); 88014843421SMatthew Ahrens 881503ad85cSMatthew Ahrens /* 882503ad85cSMatthew Ahrens * We claim to always be readonly so we can open snapshots; 883503ad85cSMatthew Ahrens * other ZPL code will prevent us from writing to snapshots. 884503ad85cSMatthew Ahrens */ 885503ad85cSMatthew Ahrens error = dmu_objset_own(osname, DMU_OST_ZFS, B_TRUE, zfsvfs, &os); 886503ad85cSMatthew Ahrens if (error) { 887503ad85cSMatthew Ahrens kmem_free(zfsvfs, sizeof (zfsvfs_t)); 88814843421SMatthew Ahrens return (error); 889503ad85cSMatthew Ahrens } 89014843421SMatthew Ahrens 89114843421SMatthew Ahrens /* 89214843421SMatthew Ahrens * Initialize the zfs-specific filesystem structure. 89314843421SMatthew Ahrens * Should probably make this a kmem cache, shuffle fields, 89414843421SMatthew Ahrens * and just bzero up to z_hold_mtx[]. 89514843421SMatthew Ahrens */ 89614843421SMatthew Ahrens zfsvfs->z_vfs = NULL; 89714843421SMatthew Ahrens zfsvfs->z_parent = zfsvfs; 89814843421SMatthew Ahrens zfsvfs->z_max_blksz = SPA_MAXBLOCKSIZE; 89914843421SMatthew Ahrens zfsvfs->z_show_ctldir = ZFS_SNAPDIR_VISIBLE; 90014843421SMatthew Ahrens zfsvfs->z_os = os; 90114843421SMatthew Ahrens 90214843421SMatthew Ahrens error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zfsvfs->z_version); 90314843421SMatthew Ahrens if (error) { 90414843421SMatthew Ahrens goto out; 905dc7cd546SMark Shellenbaum } else if (zfsvfs->z_version > 906dc7cd546SMark Shellenbaum zfs_zpl_version_map(spa_version(dmu_objset_spa(os)))) { 907dc7cd546SMark Shellenbaum (void) printf("Can't mount a version %lld file system " 908dc7cd546SMark Shellenbaum "on a version %lld pool\n. Pool must be upgraded to mount " 909dc7cd546SMark Shellenbaum "this file system.", (u_longlong_t)zfsvfs->z_version, 910dc7cd546SMark Shellenbaum (u_longlong_t)spa_version(dmu_objset_spa(os))); 91114843421SMatthew Ahrens error = ENOTSUP; 91214843421SMatthew Ahrens goto out; 91314843421SMatthew Ahrens } 91414843421SMatthew Ahrens if ((error = zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &zval)) != 0) 91514843421SMatthew Ahrens goto out; 91614843421SMatthew Ahrens zfsvfs->z_norm = (int)zval; 91714843421SMatthew Ahrens 91814843421SMatthew Ahrens if ((error = zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &zval)) != 0) 91914843421SMatthew Ahrens goto out; 92014843421SMatthew Ahrens zfsvfs->z_utf8 = (zval != 0); 92114843421SMatthew Ahrens 92214843421SMatthew Ahrens if ((error = zfs_get_zplprop(os, ZFS_PROP_CASE, &zval)) != 0) 92314843421SMatthew Ahrens goto out; 92414843421SMatthew Ahrens zfsvfs->z_case = (uint_t)zval; 92514843421SMatthew Ahrens 92614843421SMatthew Ahrens /* 92714843421SMatthew Ahrens * Fold case on file systems that are always or sometimes case 92814843421SMatthew Ahrens * insensitive. 92914843421SMatthew Ahrens */ 93014843421SMatthew Ahrens if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE || 93114843421SMatthew Ahrens zfsvfs->z_case == ZFS_CASE_MIXED) 93214843421SMatthew Ahrens zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER; 93314843421SMatthew Ahrens 93414843421SMatthew Ahrens zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os); 9350a586ceaSMark Shellenbaum zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os); 9360a586ceaSMark Shellenbaum 9370a586ceaSMark Shellenbaum if (zfsvfs->z_use_sa) { 9380a586ceaSMark Shellenbaum /* should either have both of these objects or none */ 9390a586ceaSMark Shellenbaum error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, 9400a586ceaSMark Shellenbaum &sa_obj); 9410a586ceaSMark Shellenbaum if (error) 9420a586ceaSMark Shellenbaum return (error); 9430a586ceaSMark Shellenbaum } else { 9440a586ceaSMark Shellenbaum /* 9450a586ceaSMark Shellenbaum * Pre SA versions file systems should never touch 9460a586ceaSMark Shellenbaum * either the attribute registration or layout objects. 9470a586ceaSMark Shellenbaum */ 9480a586ceaSMark Shellenbaum sa_obj = 0; 9490a586ceaSMark Shellenbaum } 9500a586ceaSMark Shellenbaum 9511d8ccc7bSMark Shellenbaum error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END, 9521d8ccc7bSMark Shellenbaum &zfsvfs->z_attr_table); 9531d8ccc7bSMark Shellenbaum if (error) 9541d8ccc7bSMark Shellenbaum goto out; 9550a586ceaSMark Shellenbaum 9560a586ceaSMark Shellenbaum if (zfsvfs->z_version >= ZPL_VERSION_SA) 9570a586ceaSMark Shellenbaum sa_register_update_callback(os, zfs_sa_upgrade); 95814843421SMatthew Ahrens 95914843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, 96014843421SMatthew Ahrens &zfsvfs->z_root); 96114843421SMatthew Ahrens if (error) 96214843421SMatthew Ahrens goto out; 96314843421SMatthew Ahrens ASSERT(zfsvfs->z_root != 0); 96414843421SMatthew Ahrens 96514843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET, 8, 1, 96614843421SMatthew Ahrens &zfsvfs->z_unlinkedobj); 96714843421SMatthew Ahrens if (error) 96814843421SMatthew Ahrens goto out; 96914843421SMatthew Ahrens 97014843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, 97114843421SMatthew Ahrens zfs_userquota_prop_prefixes[ZFS_PROP_USERQUOTA], 97214843421SMatthew Ahrens 8, 1, &zfsvfs->z_userquota_obj); 97314843421SMatthew Ahrens if (error && error != ENOENT) 97414843421SMatthew Ahrens goto out; 97514843421SMatthew Ahrens 97614843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, 97714843421SMatthew Ahrens zfs_userquota_prop_prefixes[ZFS_PROP_GROUPQUOTA], 97814843421SMatthew Ahrens 8, 1, &zfsvfs->z_groupquota_obj); 97914843421SMatthew Ahrens if (error && error != ENOENT) 98014843421SMatthew Ahrens goto out; 98114843421SMatthew Ahrens 98214843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES, 8, 1, 98314843421SMatthew Ahrens &zfsvfs->z_fuid_obj); 98414843421SMatthew Ahrens if (error && error != ENOENT) 98514843421SMatthew Ahrens goto out; 98614843421SMatthew Ahrens 98714843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SHARES_DIR, 8, 1, 98814843421SMatthew Ahrens &zfsvfs->z_shares_dir); 98914843421SMatthew Ahrens if (error && error != ENOENT) 99014843421SMatthew Ahrens goto out; 99114843421SMatthew Ahrens 99214843421SMatthew Ahrens mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); 99314843421SMatthew Ahrens mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL); 99414843421SMatthew Ahrens list_create(&zfsvfs->z_all_znodes, sizeof (znode_t), 99514843421SMatthew Ahrens offsetof(znode_t, z_link_node)); 99614843421SMatthew Ahrens rrw_init(&zfsvfs->z_teardown_lock); 99714843421SMatthew Ahrens rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL); 99814843421SMatthew Ahrens rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL); 99914843421SMatthew Ahrens for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) 100014843421SMatthew Ahrens mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); 100114843421SMatthew Ahrens 1002af4c679fSSean McEnroe *zfvp = zfsvfs; 100314843421SMatthew Ahrens return (0); 100414843421SMatthew Ahrens 100514843421SMatthew Ahrens out: 1006503ad85cSMatthew Ahrens dmu_objset_disown(os, zfsvfs); 1007af4c679fSSean McEnroe *zfvp = NULL; 100814843421SMatthew Ahrens kmem_free(zfsvfs, sizeof (zfsvfs_t)); 100914843421SMatthew Ahrens return (error); 101014843421SMatthew Ahrens } 101114843421SMatthew Ahrens 1012f18faf3fSek static int 1013f18faf3fSek zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) 1014f18faf3fSek { 1015f18faf3fSek int error; 1016f18faf3fSek 1017f18faf3fSek error = zfs_register_callbacks(zfsvfs->z_vfs); 1018f18faf3fSek if (error) 1019f18faf3fSek return (error); 1020f18faf3fSek 1021f18faf3fSek /* 1022f18faf3fSek * Set the objset user_ptr to track its zfsvfs. 1023f18faf3fSek */ 1024503ad85cSMatthew Ahrens mutex_enter(&zfsvfs->z_os->os_user_ptr_lock); 1025f18faf3fSek dmu_objset_set_user(zfsvfs->z_os, zfsvfs); 1026503ad85cSMatthew Ahrens mutex_exit(&zfsvfs->z_os->os_user_ptr_lock); 1027f18faf3fSek 1028377c02aaSNeil Perrin zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data); 1029377c02aaSNeil Perrin 1030f18faf3fSek /* 1031f18faf3fSek * If we are not mounting (ie: online recv), then we don't 1032f18faf3fSek * have to worry about replaying the log as we blocked all 1033f18faf3fSek * operations out since we closed the ZIL. 1034f18faf3fSek */ 1035f18faf3fSek if (mounting) { 1036a6e57bd4SNeil Perrin boolean_t readonly; 1037a6e57bd4SNeil Perrin 1038f18faf3fSek /* 1039f18faf3fSek * During replay we remove the read only flag to 1040f18faf3fSek * allow replays to succeed. 1041f18faf3fSek */ 1042f18faf3fSek readonly = zfsvfs->z_vfs->vfs_flag & VFS_RDONLY; 10431209a471SNeil Perrin if (readonly != 0) 10441209a471SNeil Perrin zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 10451209a471SNeil Perrin else 10461209a471SNeil Perrin zfs_unlinked_drain(zfsvfs); 1047f18faf3fSek 104855da60b9SMark J Musante /* 104955da60b9SMark J Musante * Parse and replay the intent log. 105055da60b9SMark J Musante * 105155da60b9SMark J Musante * Because of ziltest, this must be done after 105255da60b9SMark J Musante * zfs_unlinked_drain(). (Further note: ziltest 105355da60b9SMark J Musante * doesn't use readonly mounts, where 105455da60b9SMark J Musante * zfs_unlinked_drain() isn't called.) This is because 105555da60b9SMark J Musante * ziltest causes spa_sync() to think it's committed, 105655da60b9SMark J Musante * but actually it is not, so the intent log contains 105755da60b9SMark J Musante * many txg's worth of changes. 105855da60b9SMark J Musante * 105955da60b9SMark J Musante * In particular, if object N is in the unlinked set in 106055da60b9SMark J Musante * the last txg to actually sync, then it could be 106155da60b9SMark J Musante * actually freed in a later txg and then reallocated 106255da60b9SMark J Musante * in a yet later txg. This would write a "create 106355da60b9SMark J Musante * object N" record to the intent log. Normally, this 106455da60b9SMark J Musante * would be fine because the spa_sync() would have 106555da60b9SMark J Musante * written out the fact that object N is free, before 106655da60b9SMark J Musante * we could write the "create object N" intent log 106755da60b9SMark J Musante * record. 106855da60b9SMark J Musante * 106955da60b9SMark J Musante * But when we are in ziltest mode, we advance the "open 107055da60b9SMark J Musante * txg" without actually spa_sync()-ing the changes to 107155da60b9SMark J Musante * disk. So we would see that object N is still 107255da60b9SMark J Musante * allocated and in the unlinked set, and there is an 107355da60b9SMark J Musante * intent log record saying to allocate it. 107455da60b9SMark J Musante */ 1075f9af39baSGeorge Wilson if (spa_writeable(dmu_objset_spa(zfsvfs->z_os))) { 1076f9af39baSGeorge Wilson if (zil_replay_disable) { 1077f9af39baSGeorge Wilson zil_destroy(zfsvfs->z_log, B_FALSE); 1078f9af39baSGeorge Wilson } else { 1079f9af39baSGeorge Wilson zfsvfs->z_replay = B_TRUE; 1080f9af39baSGeorge Wilson zil_replay(zfsvfs->z_os, zfsvfs, 1081f9af39baSGeorge Wilson zfs_replay_vector); 1082f9af39baSGeorge Wilson zfsvfs->z_replay = B_FALSE; 1083f9af39baSGeorge Wilson } 10841209a471SNeil Perrin } 1085f18faf3fSek zfsvfs->z_vfs->vfs_flag |= readonly; /* restore readonly bit */ 1086f18faf3fSek } 1087f18faf3fSek 1088f18faf3fSek return (0); 1089f18faf3fSek } 1090f18faf3fSek 109114843421SMatthew Ahrens void 109214843421SMatthew Ahrens zfsvfs_free(zfsvfs_t *zfsvfs) 109347f263f4Sek { 109414843421SMatthew Ahrens int i; 10954e9583b2STom Erickson extern krwlock_t zfsvfs_lock; /* in zfs_znode.c */ 10964e9583b2STom Erickson 10974e9583b2STom Erickson /* 10984e9583b2STom Erickson * This is a barrier to prevent the filesystem from going away in 10994e9583b2STom Erickson * zfs_znode_move() until we can safely ensure that the filesystem is 11004e9583b2STom Erickson * not unmounted. We consider the filesystem valid before the barrier 11014e9583b2STom Erickson * and invalid after the barrier. 11024e9583b2STom Erickson */ 11034e9583b2STom Erickson rw_enter(&zfsvfs_lock, RW_READER); 11044e9583b2STom Erickson rw_exit(&zfsvfs_lock); 110514843421SMatthew Ahrens 110614843421SMatthew Ahrens zfs_fuid_destroy(zfsvfs); 110714843421SMatthew Ahrens 110847f263f4Sek mutex_destroy(&zfsvfs->z_znodes_lock); 11099e1320c0SMark Shellenbaum mutex_destroy(&zfsvfs->z_lock); 111047f263f4Sek list_destroy(&zfsvfs->z_all_znodes); 111147f263f4Sek rrw_destroy(&zfsvfs->z_teardown_lock); 111247f263f4Sek rw_destroy(&zfsvfs->z_teardown_inactive_lock); 111347f263f4Sek rw_destroy(&zfsvfs->z_fuid_lock); 111414843421SMatthew Ahrens for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) 111514843421SMatthew Ahrens mutex_destroy(&zfsvfs->z_hold_mtx[i]); 111647f263f4Sek kmem_free(zfsvfs, sizeof (zfsvfs_t)); 111747f263f4Sek } 111847f263f4Sek 111914843421SMatthew Ahrens static void 112014843421SMatthew Ahrens zfs_set_fuid_feature(zfsvfs_t *zfsvfs) 112114843421SMatthew Ahrens { 112214843421SMatthew Ahrens zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os); 112344bffe01SMark Shellenbaum if (zfsvfs->z_vfs) { 112444bffe01SMark Shellenbaum if (zfsvfs->z_use_fuids) { 112544bffe01SMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_XVATTR); 112644bffe01SMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS); 112744bffe01SMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS); 112844bffe01SMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE); 112944bffe01SMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER); 113044bffe01SMark Shellenbaum vfs_set_feature(zfsvfs->z_vfs, VFSFT_REPARSE); 113144bffe01SMark Shellenbaum } else { 113244bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_XVATTR); 113344bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS); 113444bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS); 113544bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE); 113644bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER); 113744bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_REPARSE); 113844bffe01SMark Shellenbaum } 113914843421SMatthew Ahrens } 11400a586ceaSMark Shellenbaum zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os); 114114843421SMatthew Ahrens } 114214843421SMatthew Ahrens 1143ea8dc4b6Seschrock static int 1144088f3894Sahrens zfs_domount(vfs_t *vfsp, char *osname) 1145ea8dc4b6Seschrock { 1146ea8dc4b6Seschrock dev_t mount_dev; 114714843421SMatthew Ahrens uint64_t recordsize, fsid_guid; 1148ea8dc4b6Seschrock int error = 0; 1149ea8dc4b6Seschrock zfsvfs_t *zfsvfs; 1150ea8dc4b6Seschrock 1151ea8dc4b6Seschrock ASSERT(vfsp); 1152ea8dc4b6Seschrock ASSERT(osname); 1153fa9e4066Sahrens 1154503ad85cSMatthew Ahrens error = zfsvfs_create(osname, &zfsvfs); 115514843421SMatthew Ahrens if (error) 115614843421SMatthew Ahrens return (error); 1157fa9e4066Sahrens zfsvfs->z_vfs = vfsp; 1158fa9e4066Sahrens 1159ea8dc4b6Seschrock /* Initialize the generic filesystem structure. */ 1160fa9e4066Sahrens vfsp->vfs_bcount = 0; 1161fa9e4066Sahrens vfsp->vfs_data = NULL; 1162fa9e4066Sahrens 1163ea8dc4b6Seschrock if (zfs_create_unique_device(&mount_dev) == -1) { 1164ea8dc4b6Seschrock error = ENODEV; 1165ea8dc4b6Seschrock goto out; 1166ea8dc4b6Seschrock } 1167fa9e4066Sahrens ASSERT(vfs_devismounted(mount_dev) == 0); 1168fa9e4066Sahrens 1169ea8dc4b6Seschrock if (error = dsl_prop_get_integer(osname, "recordsize", &recordsize, 1170ea8dc4b6Seschrock NULL)) 1171ea8dc4b6Seschrock goto out; 1172fa9e4066Sahrens 1173fa9e4066Sahrens vfsp->vfs_dev = mount_dev; 1174fa9e4066Sahrens vfsp->vfs_fstype = zfsfstype; 1175fa9e4066Sahrens vfsp->vfs_bsize = recordsize; 1176fa9e4066Sahrens vfsp->vfs_flag |= VFS_NOTRUNC; 1177fa9e4066Sahrens vfsp->vfs_data = zfsvfs; 1178fa9e4066Sahrens 117914843421SMatthew Ahrens /* 118014843421SMatthew Ahrens * The fsid is 64 bits, composed of an 8-bit fs type, which 118114843421SMatthew Ahrens * separates our fsid from any other filesystem types, and a 118214843421SMatthew Ahrens * 56-bit objset unique ID. The objset unique ID is unique to 118314843421SMatthew Ahrens * all objsets open on this system, provided by unique_create(). 118414843421SMatthew Ahrens * The 8-bit fs type must be put in the low bits of fsid[1] 118514843421SMatthew Ahrens * because that's where other Solaris filesystems put it. 118614843421SMatthew Ahrens */ 118714843421SMatthew Ahrens fsid_guid = dmu_objset_fsid_guid(zfsvfs->z_os); 118814843421SMatthew Ahrens ASSERT((fsid_guid & ~((1ULL<<56)-1)) == 0); 118914843421SMatthew Ahrens vfsp->vfs_fsid.val[0] = fsid_guid; 119014843421SMatthew Ahrens vfsp->vfs_fsid.val[1] = ((fsid_guid>>32) << 8) | 119114843421SMatthew Ahrens zfsfstype & 0xFF; 1192ea8dc4b6Seschrock 1193da6c28aaSamw /* 1194da6c28aaSamw * Set features for file system. 1195da6c28aaSamw */ 119614843421SMatthew Ahrens zfs_set_fuid_feature(zfsvfs); 1197de8267e0Stimh if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) { 1198de8267e0Stimh vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS); 1199de8267e0Stimh vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE); 1200de8267e0Stimh vfs_set_feature(vfsp, VFSFT_NOCASESENSITIVE); 1201de8267e0Stimh } else if (zfsvfs->z_case == ZFS_CASE_MIXED) { 1202de8267e0Stimh vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS); 1203de8267e0Stimh vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE); 1204de8267e0Stimh } 1205c242f9a0Schunli zhang - Sun Microsystems - Irvine United States vfs_set_feature(vfsp, VFSFT_ZEROCOPY_SUPPORTED); 1206da6c28aaSamw 1207ea8dc4b6Seschrock if (dmu_objset_is_snapshot(zfsvfs->z_os)) { 1208da6c28aaSamw uint64_t pval; 12097b55fa8eSck 1210fa9e4066Sahrens atime_changed_cb(zfsvfs, B_FALSE); 1211fa9e4066Sahrens readonly_changed_cb(zfsvfs, B_TRUE); 1212da6c28aaSamw if (error = dsl_prop_get_integer(osname, "xattr", &pval, NULL)) 12137b55fa8eSck goto out; 1214da6c28aaSamw xattr_changed_cb(zfsvfs, pval); 1215fa9e4066Sahrens zfsvfs->z_issnap = B_TRUE; 1216b9deb9cbSMark J Musante zfsvfs->z_os->os_sync = ZFS_SYNC_DISABLED; 1217777badbaSMatthew Ahrens 1218503ad85cSMatthew Ahrens mutex_enter(&zfsvfs->z_os->os_user_ptr_lock); 1219777badbaSMatthew Ahrens dmu_objset_set_user(zfsvfs->z_os, zfsvfs); 1220503ad85cSMatthew Ahrens mutex_exit(&zfsvfs->z_os->os_user_ptr_lock); 1221fa9e4066Sahrens } else { 1222f18faf3fSek error = zfsvfs_setup(zfsvfs, B_TRUE); 1223ea8dc4b6Seschrock } 1224fa9e4066Sahrens 1225ea8dc4b6Seschrock if (!zfsvfs->z_issnap) 1226ea8dc4b6Seschrock zfsctl_create(zfsvfs); 1227ea8dc4b6Seschrock out: 1228ea8dc4b6Seschrock if (error) { 1229503ad85cSMatthew Ahrens dmu_objset_disown(zfsvfs->z_os, zfsvfs); 123014843421SMatthew Ahrens zfsvfs_free(zfsvfs); 1231ea8dc4b6Seschrock } else { 1232ea8dc4b6Seschrock atomic_add_32(&zfs_active_fs_count, 1); 1233ea8dc4b6Seschrock } 1234fa9e4066Sahrens 1235ea8dc4b6Seschrock return (error); 1236ea8dc4b6Seschrock } 1237ea8dc4b6Seschrock 1238ea8dc4b6Seschrock void 1239ea8dc4b6Seschrock zfs_unregister_callbacks(zfsvfs_t *zfsvfs) 1240ea8dc4b6Seschrock { 1241ea8dc4b6Seschrock objset_t *os = zfsvfs->z_os; 1242ea8dc4b6Seschrock struct dsl_dataset *ds; 1243ea8dc4b6Seschrock 1244ea8dc4b6Seschrock /* 1245ea8dc4b6Seschrock * Unregister properties. 1246ea8dc4b6Seschrock */ 1247ea8dc4b6Seschrock if (!dmu_objset_is_snapshot(os)) { 1248fa9e4066Sahrens ds = dmu_objset_ds(os); 1249ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "atime", atime_changed_cb, 1250fa9e4066Sahrens zfsvfs) == 0); 1251fa9e4066Sahrens 12527b55fa8eSck VERIFY(dsl_prop_unregister(ds, "xattr", xattr_changed_cb, 12537b55fa8eSck zfsvfs) == 0); 12547b55fa8eSck 1255ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, 1256fa9e4066Sahrens zfsvfs) == 0); 1257fa9e4066Sahrens 1258ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "readonly", readonly_changed_cb, 1259fa9e4066Sahrens zfsvfs) == 0); 1260fa9e4066Sahrens 1261ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "devices", devices_changed_cb, 1262fa9e4066Sahrens zfsvfs) == 0); 1263fa9e4066Sahrens 1264ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "setuid", setuid_changed_cb, 1265fa9e4066Sahrens zfsvfs) == 0); 1266fa9e4066Sahrens 1267ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "exec", exec_changed_cb, 1268fa9e4066Sahrens zfsvfs) == 0); 1269fa9e4066Sahrens 1270ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, 1271fa9e4066Sahrens zfsvfs) == 0); 1272fa9e4066Sahrens 1273a3c49ce1SAlbert Lee VERIFY(dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, 1274a3c49ce1SAlbert Lee zfsvfs) == 0); 1275a3c49ce1SAlbert Lee 1276ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "aclinherit", 1277fa9e4066Sahrens acl_inherit_changed_cb, zfsvfs) == 0); 1278da6c28aaSamw 1279da6c28aaSamw VERIFY(dsl_prop_unregister(ds, "vscan", 1280da6c28aaSamw vscan_changed_cb, zfsvfs) == 0); 1281ea8dc4b6Seschrock } 1282ea8dc4b6Seschrock } 1283fa9e4066Sahrens 1284b1b8ab34Slling /* 1285b1b8ab34Slling * Convert a decimal digit string to a uint64_t integer. 1286b1b8ab34Slling */ 1287b1b8ab34Slling static int 1288b1b8ab34Slling str_to_uint64(char *str, uint64_t *objnum) 1289b1b8ab34Slling { 1290b1b8ab34Slling uint64_t num = 0; 1291b1b8ab34Slling 1292b1b8ab34Slling while (*str) { 1293b1b8ab34Slling if (*str < '0' || *str > '9') 1294b1b8ab34Slling return (EINVAL); 1295b1b8ab34Slling 1296b1b8ab34Slling num = num*10 + *str++ - '0'; 1297b1b8ab34Slling } 1298b1b8ab34Slling 1299b1b8ab34Slling *objnum = num; 1300b1b8ab34Slling return (0); 1301b1b8ab34Slling } 1302b1b8ab34Slling 1303b1b8ab34Slling /* 1304b1b8ab34Slling * The boot path passed from the boot loader is in the form of 1305b1b8ab34Slling * "rootpool-name/root-filesystem-object-number'. Convert this 1306b1b8ab34Slling * string to a dataset name: "rootpool-name/root-filesystem-name". 1307b1b8ab34Slling */ 1308b1b8ab34Slling static int 1309e7cbe64fSgw zfs_parse_bootfs(char *bpath, char *outpath) 1310b1b8ab34Slling { 1311b1b8ab34Slling char *slashp; 1312b1b8ab34Slling uint64_t objnum; 1313b1b8ab34Slling int error; 1314b1b8ab34Slling 1315b1b8ab34Slling if (*bpath == 0 || *bpath == '/') 1316b1b8ab34Slling return (EINVAL); 1317b1b8ab34Slling 131819397407SSherry Moore (void) strcpy(outpath, bpath); 131919397407SSherry Moore 1320b1b8ab34Slling slashp = strchr(bpath, '/'); 1321b1b8ab34Slling 1322b1b8ab34Slling /* if no '/', just return the pool name */ 1323b1b8ab34Slling if (slashp == NULL) { 1324b1b8ab34Slling return (0); 1325b1b8ab34Slling } 1326b1b8ab34Slling 132719397407SSherry Moore /* if not a number, just return the root dataset name */ 132819397407SSherry Moore if (str_to_uint64(slashp+1, &objnum)) { 132919397407SSherry Moore return (0); 133019397407SSherry Moore } 1331b1b8ab34Slling 1332b1b8ab34Slling *slashp = '\0'; 1333b1b8ab34Slling error = dsl_dsobj_to_dsname(bpath, objnum, outpath); 1334b1b8ab34Slling *slashp = '/'; 1335b1b8ab34Slling 1336b1b8ab34Slling return (error); 1337b1b8ab34Slling } 1338b1b8ab34Slling 13394201a95eSRic Aleshire /* 13404201a95eSRic Aleshire * zfs_check_global_label: 13414201a95eSRic Aleshire * Check that the hex label string is appropriate for the dataset 13424201a95eSRic Aleshire * being mounted into the global_zone proper. 13434201a95eSRic Aleshire * 13444201a95eSRic Aleshire * Return an error if the hex label string is not default or 13454201a95eSRic Aleshire * admin_low/admin_high. For admin_low labels, the corresponding 13464201a95eSRic Aleshire * dataset must be readonly. 13474201a95eSRic Aleshire */ 13484201a95eSRic Aleshire int 13494201a95eSRic Aleshire zfs_check_global_label(const char *dsname, const char *hexsl) 13504201a95eSRic Aleshire { 13514201a95eSRic Aleshire if (strcasecmp(hexsl, ZFS_MLSLABEL_DEFAULT) == 0) 13524201a95eSRic Aleshire return (0); 13534201a95eSRic Aleshire if (strcasecmp(hexsl, ADMIN_HIGH) == 0) 13544201a95eSRic Aleshire return (0); 13554201a95eSRic Aleshire if (strcasecmp(hexsl, ADMIN_LOW) == 0) { 13564201a95eSRic Aleshire /* must be readonly */ 13574201a95eSRic Aleshire uint64_t rdonly; 13584201a95eSRic Aleshire 13594201a95eSRic Aleshire if (dsl_prop_get_integer(dsname, 13604201a95eSRic Aleshire zfs_prop_to_name(ZFS_PROP_READONLY), &rdonly, NULL)) 13614201a95eSRic Aleshire return (EACCES); 13624201a95eSRic Aleshire return (rdonly ? 0 : EACCES); 13634201a95eSRic Aleshire } 13644201a95eSRic Aleshire return (EACCES); 13654201a95eSRic Aleshire } 13664201a95eSRic Aleshire 13674201a95eSRic Aleshire /* 13684201a95eSRic Aleshire * zfs_mount_label_policy: 13694201a95eSRic Aleshire * Determine whether the mount is allowed according to MAC check. 13704201a95eSRic Aleshire * by comparing (where appropriate) label of the dataset against 13714201a95eSRic Aleshire * the label of the zone being mounted into. If the dataset has 13724201a95eSRic Aleshire * no label, create one. 13734201a95eSRic Aleshire * 13744201a95eSRic Aleshire * Returns: 13754201a95eSRic Aleshire * 0 : access allowed 13764201a95eSRic Aleshire * >0 : error code, such as EACCES 13774201a95eSRic Aleshire */ 13784201a95eSRic Aleshire static int 13794201a95eSRic Aleshire zfs_mount_label_policy(vfs_t *vfsp, char *osname) 13804201a95eSRic Aleshire { 13814201a95eSRic Aleshire int error, retv; 13824201a95eSRic Aleshire zone_t *mntzone = NULL; 13834201a95eSRic Aleshire ts_label_t *mnt_tsl; 13844201a95eSRic Aleshire bslabel_t *mnt_sl; 13854201a95eSRic Aleshire bslabel_t ds_sl; 13864201a95eSRic Aleshire char ds_hexsl[MAXNAMELEN]; 13874201a95eSRic Aleshire 13884201a95eSRic Aleshire retv = EACCES; /* assume the worst */ 13894201a95eSRic Aleshire 13904201a95eSRic Aleshire /* 13914201a95eSRic Aleshire * Start by getting the dataset label if it exists. 13924201a95eSRic Aleshire */ 13934201a95eSRic Aleshire error = dsl_prop_get(osname, zfs_prop_to_name(ZFS_PROP_MLSLABEL), 13944201a95eSRic Aleshire 1, sizeof (ds_hexsl), &ds_hexsl, NULL); 13954201a95eSRic Aleshire if (error) 13964201a95eSRic Aleshire return (EACCES); 13974201a95eSRic Aleshire 13984201a95eSRic Aleshire /* 13994201a95eSRic Aleshire * If labeling is NOT enabled, then disallow the mount of datasets 14004201a95eSRic Aleshire * which have a non-default label already. No other label checks 14014201a95eSRic Aleshire * are needed. 14024201a95eSRic Aleshire */ 14034201a95eSRic Aleshire if (!is_system_labeled()) { 14044201a95eSRic Aleshire if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0) 14054201a95eSRic Aleshire return (0); 14064201a95eSRic Aleshire return (EACCES); 14074201a95eSRic Aleshire } 14084201a95eSRic Aleshire 14094201a95eSRic Aleshire /* 14104201a95eSRic Aleshire * Get the label of the mountpoint. If mounting into the global 14114201a95eSRic Aleshire * zone (i.e. mountpoint is not within an active zone and the 14124201a95eSRic Aleshire * zoned property is off), the label must be default or 14134201a95eSRic Aleshire * admin_low/admin_high only; no other checks are needed. 14144201a95eSRic Aleshire */ 14154201a95eSRic Aleshire mntzone = zone_find_by_any_path(refstr_value(vfsp->vfs_mntpt), B_FALSE); 14164201a95eSRic Aleshire if (mntzone->zone_id == GLOBAL_ZONEID) { 14174201a95eSRic Aleshire uint64_t zoned; 14184201a95eSRic Aleshire 14194201a95eSRic Aleshire zone_rele(mntzone); 14204201a95eSRic Aleshire 14214201a95eSRic Aleshire if (dsl_prop_get_integer(osname, 14224201a95eSRic Aleshire zfs_prop_to_name(ZFS_PROP_ZONED), &zoned, NULL)) 14234201a95eSRic Aleshire return (EACCES); 14244201a95eSRic Aleshire if (!zoned) 14254201a95eSRic Aleshire return (zfs_check_global_label(osname, ds_hexsl)); 14264201a95eSRic Aleshire else 14274201a95eSRic Aleshire /* 14284201a95eSRic Aleshire * This is the case of a zone dataset being mounted 14294201a95eSRic Aleshire * initially, before the zone has been fully created; 14304201a95eSRic Aleshire * allow this mount into global zone. 14314201a95eSRic Aleshire */ 14324201a95eSRic Aleshire return (0); 14334201a95eSRic Aleshire } 14344201a95eSRic Aleshire 14354201a95eSRic Aleshire mnt_tsl = mntzone->zone_slabel; 14364201a95eSRic Aleshire ASSERT(mnt_tsl != NULL); 14374201a95eSRic Aleshire label_hold(mnt_tsl); 14384201a95eSRic Aleshire mnt_sl = label2bslabel(mnt_tsl); 14394201a95eSRic Aleshire 14404201a95eSRic Aleshire if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0) { 14414201a95eSRic Aleshire /* 14424201a95eSRic Aleshire * The dataset doesn't have a real label, so fabricate one. 14434201a95eSRic Aleshire */ 14444201a95eSRic Aleshire char *str = NULL; 14454201a95eSRic Aleshire 14464201a95eSRic Aleshire if (l_to_str_internal(mnt_sl, &str) == 0 && 14474201a95eSRic Aleshire dsl_prop_set(osname, zfs_prop_to_name(ZFS_PROP_MLSLABEL), 144892241e0bSTom Erickson ZPROP_SRC_LOCAL, 1, strlen(str) + 1, str) == 0) 14494201a95eSRic Aleshire retv = 0; 14504201a95eSRic Aleshire if (str != NULL) 14514201a95eSRic Aleshire kmem_free(str, strlen(str) + 1); 14524201a95eSRic Aleshire } else if (hexstr_to_label(ds_hexsl, &ds_sl) == 0) { 14534201a95eSRic Aleshire /* 14544201a95eSRic Aleshire * Now compare labels to complete the MAC check. If the 14554201a95eSRic Aleshire * labels are equal then allow access. If the mountpoint 14564201a95eSRic Aleshire * label dominates the dataset label, allow readonly access. 14574201a95eSRic Aleshire * Otherwise, access is denied. 14584201a95eSRic Aleshire */ 14594201a95eSRic Aleshire if (blequal(mnt_sl, &ds_sl)) 14604201a95eSRic Aleshire retv = 0; 14614201a95eSRic Aleshire else if (bldominates(mnt_sl, &ds_sl)) { 14624201a95eSRic Aleshire vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0); 14634201a95eSRic Aleshire retv = 0; 14644201a95eSRic Aleshire } 14654201a95eSRic Aleshire } 14664201a95eSRic Aleshire 14674201a95eSRic Aleshire label_rele(mnt_tsl); 14684201a95eSRic Aleshire zone_rele(mntzone); 14694201a95eSRic Aleshire return (retv); 14704201a95eSRic Aleshire } 14714201a95eSRic Aleshire 1472ea8dc4b6Seschrock static int 1473ea8dc4b6Seschrock zfs_mountroot(vfs_t *vfsp, enum whymountroot why) 1474ea8dc4b6Seschrock { 1475ea8dc4b6Seschrock int error = 0; 1476ea8dc4b6Seschrock static int zfsrootdone = 0; 1477ea8dc4b6Seschrock zfsvfs_t *zfsvfs = NULL; 1478ea8dc4b6Seschrock znode_t *zp = NULL; 1479ea8dc4b6Seschrock vnode_t *vp = NULL; 1480e7cbe64fSgw char *zfs_bootfs; 1481051aabe6Staylor char *zfs_devid; 1482ea8dc4b6Seschrock 1483ea8dc4b6Seschrock ASSERT(vfsp); 1484ea8dc4b6Seschrock 1485ea8dc4b6Seschrock /* 1486b1b8ab34Slling * The filesystem that we mount as root is defined in the 1487e7cbe64fSgw * boot property "zfs-bootfs" with a format of 1488e7cbe64fSgw * "poolname/root-dataset-objnum". 1489ea8dc4b6Seschrock */ 1490ea8dc4b6Seschrock if (why == ROOT_INIT) { 1491ea8dc4b6Seschrock if (zfsrootdone++) 1492ea8dc4b6Seschrock return (EBUSY); 1493e7cbe64fSgw /* 1494e7cbe64fSgw * the process of doing a spa_load will require the 1495e7cbe64fSgw * clock to be set before we could (for example) do 1496e7cbe64fSgw * something better by looking at the timestamp on 1497e7cbe64fSgw * an uberblock, so just set it to -1. 1498e7cbe64fSgw */ 1499e7cbe64fSgw clkset(-1); 1500fa9e4066Sahrens 1501051aabe6Staylor if ((zfs_bootfs = spa_get_bootprop("zfs-bootfs")) == NULL) { 1502051aabe6Staylor cmn_err(CE_NOTE, "spa_get_bootfs: can not get " 1503051aabe6Staylor "bootfs name"); 1504e7cbe64fSgw return (EINVAL); 1505986fd29aSsetje } 1506051aabe6Staylor zfs_devid = spa_get_bootprop("diskdevid"); 1507051aabe6Staylor error = spa_import_rootpool(rootfs.bo_name, zfs_devid); 1508051aabe6Staylor if (zfs_devid) 1509051aabe6Staylor spa_free_bootprop(zfs_devid); 1510051aabe6Staylor if (error) { 1511051aabe6Staylor spa_free_bootprop(zfs_bootfs); 1512051aabe6Staylor cmn_err(CE_NOTE, "spa_import_rootpool: error %d", 1513e7cbe64fSgw error); 1514e7cbe64fSgw return (error); 1515e7cbe64fSgw } 1516e7cbe64fSgw if (error = zfs_parse_bootfs(zfs_bootfs, rootfs.bo_name)) { 1517051aabe6Staylor spa_free_bootprop(zfs_bootfs); 1518051aabe6Staylor cmn_err(CE_NOTE, "zfs_parse_bootfs: error %d", 1519e7cbe64fSgw error); 1520b1b8ab34Slling return (error); 1521e7cbe64fSgw } 1522e7cbe64fSgw 1523051aabe6Staylor spa_free_bootprop(zfs_bootfs); 1524fa9e4066Sahrens 1525ea8dc4b6Seschrock if (error = vfs_lock(vfsp)) 1526ea8dc4b6Seschrock return (error); 1527fa9e4066Sahrens 1528088f3894Sahrens if (error = zfs_domount(vfsp, rootfs.bo_name)) { 1529051aabe6Staylor cmn_err(CE_NOTE, "zfs_domount: error %d", error); 1530ea8dc4b6Seschrock goto out; 1531e7cbe64fSgw } 1532ea8dc4b6Seschrock 1533ea8dc4b6Seschrock zfsvfs = (zfsvfs_t *)vfsp->vfs_data; 1534ea8dc4b6Seschrock ASSERT(zfsvfs); 1535e7cbe64fSgw if (error = zfs_zget(zfsvfs, zfsvfs->z_root, &zp)) { 1536051aabe6Staylor cmn_err(CE_NOTE, "zfs_zget: error %d", error); 1537ea8dc4b6Seschrock goto out; 1538e7cbe64fSgw } 1539ea8dc4b6Seschrock 1540ea8dc4b6Seschrock vp = ZTOV(zp); 1541ea8dc4b6Seschrock mutex_enter(&vp->v_lock); 1542ea8dc4b6Seschrock vp->v_flag |= VROOT; 1543ea8dc4b6Seschrock mutex_exit(&vp->v_lock); 1544ea8dc4b6Seschrock rootvp = vp; 1545ea8dc4b6Seschrock 1546ea8dc4b6Seschrock /* 154740d3dfe1Smarks * Leave rootvp held. The root file system is never unmounted. 1548ea8dc4b6Seschrock */ 1549ea8dc4b6Seschrock 1550ea8dc4b6Seschrock vfs_add((struct vnode *)0, vfsp, 1551ea8dc4b6Seschrock (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0); 1552ea8dc4b6Seschrock out: 1553ea8dc4b6Seschrock vfs_unlock(vfsp); 1554e7cbe64fSgw return (error); 1555ea8dc4b6Seschrock } else if (why == ROOT_REMOUNT) { 1556ea8dc4b6Seschrock readonly_changed_cb(vfsp->vfs_data, B_FALSE); 1557ea8dc4b6Seschrock vfsp->vfs_flag |= VFS_REMOUNT; 1558b510d378Slling 1559b510d378Slling /* refresh mount options */ 1560b510d378Slling zfs_unregister_callbacks(vfsp->vfs_data); 1561b510d378Slling return (zfs_register_callbacks(vfsp)); 1562b510d378Slling 1563ea8dc4b6Seschrock } else if (why == ROOT_UNMOUNT) { 1564ea8dc4b6Seschrock zfs_unregister_callbacks((zfsvfs_t *)vfsp->vfs_data); 1565ea8dc4b6Seschrock (void) zfs_sync(vfsp, 0, 0); 1566ea8dc4b6Seschrock return (0); 1567ea8dc4b6Seschrock } 1568ea8dc4b6Seschrock 1569ea8dc4b6Seschrock /* 1570ea8dc4b6Seschrock * if "why" is equal to anything else other than ROOT_INIT, 1571ea8dc4b6Seschrock * ROOT_REMOUNT, or ROOT_UNMOUNT, we do not support it. 1572ea8dc4b6Seschrock */ 1573ea8dc4b6Seschrock return (ENOTSUP); 1574ea8dc4b6Seschrock } 1575ea8dc4b6Seschrock 1576ea8dc4b6Seschrock /*ARGSUSED*/ 1577ea8dc4b6Seschrock static int 1578ea8dc4b6Seschrock zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) 1579ea8dc4b6Seschrock { 1580ea8dc4b6Seschrock char *osname; 1581ea8dc4b6Seschrock pathname_t spn; 1582ea8dc4b6Seschrock int error = 0; 1583ea8dc4b6Seschrock uio_seg_t fromspace = (uap->flags & MS_SYSSPACE) ? 1584b1b8ab34Slling UIO_SYSSPACE : UIO_USERSPACE; 1585ea8dc4b6Seschrock int canwrite; 1586ea8dc4b6Seschrock 1587ea8dc4b6Seschrock if (mvp->v_type != VDIR) 1588ea8dc4b6Seschrock return (ENOTDIR); 1589ea8dc4b6Seschrock 1590ea8dc4b6Seschrock mutex_enter(&mvp->v_lock); 1591ea8dc4b6Seschrock if ((uap->flags & MS_REMOUNT) == 0 && 1592ea8dc4b6Seschrock (uap->flags & MS_OVERLAY) == 0 && 1593ea8dc4b6Seschrock (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { 1594ea8dc4b6Seschrock mutex_exit(&mvp->v_lock); 1595ea8dc4b6Seschrock return (EBUSY); 1596ea8dc4b6Seschrock } 1597ea8dc4b6Seschrock mutex_exit(&mvp->v_lock); 1598ea8dc4b6Seschrock 1599ea8dc4b6Seschrock /* 1600ea8dc4b6Seschrock * ZFS does not support passing unparsed data in via MS_DATA. 1601ea8dc4b6Seschrock * Users should use the MS_OPTIONSTR interface; this means 1602ea8dc4b6Seschrock * that all option parsing is already done and the options struct 1603ea8dc4b6Seschrock * can be interrogated. 1604ea8dc4b6Seschrock */ 1605ea8dc4b6Seschrock if ((uap->flags & MS_DATA) && uap->datalen > 0) 1606ea8dc4b6Seschrock return (EINVAL); 1607ea8dc4b6Seschrock 1608ea8dc4b6Seschrock /* 1609ea8dc4b6Seschrock * Get the objset name (the "special" mount argument). 1610ea8dc4b6Seschrock */ 1611ea8dc4b6Seschrock if (error = pn_get(uap->spec, fromspace, &spn)) 1612ea8dc4b6Seschrock return (error); 1613ea8dc4b6Seschrock 1614ea8dc4b6Seschrock osname = spn.pn_path; 1615ea8dc4b6Seschrock 1616ecd6cf80Smarks /* 1617ecd6cf80Smarks * Check for mount privilege? 1618ecd6cf80Smarks * 1619ecd6cf80Smarks * If we don't have privilege then see if 1620ecd6cf80Smarks * we have local permission to allow it 1621ecd6cf80Smarks */ 1622ecd6cf80Smarks error = secpolicy_fs_mount(cr, mvp, vfsp); 1623ecd6cf80Smarks if (error) { 162498679b56SMark Shellenbaum if (dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) == 0) { 1625ecd6cf80Smarks vattr_t vattr; 1626ecd6cf80Smarks 1627ecd6cf80Smarks /* 1628ecd6cf80Smarks * Make sure user is the owner of the mount point 1629ecd6cf80Smarks * or has sufficient privileges. 1630ecd6cf80Smarks */ 1631ecd6cf80Smarks 1632ecd6cf80Smarks vattr.va_mask = AT_UID; 1633ecd6cf80Smarks 163498679b56SMark Shellenbaum if (VOP_GETATTR(mvp, &vattr, 0, cr, NULL)) { 1635ecd6cf80Smarks goto out; 1636ecd6cf80Smarks } 1637ecd6cf80Smarks 16382459a9eaSmarks if (secpolicy_vnode_owner(cr, vattr.va_uid) != 0 && 16392459a9eaSmarks VOP_ACCESS(mvp, VWRITE, 0, cr, NULL) != 0) { 1640ecd6cf80Smarks goto out; 1641ecd6cf80Smarks } 1642ecd6cf80Smarks secpolicy_fs_mount_clearopts(cr, vfsp); 1643ecd6cf80Smarks } else { 1644ecd6cf80Smarks goto out; 1645ecd6cf80Smarks } 1646ecd6cf80Smarks } 1647ea8dc4b6Seschrock 1648ea8dc4b6Seschrock /* 1649ea8dc4b6Seschrock * Refuse to mount a filesystem if we are in a local zone and the 1650ea8dc4b6Seschrock * dataset is not visible. 1651ea8dc4b6Seschrock */ 1652ea8dc4b6Seschrock if (!INGLOBALZONE(curproc) && 1653ea8dc4b6Seschrock (!zone_dataset_visible(osname, &canwrite) || !canwrite)) { 1654ea8dc4b6Seschrock error = EPERM; 1655ea8dc4b6Seschrock goto out; 1656ea8dc4b6Seschrock } 1657ea8dc4b6Seschrock 16584201a95eSRic Aleshire error = zfs_mount_label_policy(vfsp, osname); 16594201a95eSRic Aleshire if (error) 16604201a95eSRic Aleshire goto out; 16614201a95eSRic Aleshire 1662b510d378Slling /* 1663b510d378Slling * When doing a remount, we simply refresh our temporary properties 1664b510d378Slling * according to those options set in the current VFS options. 1665b510d378Slling */ 1666b510d378Slling if (uap->flags & MS_REMOUNT) { 1667b510d378Slling /* refresh mount options */ 1668b510d378Slling zfs_unregister_callbacks(vfsp->vfs_data); 1669b510d378Slling error = zfs_register_callbacks(vfsp); 1670b510d378Slling goto out; 1671b510d378Slling } 1672b510d378Slling 1673088f3894Sahrens error = zfs_domount(vfsp, osname); 1674ea8dc4b6Seschrock 1675142ae85dSChris Kirby /* 1676142ae85dSChris Kirby * Add an extra VFS_HOLD on our parent vfs so that it can't 1677142ae85dSChris Kirby * disappear due to a forced unmount. 1678142ae85dSChris Kirby */ 1679984a131bSChris Kirby if (error == 0 && ((zfsvfs_t *)vfsp->vfs_data)->z_issnap) 1680142ae85dSChris Kirby VFS_HOLD(mvp->v_vfsp); 1681142ae85dSChris Kirby 1682ea8dc4b6Seschrock out: 1683fa9e4066Sahrens pn_free(&spn); 1684fa9e4066Sahrens return (error); 1685fa9e4066Sahrens } 1686fa9e4066Sahrens 1687fa9e4066Sahrens static int 1688fa9e4066Sahrens zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp) 1689fa9e4066Sahrens { 1690fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1691fa9e4066Sahrens dev32_t d32; 1692a2eea2e1Sahrens uint64_t refdbytes, availbytes, usedobjs, availobjs; 1693fa9e4066Sahrens 1694fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1695fa9e4066Sahrens 1696a2eea2e1Sahrens dmu_objset_space(zfsvfs->z_os, 1697a2eea2e1Sahrens &refdbytes, &availbytes, &usedobjs, &availobjs); 1698fa9e4066Sahrens 1699fa9e4066Sahrens /* 1700fa9e4066Sahrens * The underlying storage pool actually uses multiple block sizes. 1701fa9e4066Sahrens * We report the fragsize as the smallest block size we support, 1702fa9e4066Sahrens * and we report our blocksize as the filesystem's maximum blocksize. 1703fa9e4066Sahrens */ 1704fa9e4066Sahrens statp->f_frsize = 1UL << SPA_MINBLOCKSHIFT; 1705fa9e4066Sahrens statp->f_bsize = zfsvfs->z_max_blksz; 1706fa9e4066Sahrens 1707fa9e4066Sahrens /* 1708fa9e4066Sahrens * The following report "total" blocks of various kinds in the 1709fa9e4066Sahrens * file system, but reported in terms of f_frsize - the 1710fa9e4066Sahrens * "fragment" size. 1711fa9e4066Sahrens */ 1712fa9e4066Sahrens 1713a2eea2e1Sahrens statp->f_blocks = (refdbytes + availbytes) >> SPA_MINBLOCKSHIFT; 1714a2eea2e1Sahrens statp->f_bfree = availbytes >> SPA_MINBLOCKSHIFT; 1715fa9e4066Sahrens statp->f_bavail = statp->f_bfree; /* no root reservation */ 1716fa9e4066Sahrens 1717fa9e4066Sahrens /* 1718fa9e4066Sahrens * statvfs() should really be called statufs(), because it assumes 1719fa9e4066Sahrens * static metadata. ZFS doesn't preallocate files, so the best 1720fa9e4066Sahrens * we can do is report the max that could possibly fit in f_files, 1721fa9e4066Sahrens * and that minus the number actually used in f_ffree. 1722fa9e4066Sahrens * For f_ffree, report the smaller of the number of object available 1723fa9e4066Sahrens * and the number of blocks (each object will take at least a block). 1724fa9e4066Sahrens */ 1725a2eea2e1Sahrens statp->f_ffree = MIN(availobjs, statp->f_bfree); 1726fa9e4066Sahrens statp->f_favail = statp->f_ffree; /* no "root reservation" */ 1727a2eea2e1Sahrens statp->f_files = statp->f_ffree + usedobjs; 1728fa9e4066Sahrens 1729fa9e4066Sahrens (void) cmpldev(&d32, vfsp->vfs_dev); 1730fa9e4066Sahrens statp->f_fsid = d32; 1731fa9e4066Sahrens 1732fa9e4066Sahrens /* 1733fa9e4066Sahrens * We're a zfs filesystem. 1734fa9e4066Sahrens */ 1735fa9e4066Sahrens (void) strcpy(statp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 1736fa9e4066Sahrens 1737a5be7ebbSmarks statp->f_flag = vf_to_stf(vfsp->vfs_flag); 1738fa9e4066Sahrens 1739fa9e4066Sahrens statp->f_namemax = ZFS_MAXNAMELEN; 1740fa9e4066Sahrens 1741fa9e4066Sahrens /* 1742fa9e4066Sahrens * We have all of 32 characters to stuff a string here. 1743fa9e4066Sahrens * Is there anything useful we could/should provide? 1744fa9e4066Sahrens */ 1745fa9e4066Sahrens bzero(statp->f_fstr, sizeof (statp->f_fstr)); 1746fa9e4066Sahrens 1747fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1748fa9e4066Sahrens return (0); 1749fa9e4066Sahrens } 1750fa9e4066Sahrens 1751fa9e4066Sahrens static int 1752fa9e4066Sahrens zfs_root(vfs_t *vfsp, vnode_t **vpp) 1753fa9e4066Sahrens { 1754fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1755fa9e4066Sahrens znode_t *rootzp; 1756fa9e4066Sahrens int error; 1757fa9e4066Sahrens 1758fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1759fa9e4066Sahrens 1760fa9e4066Sahrens error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); 1761fa9e4066Sahrens if (error == 0) 1762fa9e4066Sahrens *vpp = ZTOV(rootzp); 1763fa9e4066Sahrens 1764fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1765fa9e4066Sahrens return (error); 1766fa9e4066Sahrens } 1767fa9e4066Sahrens 1768f18faf3fSek /* 1769f18faf3fSek * Teardown the zfsvfs::z_os. 1770f18faf3fSek * 1771f18faf3fSek * Note, if 'unmounting' if FALSE, we return with the 'z_teardown_lock' 1772f18faf3fSek * and 'z_teardown_inactive_lock' held. 1773f18faf3fSek */ 1774f18faf3fSek static int 1775f18faf3fSek zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting) 1776f18faf3fSek { 1777874395d5Smaybee znode_t *zp; 1778f18faf3fSek 1779f18faf3fSek rrw_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); 1780f18faf3fSek 1781f18faf3fSek if (!unmounting) { 1782f18faf3fSek /* 1783f18faf3fSek * We purge the parent filesystem's vfsp as the parent 1784f18faf3fSek * filesystem and all of its snapshots have their vnode's 1785f18faf3fSek * v_vfsp set to the parent's filesystem's vfsp. Note, 1786f18faf3fSek * 'z_parent' is self referential for non-snapshots. 1787f18faf3fSek */ 1788f18faf3fSek (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0); 1789f18faf3fSek } 1790f18faf3fSek 1791f18faf3fSek /* 1792f18faf3fSek * Close the zil. NB: Can't close the zil while zfs_inactive 1793f18faf3fSek * threads are blocked as zil_close can call zfs_inactive. 1794f18faf3fSek */ 1795f18faf3fSek if (zfsvfs->z_log) { 1796f18faf3fSek zil_close(zfsvfs->z_log); 1797f18faf3fSek zfsvfs->z_log = NULL; 1798f18faf3fSek } 1799f18faf3fSek 1800f18faf3fSek rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_WRITER); 1801f18faf3fSek 1802f18faf3fSek /* 1803f18faf3fSek * If we are not unmounting (ie: online recv) and someone already 1804f18faf3fSek * unmounted this file system while we were doing the switcheroo, 1805f18faf3fSek * or a reopen of z_os failed then just bail out now. 1806f18faf3fSek */ 1807f18faf3fSek if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) { 1808f18faf3fSek rw_exit(&zfsvfs->z_teardown_inactive_lock); 1809f18faf3fSek rrw_exit(&zfsvfs->z_teardown_lock, FTAG); 1810f18faf3fSek return (EIO); 1811f18faf3fSek } 1812f18faf3fSek 1813f18faf3fSek /* 1814f18faf3fSek * At this point there are no vops active, and any new vops will 1815f18faf3fSek * fail with EIO since we have z_teardown_lock for writer (only 1816f18faf3fSek * relavent for forced unmount). 1817f18faf3fSek * 1818f18faf3fSek * Release all holds on dbufs. 1819f18faf3fSek */ 1820f18faf3fSek mutex_enter(&zfsvfs->z_znodes_lock); 1821874395d5Smaybee for (zp = list_head(&zfsvfs->z_all_znodes); zp != NULL; 1822874395d5Smaybee zp = list_next(&zfsvfs->z_all_znodes, zp)) 18230a586ceaSMark Shellenbaum if (zp->z_sa_hdl) { 1824874395d5Smaybee ASSERT(ZTOV(zp)->v_count > 0); 1825874395d5Smaybee zfs_znode_dmu_fini(zp); 1826f18faf3fSek } 1827f18faf3fSek mutex_exit(&zfsvfs->z_znodes_lock); 1828f18faf3fSek 1829f18faf3fSek /* 1830f18faf3fSek * If we are unmounting, set the unmounted flag and let new vops 1831f18faf3fSek * unblock. zfs_inactive will have the unmounted behavior, and all 1832f18faf3fSek * other vops will fail with EIO. 1833f18faf3fSek */ 1834f18faf3fSek if (unmounting) { 1835f18faf3fSek zfsvfs->z_unmounted = B_TRUE; 1836f18faf3fSek rrw_exit(&zfsvfs->z_teardown_lock, FTAG); 1837f18faf3fSek rw_exit(&zfsvfs->z_teardown_inactive_lock); 1838f18faf3fSek } 1839f18faf3fSek 1840f18faf3fSek /* 1841f18faf3fSek * z_os will be NULL if there was an error in attempting to reopen 1842f18faf3fSek * zfsvfs, so just return as the properties had already been 1843f18faf3fSek * unregistered and cached data had been evicted before. 1844f18faf3fSek */ 1845f18faf3fSek if (zfsvfs->z_os == NULL) 1846f18faf3fSek return (0); 1847f18faf3fSek 1848f18faf3fSek /* 1849f18faf3fSek * Unregister properties. 1850f18faf3fSek */ 1851f18faf3fSek zfs_unregister_callbacks(zfsvfs); 1852f18faf3fSek 1853f18faf3fSek /* 1854f18faf3fSek * Evict cached data 1855f18faf3fSek */ 18562e2c1355SMatthew Ahrens if (dsl_dataset_is_dirty(dmu_objset_ds(zfsvfs->z_os)) && 18572e2c1355SMatthew Ahrens !(zfsvfs->z_vfs->vfs_flag & VFS_RDONLY)) 18582e2c1355SMatthew Ahrens txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0); 18595aaeed5cSSanjeev Bagewadi (void) dmu_objset_evict_dbufs(zfsvfs->z_os); 1860f18faf3fSek 1861f18faf3fSek return (0); 1862f18faf3fSek } 1863f18faf3fSek 1864fa9e4066Sahrens /*ARGSUSED*/ 1865fa9e4066Sahrens static int 1866fa9e4066Sahrens zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr) 1867fa9e4066Sahrens { 1868fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1869f18faf3fSek objset_t *os; 1870fa9e4066Sahrens int ret; 1871fa9e4066Sahrens 1872ecd6cf80Smarks ret = secpolicy_fs_unmount(cr, vfsp); 1873ecd6cf80Smarks if (ret) { 187498679b56SMark Shellenbaum if (dsl_deleg_access((char *)refstr_value(vfsp->vfs_resource), 187598679b56SMark Shellenbaum ZFS_DELEG_PERM_MOUNT, cr)) 1876ecd6cf80Smarks return (ret); 1877ecd6cf80Smarks } 1878033f9833Sek 1879ed097989Sek /* 1880ed097989Sek * We purge the parent filesystem's vfsp as the parent filesystem 1881ed097989Sek * and all of its snapshots have their vnode's v_vfsp set to the 1882ed097989Sek * parent's filesystem's vfsp. Note, 'z_parent' is self 1883ed097989Sek * referential for non-snapshots. 1884ed097989Sek */ 1885ed097989Sek (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0); 1886033f9833Sek 1887fa9e4066Sahrens /* 1888fa9e4066Sahrens * Unmount any snapshots mounted under .zfs before unmounting the 1889fa9e4066Sahrens * dataset itself. 1890fa9e4066Sahrens */ 1891fa9e4066Sahrens if (zfsvfs->z_ctldir != NULL && 1892ecd6cf80Smarks (ret = zfsctl_umount_snapshots(vfsp, fflag, cr)) != 0) { 1893fa9e4066Sahrens return (ret); 1894ecd6cf80Smarks } 1895fa9e4066Sahrens 189691ebeef5Sahrens if (!(fflag & MS_FORCE)) { 1897fa9e4066Sahrens /* 189891ebeef5Sahrens * Check the number of active vnodes in the file system. 189991ebeef5Sahrens * Our count is maintained in the vfs structure, but the 190091ebeef5Sahrens * number is off by 1 to indicate a hold on the vfs 190191ebeef5Sahrens * structure itself. 190291ebeef5Sahrens * 190391ebeef5Sahrens * The '.zfs' directory maintains a reference of its 190491ebeef5Sahrens * own, and any active references underneath are 190591ebeef5Sahrens * reflected in the vnode count. 1906fa9e4066Sahrens */ 190791ebeef5Sahrens if (zfsvfs->z_ctldir == NULL) { 190891ebeef5Sahrens if (vfsp->vfs_count > 1) 190991ebeef5Sahrens return (EBUSY); 191091ebeef5Sahrens } else { 191191ebeef5Sahrens if (vfsp->vfs_count > 2 || 1912f18faf3fSek zfsvfs->z_ctldir->v_count > 1) 191391ebeef5Sahrens return (EBUSY); 1914fa9e4066Sahrens } 191591ebeef5Sahrens } 1916fa9e4066Sahrens 191791ebeef5Sahrens vfsp->vfs_flag |= VFS_UNMOUNTED; 191891ebeef5Sahrens 1919f18faf3fSek VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0); 1920f18faf3fSek os = zfsvfs->z_os; 192191ebeef5Sahrens 192291ebeef5Sahrens /* 1923f18faf3fSek * z_os will be NULL if there was an error in 1924f18faf3fSek * attempting to reopen zfsvfs. 192591ebeef5Sahrens */ 1926f18faf3fSek if (os != NULL) { 1927f18faf3fSek /* 1928f18faf3fSek * Unset the objset user_ptr. 1929f18faf3fSek */ 1930503ad85cSMatthew Ahrens mutex_enter(&os->os_user_ptr_lock); 1931f18faf3fSek dmu_objset_set_user(os, NULL); 1932503ad85cSMatthew Ahrens mutex_exit(&os->os_user_ptr_lock); 193391ebeef5Sahrens 1934f18faf3fSek /* 1935745cd3c5Smaybee * Finally release the objset 1936f18faf3fSek */ 1937503ad85cSMatthew Ahrens dmu_objset_disown(os, zfsvfs); 193891ebeef5Sahrens } 193991ebeef5Sahrens 194091ebeef5Sahrens /* 194191ebeef5Sahrens * We can now safely destroy the '.zfs' directory node. 194291ebeef5Sahrens */ 194391ebeef5Sahrens if (zfsvfs->z_ctldir != NULL) 194491ebeef5Sahrens zfsctl_destroy(zfsvfs); 1945fa9e4066Sahrens 1946fa9e4066Sahrens return (0); 1947fa9e4066Sahrens } 1948fa9e4066Sahrens 1949fa9e4066Sahrens static int 1950fa9e4066Sahrens zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp) 1951fa9e4066Sahrens { 1952fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1953fa9e4066Sahrens znode_t *zp; 1954fa9e4066Sahrens uint64_t object = 0; 1955fa9e4066Sahrens uint64_t fid_gen = 0; 1956fa9e4066Sahrens uint64_t gen_mask; 1957fa9e4066Sahrens uint64_t zp_gen; 1958fa9e4066Sahrens int i, err; 1959fa9e4066Sahrens 1960fa9e4066Sahrens *vpp = NULL; 1961fa9e4066Sahrens 1962fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1963fa9e4066Sahrens 1964fa9e4066Sahrens if (fidp->fid_len == LONG_FID_LEN) { 1965fa9e4066Sahrens zfid_long_t *zlfid = (zfid_long_t *)fidp; 1966fa9e4066Sahrens uint64_t objsetid = 0; 1967fa9e4066Sahrens uint64_t setgen = 0; 1968fa9e4066Sahrens 1969fa9e4066Sahrens for (i = 0; i < sizeof (zlfid->zf_setid); i++) 1970fa9e4066Sahrens objsetid |= ((uint64_t)zlfid->zf_setid[i]) << (8 * i); 1971fa9e4066Sahrens 1972fa9e4066Sahrens for (i = 0; i < sizeof (zlfid->zf_setgen); i++) 1973fa9e4066Sahrens setgen |= ((uint64_t)zlfid->zf_setgen[i]) << (8 * i); 1974fa9e4066Sahrens 1975fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1976fa9e4066Sahrens 1977fa9e4066Sahrens err = zfsctl_lookup_objset(vfsp, objsetid, &zfsvfs); 1978fa9e4066Sahrens if (err) 1979fa9e4066Sahrens return (EINVAL); 1980fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1981fa9e4066Sahrens } 1982fa9e4066Sahrens 1983fa9e4066Sahrens if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) { 1984fa9e4066Sahrens zfid_short_t *zfid = (zfid_short_t *)fidp; 1985fa9e4066Sahrens 1986fa9e4066Sahrens for (i = 0; i < sizeof (zfid->zf_object); i++) 1987fa9e4066Sahrens object |= ((uint64_t)zfid->zf_object[i]) << (8 * i); 1988fa9e4066Sahrens 1989fa9e4066Sahrens for (i = 0; i < sizeof (zfid->zf_gen); i++) 1990fa9e4066Sahrens fid_gen |= ((uint64_t)zfid->zf_gen[i]) << (8 * i); 1991fa9e4066Sahrens } else { 1992fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1993fa9e4066Sahrens return (EINVAL); 1994fa9e4066Sahrens } 1995fa9e4066Sahrens 1996fa9e4066Sahrens /* A zero fid_gen means we are in the .zfs control directories */ 1997fa9e4066Sahrens if (fid_gen == 0 && 1998fa9e4066Sahrens (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) { 1999fa9e4066Sahrens *vpp = zfsvfs->z_ctldir; 2000fa9e4066Sahrens ASSERT(*vpp != NULL); 2001fa9e4066Sahrens if (object == ZFSCTL_INO_SNAPDIR) { 2002fa9e4066Sahrens VERIFY(zfsctl_root_lookup(*vpp, "snapshot", vpp, NULL, 2003da6c28aaSamw 0, NULL, NULL, NULL, NULL, NULL) == 0); 2004fa9e4066Sahrens } else { 2005fa9e4066Sahrens VN_HOLD(*vpp); 2006fa9e4066Sahrens } 2007fa9e4066Sahrens ZFS_EXIT(zfsvfs); 2008fa9e4066Sahrens return (0); 2009fa9e4066Sahrens } 2010fa9e4066Sahrens 2011fa9e4066Sahrens gen_mask = -1ULL >> (64 - 8 * i); 2012fa9e4066Sahrens 2013fa9e4066Sahrens dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask); 2014fa9e4066Sahrens if (err = zfs_zget(zfsvfs, object, &zp)) { 2015fa9e4066Sahrens ZFS_EXIT(zfsvfs); 2016fa9e4066Sahrens return (err); 2017fa9e4066Sahrens } 20180a586ceaSMark Shellenbaum (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &zp_gen, 20190a586ceaSMark Shellenbaum sizeof (uint64_t)); 20200a586ceaSMark Shellenbaum zp_gen = zp_gen & gen_mask; 2021fa9e4066Sahrens if (zp_gen == 0) 2022fa9e4066Sahrens zp_gen = 1; 2023893a6d32Sahrens if (zp->z_unlinked || zp_gen != fid_gen) { 2024fa9e4066Sahrens dprintf("znode gen (%u) != fid gen (%u)\n", zp_gen, fid_gen); 2025fa9e4066Sahrens VN_RELE(ZTOV(zp)); 2026fa9e4066Sahrens ZFS_EXIT(zfsvfs); 2027fa9e4066Sahrens return (EINVAL); 2028fa9e4066Sahrens } 2029fa9e4066Sahrens 2030fa9e4066Sahrens *vpp = ZTOV(zp); 2031fa9e4066Sahrens ZFS_EXIT(zfsvfs); 2032fa9e4066Sahrens return (0); 2033fa9e4066Sahrens } 2034fa9e4066Sahrens 2035f18faf3fSek /* 2036f18faf3fSek * Block out VOPs and close zfsvfs_t::z_os 2037f18faf3fSek * 2038f18faf3fSek * Note, if successful, then we return with the 'z_teardown_lock' and 2039f18faf3fSek * 'z_teardown_inactive_lock' write held. 2040f18faf3fSek */ 2041f18faf3fSek int 2042503ad85cSMatthew Ahrens zfs_suspend_fs(zfsvfs_t *zfsvfs) 2043f18faf3fSek { 2044f18faf3fSek int error; 2045f18faf3fSek 2046f18faf3fSek if ((error = zfsvfs_teardown(zfsvfs, B_FALSE)) != 0) 2047f18faf3fSek return (error); 2048503ad85cSMatthew Ahrens dmu_objset_disown(zfsvfs->z_os, zfsvfs); 2049f18faf3fSek 2050f18faf3fSek return (0); 2051f18faf3fSek } 2052f18faf3fSek 2053f18faf3fSek /* 2054f18faf3fSek * Reopen zfsvfs_t::z_os and release VOPs. 2055f18faf3fSek */ 2056f18faf3fSek int 2057503ad85cSMatthew Ahrens zfs_resume_fs(zfsvfs_t *zfsvfs, const char *osname) 2058f18faf3fSek { 205944bffe01SMark Shellenbaum int err; 2060f18faf3fSek 2061f18faf3fSek ASSERT(RRW_WRITE_HELD(&zfsvfs->z_teardown_lock)); 2062f18faf3fSek ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock)); 2063f18faf3fSek 2064503ad85cSMatthew Ahrens err = dmu_objset_own(osname, DMU_OST_ZFS, B_FALSE, zfsvfs, 2065503ad85cSMatthew Ahrens &zfsvfs->z_os); 2066f18faf3fSek if (err) { 2067f18faf3fSek zfsvfs->z_os = NULL; 2068f18faf3fSek } else { 2069f18faf3fSek znode_t *zp; 20700a586ceaSMark Shellenbaum uint64_t sa_obj = 0; 20710a586ceaSMark Shellenbaum 207244bffe01SMark Shellenbaum /* 207344bffe01SMark Shellenbaum * Make sure version hasn't changed 207444bffe01SMark Shellenbaum */ 207544bffe01SMark Shellenbaum 207644bffe01SMark Shellenbaum err = zfs_get_zplprop(zfsvfs->z_os, ZFS_PROP_VERSION, 207744bffe01SMark Shellenbaum &zfsvfs->z_version); 20780a586ceaSMark Shellenbaum 207944bffe01SMark Shellenbaum if (err) 20800a586ceaSMark Shellenbaum goto bail; 20810a586ceaSMark Shellenbaum 208244bffe01SMark Shellenbaum err = zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ, 208344bffe01SMark Shellenbaum ZFS_SA_ATTRS, 8, 1, &sa_obj); 208444bffe01SMark Shellenbaum 208544bffe01SMark Shellenbaum if (err && zfsvfs->z_version >= ZPL_VERSION_SA) 208644bffe01SMark Shellenbaum goto bail; 20870a586ceaSMark Shellenbaum 20881d8ccc7bSMark Shellenbaum if ((err = sa_setup(zfsvfs->z_os, sa_obj, 20891d8ccc7bSMark Shellenbaum zfs_attr_table, ZPL_END, &zfsvfs->z_attr_table)) != 0) 20901d8ccc7bSMark Shellenbaum goto bail; 2091f18faf3fSek 209244bffe01SMark Shellenbaum if (zfsvfs->z_version >= ZPL_VERSION_SA) 209344bffe01SMark Shellenbaum sa_register_update_callback(zfsvfs->z_os, 209444bffe01SMark Shellenbaum zfs_sa_upgrade); 209544bffe01SMark Shellenbaum 2096f18faf3fSek VERIFY(zfsvfs_setup(zfsvfs, B_FALSE) == 0); 2097f18faf3fSek 209844bffe01SMark Shellenbaum zfs_set_fuid_feature(zfsvfs); 209944bffe01SMark Shellenbaum 2100f18faf3fSek /* 2101f18faf3fSek * Attempt to re-establish all the active znodes with 2102f18faf3fSek * their dbufs. If a zfs_rezget() fails, then we'll let 2103f18faf3fSek * any potential callers discover that via ZFS_ENTER_VERIFY_VP 2104f18faf3fSek * when they try to use their znode. 2105f18faf3fSek */ 2106f18faf3fSek mutex_enter(&zfsvfs->z_znodes_lock); 2107f18faf3fSek for (zp = list_head(&zfsvfs->z_all_znodes); zp; 2108f18faf3fSek zp = list_next(&zfsvfs->z_all_znodes, zp)) { 2109f18faf3fSek (void) zfs_rezget(zp); 2110f18faf3fSek } 2111f18faf3fSek mutex_exit(&zfsvfs->z_znodes_lock); 2112f18faf3fSek } 2113f18faf3fSek 21140a586ceaSMark Shellenbaum bail: 2115f18faf3fSek /* release the VOPs */ 2116f18faf3fSek rw_exit(&zfsvfs->z_teardown_inactive_lock); 2117f18faf3fSek rrw_exit(&zfsvfs->z_teardown_lock, FTAG); 2118f18faf3fSek 2119f18faf3fSek if (err) { 2120f18faf3fSek /* 212144bffe01SMark Shellenbaum * Since we couldn't reopen zfsvfs::z_os, or 212244bffe01SMark Shellenbaum * setup the sa framework force unmount this file system. 2123f18faf3fSek */ 2124f18faf3fSek if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0) 2125f18faf3fSek (void) dounmount(zfsvfs->z_vfs, MS_FORCE, CRED()); 2126f18faf3fSek } 2127f18faf3fSek return (err); 2128f18faf3fSek } 2129f18faf3fSek 2130fa9e4066Sahrens static void 2131fa9e4066Sahrens zfs_freevfs(vfs_t *vfsp) 2132fa9e4066Sahrens { 2133fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 2134142ae85dSChris Kirby 2135142ae85dSChris Kirby /* 2136142ae85dSChris Kirby * If this is a snapshot, we have an extra VFS_HOLD on our parent 2137f80ce222SChris Kirby * from zfs_mount(). Release it here. If we came through 2138f80ce222SChris Kirby * zfs_mountroot() instead, we didn't grab an extra hold, so 2139f80ce222SChris Kirby * skip the VFS_RELE for rootvfs. 2140142ae85dSChris Kirby */ 2141f80ce222SChris Kirby if (zfsvfs->z_issnap && (vfsp != rootvfs)) 2142142ae85dSChris Kirby VFS_RELE(zfsvfs->z_parent->z_vfs); 2143142ae85dSChris Kirby 214414843421SMatthew Ahrens zfsvfs_free(zfsvfs); 2145fa9e4066Sahrens 2146fa9e4066Sahrens atomic_add_32(&zfs_active_fs_count, -1); 2147fa9e4066Sahrens } 2148fa9e4066Sahrens 2149fa9e4066Sahrens /* 2150fa9e4066Sahrens * VFS_INIT() initialization. Note that there is no VFS_FINI(), 2151fa9e4066Sahrens * so we can't safely do any non-idempotent initialization here. 2152fa9e4066Sahrens * Leave that to zfs_init() and zfs_fini(), which are called 2153fa9e4066Sahrens * from the module's _init() and _fini() entry points. 2154fa9e4066Sahrens */ 2155fa9e4066Sahrens /*ARGSUSED*/ 2156fa9e4066Sahrens static int 2157fa9e4066Sahrens zfs_vfsinit(int fstype, char *name) 2158fa9e4066Sahrens { 2159fa9e4066Sahrens int error; 2160fa9e4066Sahrens 2161fa9e4066Sahrens zfsfstype = fstype; 2162fa9e4066Sahrens 2163fa9e4066Sahrens /* 2164fa9e4066Sahrens * Setup vfsops and vnodeops tables. 2165fa9e4066Sahrens */ 2166fa9e4066Sahrens error = vfs_setfsops(fstype, zfs_vfsops_template, &zfs_vfsops); 2167fa9e4066Sahrens if (error != 0) { 2168fa9e4066Sahrens cmn_err(CE_WARN, "zfs: bad vfs ops template"); 2169fa9e4066Sahrens } 2170fa9e4066Sahrens 2171fa9e4066Sahrens error = zfs_create_op_tables(); 2172fa9e4066Sahrens if (error) { 2173fa9e4066Sahrens zfs_remove_op_tables(); 2174fa9e4066Sahrens cmn_err(CE_WARN, "zfs: bad vnode ops template"); 2175fa9e4066Sahrens (void) vfs_freevfsops_by_type(zfsfstype); 2176fa9e4066Sahrens return (error); 2177fa9e4066Sahrens } 2178fa9e4066Sahrens 2179fa9e4066Sahrens mutex_init(&zfs_dev_mtx, NULL, MUTEX_DEFAULT, NULL); 2180fa9e4066Sahrens 2181fa9e4066Sahrens /* 2182a0965f35Sbonwick * Unique major number for all zfs mounts. 2183a0965f35Sbonwick * If we run out of 32-bit minors, we'll getudev() another major. 2184fa9e4066Sahrens */ 2185a0965f35Sbonwick zfs_major = ddi_name_to_major(ZFS_DRIVER); 2186a0965f35Sbonwick zfs_minor = ZFS_MIN_MINOR; 2187fa9e4066Sahrens 2188fa9e4066Sahrens return (0); 2189fa9e4066Sahrens } 2190fa9e4066Sahrens 2191fa9e4066Sahrens void 2192fa9e4066Sahrens zfs_init(void) 2193fa9e4066Sahrens { 2194fa9e4066Sahrens /* 2195fa9e4066Sahrens * Initialize .zfs directory structures 2196fa9e4066Sahrens */ 2197fa9e4066Sahrens zfsctl_init(); 2198fa9e4066Sahrens 2199fa9e4066Sahrens /* 2200fa9e4066Sahrens * Initialize znode cache, vnode ops, etc... 2201fa9e4066Sahrens */ 2202fa9e4066Sahrens zfs_znode_init(); 220314843421SMatthew Ahrens 220414843421SMatthew Ahrens dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb); 2205fa9e4066Sahrens } 2206fa9e4066Sahrens 2207fa9e4066Sahrens void 2208fa9e4066Sahrens zfs_fini(void) 2209fa9e4066Sahrens { 2210fa9e4066Sahrens zfsctl_fini(); 2211fa9e4066Sahrens zfs_znode_fini(); 2212fa9e4066Sahrens } 2213fa9e4066Sahrens 2214fa9e4066Sahrens int 2215fa9e4066Sahrens zfs_busy(void) 2216fa9e4066Sahrens { 2217fa9e4066Sahrens return (zfs_active_fs_count != 0); 2218fa9e4066Sahrens } 2219fa9e4066Sahrens 2220e7437265Sahrens int 222114843421SMatthew Ahrens zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers) 2222e7437265Sahrens { 2223e7437265Sahrens int error; 222414843421SMatthew Ahrens objset_t *os = zfsvfs->z_os; 2225e7437265Sahrens dmu_tx_t *tx; 2226e7437265Sahrens 2227e7437265Sahrens if (newvers < ZPL_VERSION_INITIAL || newvers > ZPL_VERSION) 2228e7437265Sahrens return (EINVAL); 2229e7437265Sahrens 223014843421SMatthew Ahrens if (newvers < zfsvfs->z_version) 223114843421SMatthew Ahrens return (EINVAL); 2232e7437265Sahrens 22330a586ceaSMark Shellenbaum if (zfs_spa_version_map(newvers) > 22340a586ceaSMark Shellenbaum spa_version(dmu_objset_spa(zfsvfs->z_os))) 22350a586ceaSMark Shellenbaum return (ENOTSUP); 22360a586ceaSMark Shellenbaum 2237e7437265Sahrens tx = dmu_tx_create(os); 223814843421SMatthew Ahrens dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_FALSE, ZPL_VERSION_STR); 22390a586ceaSMark Shellenbaum if (newvers >= ZPL_VERSION_SA && !zfsvfs->z_use_sa) { 22400a586ceaSMark Shellenbaum dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE, 22410a586ceaSMark Shellenbaum ZFS_SA_ATTRS); 22420a586ceaSMark Shellenbaum dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL); 22430a586ceaSMark Shellenbaum } 2244e7437265Sahrens error = dmu_tx_assign(tx, TXG_WAIT); 2245e7437265Sahrens if (error) { 2246e7437265Sahrens dmu_tx_abort(tx); 224714843421SMatthew Ahrens return (error); 224814843421SMatthew Ahrens } 22490a586ceaSMark Shellenbaum 225014843421SMatthew Ahrens error = zap_update(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 225114843421SMatthew Ahrens 8, 1, &newvers, tx); 225214843421SMatthew Ahrens 225314843421SMatthew Ahrens if (error) { 225414843421SMatthew Ahrens dmu_tx_commit(tx); 225514843421SMatthew Ahrens return (error); 2256e7437265Sahrens } 2257e7437265Sahrens 22580a586ceaSMark Shellenbaum if (newvers >= ZPL_VERSION_SA && !zfsvfs->z_use_sa) { 22590a586ceaSMark Shellenbaum uint64_t sa_obj; 22600a586ceaSMark Shellenbaum 22610a586ceaSMark Shellenbaum ASSERT3U(spa_version(dmu_objset_spa(zfsvfs->z_os)), >=, 22620a586ceaSMark Shellenbaum SPA_VERSION_SA); 22630a586ceaSMark Shellenbaum sa_obj = zap_create(os, DMU_OT_SA_MASTER_NODE, 22640a586ceaSMark Shellenbaum DMU_OT_NONE, 0, tx); 22650a586ceaSMark Shellenbaum 22660a586ceaSMark Shellenbaum error = zap_add(os, MASTER_NODE_OBJ, 22670a586ceaSMark Shellenbaum ZFS_SA_ATTRS, 8, 1, &sa_obj, tx); 2268fb09f5aaSMadhav Suresh ASSERT0(error); 22690a586ceaSMark Shellenbaum 22700a586ceaSMark Shellenbaum VERIFY(0 == sa_set_sa_object(os, sa_obj)); 22710a586ceaSMark Shellenbaum sa_register_update_callback(os, zfs_sa_upgrade); 22720a586ceaSMark Shellenbaum } 22730a586ceaSMark Shellenbaum 22744445fffbSMatthew Ahrens spa_history_log_internal_ds(dmu_objset_ds(os), "upgrade", tx, 22754445fffbSMatthew Ahrens "from %llu to %llu", zfsvfs->z_version, newvers); 227614843421SMatthew Ahrens 2277e7437265Sahrens dmu_tx_commit(tx); 2278e7437265Sahrens 227914843421SMatthew Ahrens zfsvfs->z_version = newvers; 228014843421SMatthew Ahrens 228144bffe01SMark Shellenbaum zfs_set_fuid_feature(zfsvfs); 228214843421SMatthew Ahrens 228314843421SMatthew Ahrens return (0); 2284e7437265Sahrens } 2285e7437265Sahrens 2286de8267e0Stimh /* 2287de8267e0Stimh * Read a property stored within the master node. 2288de8267e0Stimh */ 2289de8267e0Stimh int 2290de8267e0Stimh zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value) 2291de8267e0Stimh { 2292de8267e0Stimh const char *pname; 22930a48a24eStimh int error = ENOENT; 2294de8267e0Stimh 2295de8267e0Stimh /* 2296de8267e0Stimh * Look up the file system's value for the property. For the 2297de8267e0Stimh * version property, we look up a slightly different string. 2298de8267e0Stimh */ 2299de8267e0Stimh if (prop == ZFS_PROP_VERSION) 2300de8267e0Stimh pname = ZPL_VERSION_STR; 2301de8267e0Stimh else 2302de8267e0Stimh pname = zfs_prop_to_name(prop); 2303de8267e0Stimh 23040a48a24eStimh if (os != NULL) 23050a48a24eStimh error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value); 2306de8267e0Stimh 2307aa60ed0eSmaybee if (error == ENOENT) { 2308de8267e0Stimh /* No value set, use the default value */ 2309de8267e0Stimh switch (prop) { 2310aa60ed0eSmaybee case ZFS_PROP_VERSION: 2311aa60ed0eSmaybee *value = ZPL_VERSION; 2312aa60ed0eSmaybee break; 2313de8267e0Stimh case ZFS_PROP_NORMALIZE: 2314de8267e0Stimh case ZFS_PROP_UTF8ONLY: 2315de8267e0Stimh *value = 0; 2316de8267e0Stimh break; 2317de8267e0Stimh case ZFS_PROP_CASE: 2318de8267e0Stimh *value = ZFS_CASE_SENSITIVE; 2319de8267e0Stimh break; 2320de8267e0Stimh default: 2321aa60ed0eSmaybee return (error); 2322de8267e0Stimh } 2323aa60ed0eSmaybee error = 0; 2324de8267e0Stimh } 2325aa60ed0eSmaybee return (error); 2326de8267e0Stimh } 2327de8267e0Stimh 2328fa9e4066Sahrens static vfsdef_t vfw = { 2329fa9e4066Sahrens VFSDEF_VERSION, 2330fa9e4066Sahrens MNTTYPE_ZFS, 2331fa9e4066Sahrens zfs_vfsinit, 2332da6c28aaSamw VSW_HASPROTO|VSW_CANRWRO|VSW_CANREMOUNT|VSW_VOLATILEDEV|VSW_STATS| 23330fbb751dSJohn Levon VSW_XID|VSW_ZMOUNT, 2334fa9e4066Sahrens &zfs_mntopts 2335fa9e4066Sahrens }; 2336fa9e4066Sahrens 2337fa9e4066Sahrens struct modlfs zfs_modlfs = { 2338e7437265Sahrens &mod_fsops, "ZFS filesystem version " SPA_VERSION_STRING, &vfw 2339fa9e4066Sahrens }; 2340