1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5033f9833Sek110237 * Common Development and Distribution License (the "License"). 6033f9833Sek110237 * 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. 2340a5c998SMatthew Ahrens * Copyright (c) 2012, 2015 by Delphix. All rights reserved. 24c3d26abcSMatthew Ahrens * Copyright (c) 2014 Integros [integros.com] 25fa9e4066Sahrens */ 26fa9e4066Sahrens 2755da60b9SMark J Musante /* Portions Copyright 2010 Robert Milkowski */ 2855da60b9SMark J Musante 29fa9e4066Sahrens #include <sys/types.h> 30fa9e4066Sahrens #include <sys/param.h> 31fa9e4066Sahrens #include <sys/systm.h> 32fa9e4066Sahrens #include <sys/sysmacros.h> 33fa9e4066Sahrens #include <sys/kmem.h> 34fa9e4066Sahrens #include <sys/pathname.h> 35fa9e4066Sahrens #include <sys/vnode.h> 36fa9e4066Sahrens #include <sys/vfs.h> 37aa59c4cbSrsb #include <sys/vfs_opreg.h> 38fa9e4066Sahrens #include <sys/mntent.h> 39fa9e4066Sahrens #include <sys/mount.h> 40fa9e4066Sahrens #include <sys/cmn_err.h> 41fa9e4066Sahrens #include "fs/fs_subr.h" 42fa9e4066Sahrens #include <sys/zfs_znode.h> 43893a6d32Sahrens #include <sys/zfs_dir.h> 44fa9e4066Sahrens #include <sys/zil.h> 45fa9e4066Sahrens #include <sys/fs/zfs.h> 46fa9e4066Sahrens #include <sys/dmu.h> 47fa9e4066Sahrens #include <sys/dsl_prop.h> 48b1b8ab34Slling #include <sys/dsl_dataset.h> 49ecd6cf80Smarks #include <sys/dsl_deleg.h> 50fa9e4066Sahrens #include <sys/spa.h> 51fa9e4066Sahrens #include <sys/zap.h> 520a586ceaSMark Shellenbaum #include <sys/sa.h> 53e828a46dSMatthew Ahrens #include <sys/sa_impl.h> 54fa9e4066Sahrens #include <sys/varargs.h> 55fa9e4066Sahrens #include <sys/policy.h> 56fa9e4066Sahrens #include <sys/atomic.h> 57fa9e4066Sahrens #include <sys/mkdev.h> 58fa9e4066Sahrens #include <sys/modctl.h> 59ecd6cf80Smarks #include <sys/refstr.h> 60fa9e4066Sahrens #include <sys/zfs_ioctl.h> 61fa9e4066Sahrens #include <sys/zfs_ctldir.h> 62da6c28aaSamw #include <sys/zfs_fuid.h> 63ea8dc4b6Seschrock #include <sys/bootconf.h> 64a0965f35Sbonwick #include <sys/sunddi.h> 65033f9833Sek110237 #include <sys/dnlc.h> 66f18faf3fSek110237 #include <sys/dmu_objset.h> 67e7cbe64fSgw25295 #include <sys/spa_boot.h> 68d78b796cSAndreas Jaekel #include <sys/zfs_events.h> 690a586ceaSMark Shellenbaum #include "zfs_comutil.h" 70fa9e4066Sahrens 71fa9e4066Sahrens int zfsfstype; 72fa9e4066Sahrens vfsops_t *zfs_vfsops = NULL; 73fa9e4066Sahrens static major_t zfs_major; 74fa9e4066Sahrens static minor_t zfs_minor; 75fa9e4066Sahrens static kmutex_t zfs_dev_mtx; 76fa9e4066Sahrens 7754d692b7SGeorge Wilson extern int sys_shutdown; 7854d692b7SGeorge Wilson 79fa9e4066Sahrens static int zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr); 80fa9e4066Sahrens static int zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr); 81ea8dc4b6Seschrock static int zfs_mountroot(vfs_t *vfsp, enum whymountroot); 82fa9e4066Sahrens static int zfs_root(vfs_t *vfsp, vnode_t **vpp); 83fa9e4066Sahrens static int zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp); 84fa9e4066Sahrens static int zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp); 85fa9e4066Sahrens static void zfs_freevfs(vfs_t *vfsp); 86fa9e4066Sahrens 87fa9e4066Sahrens static const fs_operation_def_t zfs_vfsops_template[] = { 88aa59c4cbSrsb VFSNAME_MOUNT, { .vfs_mount = zfs_mount }, 89aa59c4cbSrsb VFSNAME_MOUNTROOT, { .vfs_mountroot = zfs_mountroot }, 90aa59c4cbSrsb VFSNAME_UNMOUNT, { .vfs_unmount = zfs_umount }, 91aa59c4cbSrsb VFSNAME_ROOT, { .vfs_root = zfs_root }, 92aa59c4cbSrsb VFSNAME_STATVFS, { .vfs_statvfs = zfs_statvfs }, 93aa59c4cbSrsb VFSNAME_SYNC, { .vfs_sync = zfs_sync }, 94aa59c4cbSrsb VFSNAME_VGET, { .vfs_vget = zfs_vget }, 95aa59c4cbSrsb VFSNAME_FREEVFS, { .vfs_freevfs = zfs_freevfs }, 96fa9e4066Sahrens NULL, NULL 97fa9e4066Sahrens }; 98fa9e4066Sahrens 99fa9e4066Sahrens static const fs_operation_def_t zfs_vfsops_eio_template[] = { 100aa59c4cbSrsb VFSNAME_FREEVFS, { .vfs_freevfs = zfs_freevfs }, 101fa9e4066Sahrens NULL, NULL 102fa9e4066Sahrens }; 103fa9e4066Sahrens 104fa9e4066Sahrens /* 105fa9e4066Sahrens * We need to keep a count of active fs's. 106fa9e4066Sahrens * This is necessary to prevent our module 107fa9e4066Sahrens * from being unloaded after a umount -f 108fa9e4066Sahrens */ 109fa9e4066Sahrens static uint32_t zfs_active_fs_count = 0; 110fa9e4066Sahrens 111fa9e4066Sahrens static char *noatime_cancel[] = { MNTOPT_ATIME, NULL }; 112fa9e4066Sahrens static char *atime_cancel[] = { MNTOPT_NOATIME, NULL }; 1137b55fa8eSck153898 static char *noxattr_cancel[] = { MNTOPT_XATTR, NULL }; 1147b55fa8eSck153898 static char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL }; 115fa9e4066Sahrens 1167b55fa8eSck153898 /* 117b510d378Slling * MO_DEFAULT is not used since the default value is determined 118b510d378Slling * by the equivalent property. 1197b55fa8eSck153898 */ 120fa9e4066Sahrens static mntopt_t mntopts[] = { 1217b55fa8eSck153898 { MNTOPT_NOXATTR, noxattr_cancel, NULL, 0, NULL }, 1227b55fa8eSck153898 { MNTOPT_XATTR, xattr_cancel, NULL, 0, NULL }, 123b510d378Slling { MNTOPT_NOATIME, noatime_cancel, NULL, 0, NULL }, 124fa9e4066Sahrens { MNTOPT_ATIME, atime_cancel, NULL, 0, NULL } 125fa9e4066Sahrens }; 126fa9e4066Sahrens 127fa9e4066Sahrens static mntopts_t zfs_mntopts = { 128fa9e4066Sahrens sizeof (mntopts) / sizeof (mntopt_t), 129fa9e4066Sahrens mntopts 130fa9e4066Sahrens }; 131fa9e4066Sahrens 132fa9e4066Sahrens /*ARGSUSED*/ 133fa9e4066Sahrens int 134fa9e4066Sahrens zfs_sync(vfs_t *vfsp, short flag, cred_t *cr) 135fa9e4066Sahrens { 136fa9e4066Sahrens /* 137fa9e4066Sahrens * Data integrity is job one. We don't want a compromised kernel 138fa9e4066Sahrens * writing to the storage pool, so we never sync during panic. 139fa9e4066Sahrens */ 140fa9e4066Sahrens if (panicstr) 141fa9e4066Sahrens return (0); 142fa9e4066Sahrens 143fa9e4066Sahrens /* 144fa9e4066Sahrens * SYNC_ATTR is used by fsflush() to force old filesystems like UFS 145fa9e4066Sahrens * to sync metadata, which they would otherwise cache indefinitely. 146fa9e4066Sahrens * Semantically, the only requirement is that the sync be initiated. 147fa9e4066Sahrens * The DMU syncs out txgs frequently, so there's nothing to do. 148fa9e4066Sahrens */ 149fa9e4066Sahrens if (flag & SYNC_ATTR) 150fa9e4066Sahrens return (0); 151fa9e4066Sahrens 152fa9e4066Sahrens if (vfsp != NULL) { 153fa9e4066Sahrens /* 154fa9e4066Sahrens * Sync a specific filesystem. 155fa9e4066Sahrens */ 156fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 15754d692b7SGeorge Wilson dsl_pool_t *dp; 158fa9e4066Sahrens 159fa9e4066Sahrens ZFS_ENTER(zfsvfs); 16054d692b7SGeorge Wilson dp = dmu_objset_pool(zfsvfs->z_os); 16154d692b7SGeorge Wilson 16254d692b7SGeorge Wilson /* 16354d692b7SGeorge Wilson * If the system is shutting down, then skip any 16454d692b7SGeorge Wilson * filesystems which may exist on a suspended pool. 16554d692b7SGeorge Wilson */ 16654d692b7SGeorge Wilson if (sys_shutdown && spa_suspended(dp->dp_spa)) { 16754d692b7SGeorge Wilson ZFS_EXIT(zfsvfs); 16854d692b7SGeorge Wilson return (0); 16954d692b7SGeorge Wilson } 17054d692b7SGeorge Wilson 171fa9e4066Sahrens if (zfsvfs->z_log != NULL) 1725002558fSNeil Perrin zil_commit(zfsvfs->z_log, 0); 17355da60b9SMark J Musante 174fa9e4066Sahrens ZFS_EXIT(zfsvfs); 175fa9e4066Sahrens } else { 176fa9e4066Sahrens /* 177fa9e4066Sahrens * Sync all ZFS filesystems. This is what happens when you 178fa9e4066Sahrens * run sync(1M). Unlike other filesystems, ZFS honors the 179fa9e4066Sahrens * request by waiting for all pools to commit all dirty data. 180fa9e4066Sahrens */ 181fa9e4066Sahrens spa_sync_allpools(); 182fa9e4066Sahrens } 183fa9e4066Sahrens 184fa9e4066Sahrens return (0); 185fa9e4066Sahrens } 186fa9e4066Sahrens 187ea8dc4b6Seschrock static int 188ea8dc4b6Seschrock zfs_create_unique_device(dev_t *dev) 189ea8dc4b6Seschrock { 190ea8dc4b6Seschrock major_t new_major; 191ea8dc4b6Seschrock 192ea8dc4b6Seschrock do { 193ea8dc4b6Seschrock ASSERT3U(zfs_minor, <=, MAXMIN32); 194ea8dc4b6Seschrock minor_t start = zfs_minor; 195ea8dc4b6Seschrock do { 196ea8dc4b6Seschrock mutex_enter(&zfs_dev_mtx); 197ea8dc4b6Seschrock if (zfs_minor >= MAXMIN32) { 198ea8dc4b6Seschrock /* 199ea8dc4b6Seschrock * If we're still using the real major 200ea8dc4b6Seschrock * keep out of /dev/zfs and /dev/zvol minor 201ea8dc4b6Seschrock * number space. If we're using a getudev()'ed 202ea8dc4b6Seschrock * major number, we can use all of its minors. 203ea8dc4b6Seschrock */ 204ea8dc4b6Seschrock if (zfs_major == ddi_name_to_major(ZFS_DRIVER)) 205ea8dc4b6Seschrock zfs_minor = ZFS_MIN_MINOR; 206ea8dc4b6Seschrock else 207ea8dc4b6Seschrock zfs_minor = 0; 208ea8dc4b6Seschrock } else { 209ea8dc4b6Seschrock zfs_minor++; 210ea8dc4b6Seschrock } 211ea8dc4b6Seschrock *dev = makedevice(zfs_major, zfs_minor); 212ea8dc4b6Seschrock mutex_exit(&zfs_dev_mtx); 213ea8dc4b6Seschrock } while (vfs_devismounted(*dev) && zfs_minor != start); 214ea8dc4b6Seschrock if (zfs_minor == start) { 215ea8dc4b6Seschrock /* 216ea8dc4b6Seschrock * We are using all ~262,000 minor numbers for the 217ea8dc4b6Seschrock * current major number. Create a new major number. 218ea8dc4b6Seschrock */ 219ea8dc4b6Seschrock if ((new_major = getudev()) == (major_t)-1) { 220ea8dc4b6Seschrock cmn_err(CE_WARN, 221ea8dc4b6Seschrock "zfs_mount: Can't get unique major " 222ea8dc4b6Seschrock "device number."); 223ea8dc4b6Seschrock return (-1); 224ea8dc4b6Seschrock } 225ea8dc4b6Seschrock mutex_enter(&zfs_dev_mtx); 226ea8dc4b6Seschrock zfs_major = new_major; 227ea8dc4b6Seschrock zfs_minor = 0; 228ea8dc4b6Seschrock 229ea8dc4b6Seschrock mutex_exit(&zfs_dev_mtx); 230ea8dc4b6Seschrock } else { 231ea8dc4b6Seschrock break; 232ea8dc4b6Seschrock } 233ea8dc4b6Seschrock /* CONSTANTCONDITION */ 234ea8dc4b6Seschrock } while (1); 235ea8dc4b6Seschrock 236ea8dc4b6Seschrock return (0); 237ea8dc4b6Seschrock } 238ea8dc4b6Seschrock 239fa9e4066Sahrens static void 240fa9e4066Sahrens atime_changed_cb(void *arg, uint64_t newval) 241fa9e4066Sahrens { 242fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 243fa9e4066Sahrens 244fa9e4066Sahrens if (newval == TRUE) { 245fa9e4066Sahrens zfsvfs->z_atime = TRUE; 246fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME); 247fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_ATIME, NULL, 0); 248fa9e4066Sahrens } else { 249fa9e4066Sahrens zfsvfs->z_atime = FALSE; 250fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_ATIME); 251fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME, NULL, 0); 252fa9e4066Sahrens } 253fa9e4066Sahrens } 254fa9e4066Sahrens 255fa9e4066Sahrens static void 2567b55fa8eSck153898 xattr_changed_cb(void *arg, uint64_t newval) 2577b55fa8eSck153898 { 2587b55fa8eSck153898 zfsvfs_t *zfsvfs = arg; 2597b55fa8eSck153898 2607b55fa8eSck153898 if (newval == TRUE) { 2617b55fa8eSck153898 /* XXX locking on vfs_flag? */ 2627b55fa8eSck153898 zfsvfs->z_vfs->vfs_flag |= VFS_XATTR; 2637b55fa8eSck153898 vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR); 2647b55fa8eSck153898 vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_XATTR, NULL, 0); 2657b55fa8eSck153898 } else { 2667b55fa8eSck153898 /* XXX locking on vfs_flag? */ 2677b55fa8eSck153898 zfsvfs->z_vfs->vfs_flag &= ~VFS_XATTR; 2687b55fa8eSck153898 vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_XATTR); 2697b55fa8eSck153898 vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR, NULL, 0); 2707b55fa8eSck153898 } 2717b55fa8eSck153898 } 2727b55fa8eSck153898 2737b55fa8eSck153898 static void 274fa9e4066Sahrens blksz_changed_cb(void *arg, uint64_t newval) 275fa9e4066Sahrens { 276fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 277b5152584SMatthew Ahrens ASSERT3U(newval, <=, spa_maxblocksize(dmu_objset_spa(zfsvfs->z_os))); 278b5152584SMatthew Ahrens ASSERT3U(newval, >=, SPA_MINBLOCKSIZE); 279b5152584SMatthew Ahrens ASSERT(ISP2(newval)); 280fa9e4066Sahrens 281fa9e4066Sahrens zfsvfs->z_max_blksz = newval; 282fa9e4066Sahrens zfsvfs->z_vfs->vfs_bsize = newval; 283fa9e4066Sahrens } 284fa9e4066Sahrens 285fa9e4066Sahrens static void 286fa9e4066Sahrens readonly_changed_cb(void *arg, uint64_t newval) 287fa9e4066Sahrens { 288fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 289fa9e4066Sahrens 290fa9e4066Sahrens if (newval) { 291fa9e4066Sahrens /* XXX locking on vfs_flag? */ 292fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY; 293fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RW); 294fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RO, NULL, 0); 295fa9e4066Sahrens } else { 296fa9e4066Sahrens /* XXX locking on vfs_flag? */ 297fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 298fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RO); 299fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RW, NULL, 0); 300fa9e4066Sahrens } 301fa9e4066Sahrens } 302fa9e4066Sahrens 303fa9e4066Sahrens static void 304fa9e4066Sahrens devices_changed_cb(void *arg, uint64_t newval) 305fa9e4066Sahrens { 306fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 307fa9e4066Sahrens 308fa9e4066Sahrens if (newval == FALSE) { 309fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NODEVICES; 310fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES); 311fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES, NULL, 0); 312fa9e4066Sahrens } else { 313fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NODEVICES; 314fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES); 315fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES, NULL, 0); 316fa9e4066Sahrens } 317fa9e4066Sahrens } 318fa9e4066Sahrens 319fa9e4066Sahrens static void 320fa9e4066Sahrens setuid_changed_cb(void *arg, uint64_t newval) 321fa9e4066Sahrens { 322fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 323fa9e4066Sahrens 324fa9e4066Sahrens if (newval == FALSE) { 325fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NOSETUID; 326fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_SETUID); 327fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID, NULL, 0); 328fa9e4066Sahrens } else { 329fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NOSETUID; 330fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID); 331fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_SETUID, NULL, 0); 332fa9e4066Sahrens } 333fa9e4066Sahrens } 334fa9e4066Sahrens 335fa9e4066Sahrens static void 336fa9e4066Sahrens exec_changed_cb(void *arg, uint64_t newval) 337fa9e4066Sahrens { 338fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 339fa9e4066Sahrens 340fa9e4066Sahrens if (newval == FALSE) { 341fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NOEXEC; 342fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_EXEC); 343fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC, NULL, 0); 344fa9e4066Sahrens } else { 345fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NOEXEC; 346fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC); 347fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_EXEC, NULL, 0); 348fa9e4066Sahrens } 349fa9e4066Sahrens } 350fa9e4066Sahrens 351*1a4cea1bSArne Jansen static void 352*1a4cea1bSArne Jansen follow_changed_cb(void *arg, uint64_t newval) 353*1a4cea1bSArne Jansen { 354*1a4cea1bSArne Jansen zfsvfs_t *zfsvfs = arg; 355*1a4cea1bSArne Jansen 356*1a4cea1bSArne Jansen if (newval == FALSE) { 357*1a4cea1bSArne Jansen zfsvfs->z_vfs->vfs_flag |= VFS_NOFOLLOW; 358*1a4cea1bSArne Jansen vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_FOLLOW); 359*1a4cea1bSArne Jansen vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOFOLLOW, NULL, 0); 360*1a4cea1bSArne Jansen } else { 361*1a4cea1bSArne Jansen zfsvfs->z_vfs->vfs_flag &= ~VFS_NOFOLLOW; 362*1a4cea1bSArne Jansen vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOFOLLOW); 363*1a4cea1bSArne Jansen vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_FOLLOW, NULL, 0); 364*1a4cea1bSArne Jansen } 365*1a4cea1bSArne Jansen } 366*1a4cea1bSArne Jansen 367da6c28aaSamw /* 368da6c28aaSamw * The nbmand mount option can be changed at mount time. 369da6c28aaSamw * We can't allow it to be toggled on live file systems or incorrect 370da6c28aaSamw * behavior may be seen from cifs clients 371da6c28aaSamw * 372da6c28aaSamw * This property isn't registered via dsl_prop_register(), but this callback 373da6c28aaSamw * will be called when a file system is first mounted 374da6c28aaSamw */ 375da6c28aaSamw static void 376da6c28aaSamw nbmand_changed_cb(void *arg, uint64_t newval) 377da6c28aaSamw { 378da6c28aaSamw zfsvfs_t *zfsvfs = arg; 379da6c28aaSamw if (newval == FALSE) { 380da6c28aaSamw vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND); 381da6c28aaSamw vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND, NULL, 0); 382da6c28aaSamw } else { 383da6c28aaSamw vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND); 384da6c28aaSamw vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND, NULL, 0); 385da6c28aaSamw } 386da6c28aaSamw } 387da6c28aaSamw 388fa9e4066Sahrens static void 389fa9e4066Sahrens snapdir_changed_cb(void *arg, uint64_t newval) 390fa9e4066Sahrens { 391fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 392fa9e4066Sahrens 393fa9e4066Sahrens zfsvfs->z_show_ctldir = newval; 394fa9e4066Sahrens } 395fa9e4066Sahrens 396fa9e4066Sahrens static void 397da6c28aaSamw vscan_changed_cb(void *arg, uint64_t newval) 398da6c28aaSamw { 399da6c28aaSamw zfsvfs_t *zfsvfs = arg; 400da6c28aaSamw 401da6c28aaSamw zfsvfs->z_vscan = newval; 402da6c28aaSamw } 403da6c28aaSamw 404da6c28aaSamw static void 405a3c49ce1SAlbert Lee acl_mode_changed_cb(void *arg, uint64_t newval) 406a3c49ce1SAlbert Lee { 407a3c49ce1SAlbert Lee zfsvfs_t *zfsvfs = arg; 408a3c49ce1SAlbert Lee 409a3c49ce1SAlbert Lee zfsvfs->z_acl_mode = newval; 410a3c49ce1SAlbert Lee } 411a3c49ce1SAlbert Lee 412a3c49ce1SAlbert Lee static void 413fa9e4066Sahrens acl_inherit_changed_cb(void *arg, uint64_t newval) 414fa9e4066Sahrens { 415fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 416fa9e4066Sahrens 417fa9e4066Sahrens zfsvfs->z_acl_inherit = newval; 418fa9e4066Sahrens } 419fa9e4066Sahrens 420fa9e4066Sahrens static int 421ea8dc4b6Seschrock zfs_register_callbacks(vfs_t *vfsp) 422ea8dc4b6Seschrock { 423ea8dc4b6Seschrock struct dsl_dataset *ds = NULL; 424ea8dc4b6Seschrock objset_t *os = NULL; 425ea8dc4b6Seschrock zfsvfs_t *zfsvfs = NULL; 426da6c28aaSamw uint64_t nbmand; 427d5285caeSGeorge Wilson boolean_t readonly = B_FALSE; 428d5285caeSGeorge Wilson boolean_t do_readonly = B_FALSE; 429d5285caeSGeorge Wilson boolean_t setuid = B_FALSE; 430d5285caeSGeorge Wilson boolean_t do_setuid = B_FALSE; 431d5285caeSGeorge Wilson boolean_t exec = B_FALSE; 432d5285caeSGeorge Wilson boolean_t do_exec = B_FALSE; 433*1a4cea1bSArne Jansen boolean_t follow = B_FALSE; 434*1a4cea1bSArne Jansen boolean_t do_follow = B_FALSE; 435d5285caeSGeorge Wilson boolean_t devices = B_FALSE; 436d5285caeSGeorge Wilson boolean_t do_devices = B_FALSE; 437d5285caeSGeorge Wilson boolean_t xattr = B_FALSE; 438d5285caeSGeorge Wilson boolean_t do_xattr = B_FALSE; 439d5285caeSGeorge Wilson boolean_t atime = B_FALSE; 440d5285caeSGeorge Wilson boolean_t do_atime = B_FALSE; 441ea8dc4b6Seschrock int error = 0; 442fa9e4066Sahrens 443ea8dc4b6Seschrock ASSERT(vfsp); 444ea8dc4b6Seschrock zfsvfs = vfsp->vfs_data; 445ea8dc4b6Seschrock ASSERT(zfsvfs); 446ea8dc4b6Seschrock os = zfsvfs->z_os; 447fa9e4066Sahrens 448fa9e4066Sahrens /* 449fa9e4066Sahrens * The act of registering our callbacks will destroy any mount 450fa9e4066Sahrens * options we may have. In order to enable temporary overrides 4517b55fa8eSck153898 * of mount options, we stash away the current values and 452fa9e4066Sahrens * restore them after we register the callbacks. 453fa9e4066Sahrens */ 454f9af39baSGeorge Wilson if (vfs_optionisset(vfsp, MNTOPT_RO, NULL) || 455f9af39baSGeorge Wilson !spa_writeable(dmu_objset_spa(os))) { 456fa9e4066Sahrens readonly = B_TRUE; 457fa9e4066Sahrens do_readonly = B_TRUE; 458fa9e4066Sahrens } else if (vfs_optionisset(vfsp, MNTOPT_RW, NULL)) { 459fa9e4066Sahrens readonly = B_FALSE; 460fa9e4066Sahrens do_readonly = B_TRUE; 461fa9e4066Sahrens } 462fa9e4066Sahrens if (vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL)) { 463fa9e4066Sahrens devices = B_FALSE; 464fa9e4066Sahrens setuid = B_FALSE; 465fa9e4066Sahrens do_devices = B_TRUE; 466fa9e4066Sahrens do_setuid = B_TRUE; 467fa9e4066Sahrens } else { 468fa9e4066Sahrens if (vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL)) { 469fa9e4066Sahrens devices = B_FALSE; 470fa9e4066Sahrens do_devices = B_TRUE; 471b1b8ab34Slling } else if (vfs_optionisset(vfsp, MNTOPT_DEVICES, NULL)) { 472fa9e4066Sahrens devices = B_TRUE; 473fa9e4066Sahrens do_devices = B_TRUE; 474fa9e4066Sahrens } 475fa9e4066Sahrens 476fa9e4066Sahrens if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) { 477fa9e4066Sahrens setuid = B_FALSE; 478fa9e4066Sahrens do_setuid = B_TRUE; 479fa9e4066Sahrens } else if (vfs_optionisset(vfsp, MNTOPT_SETUID, NULL)) { 480fa9e4066Sahrens setuid = B_TRUE; 481fa9e4066Sahrens do_setuid = B_TRUE; 482fa9e4066Sahrens } 483fa9e4066Sahrens } 484fa9e4066Sahrens if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) { 485fa9e4066Sahrens exec = B_FALSE; 486fa9e4066Sahrens do_exec = B_TRUE; 487fa9e4066Sahrens } else if (vfs_optionisset(vfsp, MNTOPT_EXEC, NULL)) { 488fa9e4066Sahrens exec = B_TRUE; 489fa9e4066Sahrens do_exec = B_TRUE; 490fa9e4066Sahrens } 491*1a4cea1bSArne Jansen if (vfs_optionisset(vfsp, MNTOPT_NOFOLLOW, NULL)) { 492*1a4cea1bSArne Jansen follow = B_FALSE; 493*1a4cea1bSArne Jansen do_follow = B_TRUE; 494*1a4cea1bSArne Jansen } else if (vfs_optionisset(vfsp, MNTOPT_FOLLOW, NULL)) { 495*1a4cea1bSArne Jansen follow = B_TRUE; 496*1a4cea1bSArne Jansen do_follow = B_TRUE; 497*1a4cea1bSArne Jansen } 4987b55fa8eSck153898 if (vfs_optionisset(vfsp, MNTOPT_NOXATTR, NULL)) { 4997b55fa8eSck153898 xattr = B_FALSE; 5007b55fa8eSck153898 do_xattr = B_TRUE; 5017b55fa8eSck153898 } else if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) { 5027b55fa8eSck153898 xattr = B_TRUE; 5037b55fa8eSck153898 do_xattr = B_TRUE; 5047b55fa8eSck153898 } 505b510d378Slling if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) { 506b510d378Slling atime = B_FALSE; 507b510d378Slling do_atime = B_TRUE; 508b510d378Slling } else if (vfs_optionisset(vfsp, MNTOPT_ATIME, NULL)) { 509b510d378Slling atime = B_TRUE; 510b510d378Slling do_atime = B_TRUE; 511b510d378Slling } 512fa9e4066Sahrens 513fa9e4066Sahrens /* 514da6c28aaSamw * nbmand is a special property. It can only be changed at 515da6c28aaSamw * mount time. 516da6c28aaSamw * 517da6c28aaSamw * This is weird, but it is documented to only be changeable 518da6c28aaSamw * at mount time. 519da6c28aaSamw */ 520da6c28aaSamw if (vfs_optionisset(vfsp, MNTOPT_NONBMAND, NULL)) { 521da6c28aaSamw nbmand = B_FALSE; 522da6c28aaSamw } else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) { 523da6c28aaSamw nbmand = B_TRUE; 524da6c28aaSamw } else { 52540a5c998SMatthew Ahrens char osname[ZFS_MAX_DATASET_NAME_LEN]; 526da6c28aaSamw 527da6c28aaSamw dmu_objset_name(os, osname); 528da6c28aaSamw if (error = dsl_prop_get_integer(osname, "nbmand", &nbmand, 529bb0ade09Sahrens NULL)) { 530da6c28aaSamw return (error); 531da6c28aaSamw } 532bb0ade09Sahrens } 533da6c28aaSamw 534da6c28aaSamw /* 535fa9e4066Sahrens * Register property callbacks. 536ea8dc4b6Seschrock * 537ea8dc4b6Seschrock * It would probably be fine to just check for i/o error from 538ea8dc4b6Seschrock * the first prop_register(), but I guess I like to go 539ea8dc4b6Seschrock * overboard... 540fa9e4066Sahrens */ 541fa9e4066Sahrens ds = dmu_objset_ds(os); 5423b2aab18SMatthew Ahrens dsl_pool_config_enter(dmu_objset_pool(os), FTAG); 5433b2aab18SMatthew Ahrens error = dsl_prop_register(ds, 5443b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_ATIME), atime_changed_cb, zfsvfs); 545ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 5463b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_XATTR), xattr_changed_cb, zfsvfs); 5477b55fa8eSck153898 error = error ? error : dsl_prop_register(ds, 5483b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_RECORDSIZE), blksz_changed_cb, zfsvfs); 549ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 5503b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_READONLY), readonly_changed_cb, zfsvfs); 551ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 5523b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_DEVICES), devices_changed_cb, zfsvfs); 553ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 5543b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_SETUID), setuid_changed_cb, zfsvfs); 555ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 5563b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_EXEC), exec_changed_cb, zfsvfs); 557ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 558*1a4cea1bSArne Jansen zfs_prop_to_name(ZFS_PROP_FOLLOW), follow_changed_cb, zfsvfs); 559*1a4cea1bSArne Jansen error = error ? error : dsl_prop_register(ds, 5603b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_SNAPDIR), snapdir_changed_cb, zfsvfs); 561ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 5623b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_ACLMODE), acl_mode_changed_cb, zfsvfs); 563a3c49ce1SAlbert Lee error = error ? error : dsl_prop_register(ds, 5643b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_ACLINHERIT), acl_inherit_changed_cb, 5653b2aab18SMatthew Ahrens zfsvfs); 566da6c28aaSamw error = error ? error : dsl_prop_register(ds, 5673b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_VSCAN), vscan_changed_cb, zfsvfs); 5683b2aab18SMatthew Ahrens dsl_pool_config_exit(dmu_objset_pool(os), FTAG); 569ea8dc4b6Seschrock if (error) 570ea8dc4b6Seschrock goto unregister; 571fa9e4066Sahrens 572fa9e4066Sahrens /* 573fa9e4066Sahrens * Invoke our callbacks to restore temporary mount options. 574fa9e4066Sahrens */ 575fa9e4066Sahrens if (do_readonly) 576fa9e4066Sahrens readonly_changed_cb(zfsvfs, readonly); 577fa9e4066Sahrens if (do_setuid) 578fa9e4066Sahrens setuid_changed_cb(zfsvfs, setuid); 579fa9e4066Sahrens if (do_exec) 580fa9e4066Sahrens exec_changed_cb(zfsvfs, exec); 581*1a4cea1bSArne Jansen if (do_follow) 582*1a4cea1bSArne Jansen follow_changed_cb(zfsvfs, follow); 583fa9e4066Sahrens if (do_devices) 584fa9e4066Sahrens devices_changed_cb(zfsvfs, devices); 5857b55fa8eSck153898 if (do_xattr) 5867b55fa8eSck153898 xattr_changed_cb(zfsvfs, xattr); 587b510d378Slling if (do_atime) 588b510d378Slling atime_changed_cb(zfsvfs, atime); 589ea8dc4b6Seschrock 590da6c28aaSamw nbmand_changed_cb(zfsvfs, nbmand); 591da6c28aaSamw 592ea8dc4b6Seschrock return (0); 593ea8dc4b6Seschrock 594ea8dc4b6Seschrock unregister: 59503bad06fSJustin Gibbs dsl_prop_unregister_all(ds, zfsvfs); 596ea8dc4b6Seschrock return (error); 597fa9e4066Sahrens } 598fa9e4066Sahrens 5999966ca11SMatthew Ahrens static int 6000a586ceaSMark Shellenbaum zfs_space_delta_cb(dmu_object_type_t bonustype, void *data, 6019966ca11SMatthew Ahrens uint64_t *userp, uint64_t *groupp) 60214843421SMatthew Ahrens { 60306e0070dSMark Shellenbaum /* 60406e0070dSMark Shellenbaum * Is it a valid type of object to track? 60506e0070dSMark Shellenbaum */ 6060a586ceaSMark Shellenbaum if (bonustype != DMU_OT_ZNODE && bonustype != DMU_OT_SA) 607be6fd75aSMatthew Ahrens return (SET_ERROR(ENOENT)); 60814843421SMatthew Ahrens 60906e0070dSMark Shellenbaum /* 61006e0070dSMark Shellenbaum * If we have a NULL data pointer 61106e0070dSMark Shellenbaum * then assume the id's aren't changing and 61206e0070dSMark Shellenbaum * return EEXIST to the dmu to let it know to 61306e0070dSMark Shellenbaum * use the same ids 61406e0070dSMark Shellenbaum */ 61506e0070dSMark Shellenbaum if (data == NULL) 616be6fd75aSMatthew Ahrens return (SET_ERROR(EEXIST)); 61706e0070dSMark Shellenbaum 6180a586ceaSMark Shellenbaum if (bonustype == DMU_OT_ZNODE) { 619e828a46dSMatthew Ahrens znode_phys_t *znp = data; 6209966ca11SMatthew Ahrens *userp = znp->zp_uid; 6219966ca11SMatthew Ahrens *groupp = znp->zp_gid; 6220a586ceaSMark Shellenbaum } else { 6230a586ceaSMark Shellenbaum int hdrsize; 624e828a46dSMatthew Ahrens sa_hdr_phys_t *sap = data; 625e828a46dSMatthew Ahrens sa_hdr_phys_t sa = *sap; 626e828a46dSMatthew Ahrens boolean_t swap = B_FALSE; 6270a586ceaSMark Shellenbaum 6280a586ceaSMark Shellenbaum ASSERT(bonustype == DMU_OT_SA); 6290a586ceaSMark Shellenbaum 630e828a46dSMatthew Ahrens if (sa.sa_magic == 0) { 63106e0070dSMark Shellenbaum /* 63206e0070dSMark Shellenbaum * This should only happen for newly created 63306e0070dSMark Shellenbaum * files that haven't had the znode data filled 63406e0070dSMark Shellenbaum * in yet. 63506e0070dSMark Shellenbaum */ 63606e0070dSMark Shellenbaum *userp = 0; 63706e0070dSMark Shellenbaum *groupp = 0; 638e828a46dSMatthew Ahrens return (0); 639e828a46dSMatthew Ahrens } 640e828a46dSMatthew Ahrens if (sa.sa_magic == BSWAP_32(SA_MAGIC)) { 641e828a46dSMatthew Ahrens sa.sa_magic = SA_MAGIC; 642e828a46dSMatthew Ahrens sa.sa_layout_info = BSWAP_16(sa.sa_layout_info); 643e828a46dSMatthew Ahrens swap = B_TRUE; 644e828a46dSMatthew Ahrens } else { 645e828a46dSMatthew Ahrens VERIFY3U(sa.sa_magic, ==, SA_MAGIC); 646e828a46dSMatthew Ahrens } 647e828a46dSMatthew Ahrens 648e828a46dSMatthew Ahrens hdrsize = sa_hdrsize(&sa); 649e828a46dSMatthew Ahrens VERIFY3U(hdrsize, >=, sizeof (sa_hdr_phys_t)); 650e828a46dSMatthew Ahrens *userp = *((uint64_t *)((uintptr_t)data + hdrsize + 651e828a46dSMatthew Ahrens SA_UID_OFFSET)); 652e828a46dSMatthew Ahrens *groupp = *((uint64_t *)((uintptr_t)data + hdrsize + 653e828a46dSMatthew Ahrens SA_GID_OFFSET)); 654e828a46dSMatthew Ahrens if (swap) { 655e828a46dSMatthew Ahrens *userp = BSWAP_64(*userp); 656e828a46dSMatthew Ahrens *groupp = BSWAP_64(*groupp); 6570a586ceaSMark Shellenbaum } 6580a586ceaSMark Shellenbaum } 6593b2aab18SMatthew Ahrens return (0); 66014843421SMatthew Ahrens } 66114843421SMatthew Ahrens 66214843421SMatthew Ahrens static void 66314843421SMatthew Ahrens fuidstr_to_sid(zfsvfs_t *zfsvfs, const char *fuidstr, 66414843421SMatthew Ahrens char *domainbuf, int buflen, uid_t *ridp) 66514843421SMatthew Ahrens { 66614843421SMatthew Ahrens uint64_t fuid; 66714843421SMatthew Ahrens const char *domain; 66814843421SMatthew Ahrens 66914843421SMatthew Ahrens fuid = strtonum(fuidstr, NULL); 67014843421SMatthew Ahrens 67114843421SMatthew Ahrens domain = zfs_fuid_find_by_idx(zfsvfs, FUID_INDEX(fuid)); 67214843421SMatthew Ahrens if (domain) 67314843421SMatthew Ahrens (void) strlcpy(domainbuf, domain, buflen); 67414843421SMatthew Ahrens else 67514843421SMatthew Ahrens domainbuf[0] = '\0'; 67614843421SMatthew Ahrens *ridp = FUID_RID(fuid); 67714843421SMatthew Ahrens } 67814843421SMatthew Ahrens 67914843421SMatthew Ahrens static uint64_t 68014843421SMatthew Ahrens zfs_userquota_prop_to_obj(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type) 68114843421SMatthew Ahrens { 68214843421SMatthew Ahrens switch (type) { 68314843421SMatthew Ahrens case ZFS_PROP_USERUSED: 68414843421SMatthew Ahrens return (DMU_USERUSED_OBJECT); 68514843421SMatthew Ahrens case ZFS_PROP_GROUPUSED: 68614843421SMatthew Ahrens return (DMU_GROUPUSED_OBJECT); 68714843421SMatthew Ahrens case ZFS_PROP_USERQUOTA: 68814843421SMatthew Ahrens return (zfsvfs->z_userquota_obj); 68914843421SMatthew Ahrens case ZFS_PROP_GROUPQUOTA: 69014843421SMatthew Ahrens return (zfsvfs->z_groupquota_obj); 69114843421SMatthew Ahrens } 69214843421SMatthew Ahrens return (0); 69314843421SMatthew Ahrens } 69414843421SMatthew Ahrens 69514843421SMatthew Ahrens int 69614843421SMatthew Ahrens zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 69714843421SMatthew Ahrens uint64_t *cookiep, void *vbuf, uint64_t *bufsizep) 69814843421SMatthew Ahrens { 69914843421SMatthew Ahrens int error; 70014843421SMatthew Ahrens zap_cursor_t zc; 70114843421SMatthew Ahrens zap_attribute_t za; 70214843421SMatthew Ahrens zfs_useracct_t *buf = vbuf; 70314843421SMatthew Ahrens uint64_t obj; 70414843421SMatthew Ahrens 70514843421SMatthew Ahrens if (!dmu_objset_userspace_present(zfsvfs->z_os)) 706be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 70714843421SMatthew Ahrens 70814843421SMatthew Ahrens obj = zfs_userquota_prop_to_obj(zfsvfs, type); 70914843421SMatthew Ahrens if (obj == 0) { 71014843421SMatthew Ahrens *bufsizep = 0; 71114843421SMatthew Ahrens return (0); 71214843421SMatthew Ahrens } 71314843421SMatthew Ahrens 71414843421SMatthew Ahrens for (zap_cursor_init_serialized(&zc, zfsvfs->z_os, obj, *cookiep); 71514843421SMatthew Ahrens (error = zap_cursor_retrieve(&zc, &za)) == 0; 71614843421SMatthew Ahrens zap_cursor_advance(&zc)) { 71714843421SMatthew Ahrens if ((uintptr_t)buf - (uintptr_t)vbuf + sizeof (zfs_useracct_t) > 71814843421SMatthew Ahrens *bufsizep) 71914843421SMatthew Ahrens break; 72014843421SMatthew Ahrens 72114843421SMatthew Ahrens fuidstr_to_sid(zfsvfs, za.za_name, 72214843421SMatthew Ahrens buf->zu_domain, sizeof (buf->zu_domain), &buf->zu_rid); 72314843421SMatthew Ahrens 72414843421SMatthew Ahrens buf->zu_space = za.za_first_integer; 72514843421SMatthew Ahrens buf++; 72614843421SMatthew Ahrens } 72714843421SMatthew Ahrens if (error == ENOENT) 72814843421SMatthew Ahrens error = 0; 72914843421SMatthew Ahrens 73014843421SMatthew Ahrens ASSERT3U((uintptr_t)buf - (uintptr_t)vbuf, <=, *bufsizep); 73114843421SMatthew Ahrens *bufsizep = (uintptr_t)buf - (uintptr_t)vbuf; 73214843421SMatthew Ahrens *cookiep = zap_cursor_serialize(&zc); 73314843421SMatthew Ahrens zap_cursor_fini(&zc); 73414843421SMatthew Ahrens return (error); 73514843421SMatthew Ahrens } 73614843421SMatthew Ahrens 73714843421SMatthew Ahrens /* 73814843421SMatthew Ahrens * buf must be big enough (eg, 32 bytes) 73914843421SMatthew Ahrens */ 74014843421SMatthew Ahrens static int 74114843421SMatthew Ahrens id_to_fuidstr(zfsvfs_t *zfsvfs, const char *domain, uid_t rid, 74214843421SMatthew Ahrens char *buf, boolean_t addok) 74314843421SMatthew Ahrens { 74414843421SMatthew Ahrens uint64_t fuid; 74514843421SMatthew Ahrens int domainid = 0; 74614843421SMatthew Ahrens 74714843421SMatthew Ahrens if (domain && domain[0]) { 74814843421SMatthew Ahrens domainid = zfs_fuid_find_by_domain(zfsvfs, domain, NULL, addok); 74914843421SMatthew Ahrens if (domainid == -1) 750be6fd75aSMatthew Ahrens return (SET_ERROR(ENOENT)); 75114843421SMatthew Ahrens } 75214843421SMatthew Ahrens fuid = FUID_ENCODE(domainid, rid); 75314843421SMatthew Ahrens (void) sprintf(buf, "%llx", (longlong_t)fuid); 75414843421SMatthew Ahrens return (0); 75514843421SMatthew Ahrens } 75614843421SMatthew Ahrens 75714843421SMatthew Ahrens int 75814843421SMatthew Ahrens zfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 75914843421SMatthew Ahrens const char *domain, uint64_t rid, uint64_t *valp) 76014843421SMatthew Ahrens { 76114843421SMatthew Ahrens char buf[32]; 76214843421SMatthew Ahrens int err; 76314843421SMatthew Ahrens uint64_t obj; 76414843421SMatthew Ahrens 76514843421SMatthew Ahrens *valp = 0; 76614843421SMatthew Ahrens 76714843421SMatthew Ahrens if (!dmu_objset_userspace_present(zfsvfs->z_os)) 768be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 76914843421SMatthew Ahrens 77014843421SMatthew Ahrens obj = zfs_userquota_prop_to_obj(zfsvfs, type); 77114843421SMatthew Ahrens if (obj == 0) 77214843421SMatthew Ahrens return (0); 77314843421SMatthew Ahrens 77414843421SMatthew Ahrens err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_FALSE); 77514843421SMatthew Ahrens if (err) 77614843421SMatthew Ahrens return (err); 77714843421SMatthew Ahrens 77814843421SMatthew Ahrens err = zap_lookup(zfsvfs->z_os, obj, buf, 8, 1, valp); 77914843421SMatthew Ahrens if (err == ENOENT) 78014843421SMatthew Ahrens err = 0; 78114843421SMatthew Ahrens return (err); 78214843421SMatthew Ahrens } 78314843421SMatthew Ahrens 78414843421SMatthew Ahrens int 78514843421SMatthew Ahrens zfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 78614843421SMatthew Ahrens const char *domain, uint64_t rid, uint64_t quota) 78714843421SMatthew Ahrens { 78814843421SMatthew Ahrens char buf[32]; 78914843421SMatthew Ahrens int err; 79014843421SMatthew Ahrens dmu_tx_t *tx; 79114843421SMatthew Ahrens uint64_t *objp; 79214843421SMatthew Ahrens boolean_t fuid_dirtied; 79314843421SMatthew Ahrens 79414843421SMatthew Ahrens if (type != ZFS_PROP_USERQUOTA && type != ZFS_PROP_GROUPQUOTA) 795be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 79614843421SMatthew Ahrens 79714843421SMatthew Ahrens if (zfsvfs->z_version < ZPL_VERSION_USERSPACE) 798be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 79914843421SMatthew Ahrens 80014843421SMatthew Ahrens objp = (type == ZFS_PROP_USERQUOTA) ? &zfsvfs->z_userquota_obj : 80114843421SMatthew Ahrens &zfsvfs->z_groupquota_obj; 80214843421SMatthew Ahrens 80314843421SMatthew Ahrens err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_TRUE); 80414843421SMatthew Ahrens if (err) 80514843421SMatthew Ahrens return (err); 80614843421SMatthew Ahrens fuid_dirtied = zfsvfs->z_fuid_dirty; 80714843421SMatthew Ahrens 80814843421SMatthew Ahrens tx = dmu_tx_create(zfsvfs->z_os); 80914843421SMatthew Ahrens dmu_tx_hold_zap(tx, *objp ? *objp : DMU_NEW_OBJECT, B_TRUE, NULL); 81014843421SMatthew Ahrens if (*objp == 0) { 81114843421SMatthew Ahrens dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE, 81214843421SMatthew Ahrens zfs_userquota_prop_prefixes[type]); 81314843421SMatthew Ahrens } 81414843421SMatthew Ahrens if (fuid_dirtied) 81514843421SMatthew Ahrens zfs_fuid_txhold(zfsvfs, tx); 81614843421SMatthew Ahrens err = dmu_tx_assign(tx, TXG_WAIT); 81714843421SMatthew Ahrens if (err) { 81814843421SMatthew Ahrens dmu_tx_abort(tx); 81914843421SMatthew Ahrens return (err); 82014843421SMatthew Ahrens } 82114843421SMatthew Ahrens 82214843421SMatthew Ahrens mutex_enter(&zfsvfs->z_lock); 82314843421SMatthew Ahrens if (*objp == 0) { 82414843421SMatthew Ahrens *objp = zap_create(zfsvfs->z_os, DMU_OT_USERGROUP_QUOTA, 82514843421SMatthew Ahrens DMU_OT_NONE, 0, tx); 82614843421SMatthew Ahrens VERIFY(0 == zap_add(zfsvfs->z_os, MASTER_NODE_OBJ, 82714843421SMatthew Ahrens zfs_userquota_prop_prefixes[type], 8, 1, objp, tx)); 82814843421SMatthew Ahrens } 82914843421SMatthew Ahrens mutex_exit(&zfsvfs->z_lock); 83014843421SMatthew Ahrens 83114843421SMatthew Ahrens if (quota == 0) { 83214843421SMatthew Ahrens err = zap_remove(zfsvfs->z_os, *objp, buf, tx); 83314843421SMatthew Ahrens if (err == ENOENT) 83414843421SMatthew Ahrens err = 0; 83514843421SMatthew Ahrens } else { 83614843421SMatthew Ahrens err = zap_update(zfsvfs->z_os, *objp, buf, 8, 1, "a, tx); 83714843421SMatthew Ahrens } 83814843421SMatthew Ahrens ASSERT(err == 0); 83914843421SMatthew Ahrens if (fuid_dirtied) 84014843421SMatthew Ahrens zfs_fuid_sync(zfsvfs, tx); 84114843421SMatthew Ahrens dmu_tx_commit(tx); 84214843421SMatthew Ahrens return (err); 84314843421SMatthew Ahrens } 84414843421SMatthew Ahrens 84514843421SMatthew Ahrens boolean_t 8460a586ceaSMark Shellenbaum zfs_fuid_overquota(zfsvfs_t *zfsvfs, boolean_t isgroup, uint64_t fuid) 84714843421SMatthew Ahrens { 84814843421SMatthew Ahrens char buf[32]; 84914843421SMatthew Ahrens uint64_t used, quota, usedobj, quotaobj; 85014843421SMatthew Ahrens int err; 85114843421SMatthew Ahrens 85214843421SMatthew Ahrens usedobj = isgroup ? DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT; 85314843421SMatthew Ahrens quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj; 85414843421SMatthew Ahrens 85514843421SMatthew Ahrens if (quotaobj == 0 || zfsvfs->z_replay) 85614843421SMatthew Ahrens return (B_FALSE); 85714843421SMatthew Ahrens 85814843421SMatthew Ahrens (void) sprintf(buf, "%llx", (longlong_t)fuid); 85914843421SMatthew Ahrens err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); 86014843421SMatthew Ahrens if (err != 0) 86114843421SMatthew Ahrens return (B_FALSE); 86214843421SMatthew Ahrens 86314843421SMatthew Ahrens err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used); 86414843421SMatthew Ahrens if (err != 0) 86514843421SMatthew Ahrens return (B_FALSE); 86614843421SMatthew Ahrens return (used >= quota); 86714843421SMatthew Ahrens } 86814843421SMatthew Ahrens 8690a586ceaSMark Shellenbaum boolean_t 8700a586ceaSMark Shellenbaum zfs_owner_overquota(zfsvfs_t *zfsvfs, znode_t *zp, boolean_t isgroup) 8710a586ceaSMark Shellenbaum { 8720a586ceaSMark Shellenbaum uint64_t fuid; 8730a586ceaSMark Shellenbaum uint64_t quotaobj; 8740a586ceaSMark Shellenbaum 8750a586ceaSMark Shellenbaum quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj; 8760a586ceaSMark Shellenbaum 877f1696b23SMark Shellenbaum fuid = isgroup ? zp->z_gid : zp->z_uid; 8780a586ceaSMark Shellenbaum 8790a586ceaSMark Shellenbaum if (quotaobj == 0 || zfsvfs->z_replay) 8800a586ceaSMark Shellenbaum return (B_FALSE); 8810a586ceaSMark Shellenbaum 8820a586ceaSMark Shellenbaum return (zfs_fuid_overquota(zfsvfs, isgroup, fuid)); 8830a586ceaSMark Shellenbaum } 8840a586ceaSMark Shellenbaum 88514843421SMatthew Ahrens int 886af4c679fSSean McEnroe zfsvfs_create(const char *osname, zfsvfs_t **zfvp) 88714843421SMatthew Ahrens { 88814843421SMatthew Ahrens objset_t *os; 88914843421SMatthew Ahrens zfsvfs_t *zfsvfs; 89014843421SMatthew Ahrens uint64_t zval; 89114843421SMatthew Ahrens int i, error; 8920a586ceaSMark Shellenbaum uint64_t sa_obj; 89314843421SMatthew Ahrens 894503ad85cSMatthew Ahrens zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); 89514843421SMatthew Ahrens 896503ad85cSMatthew Ahrens /* 897503ad85cSMatthew Ahrens * We claim to always be readonly so we can open snapshots; 898503ad85cSMatthew Ahrens * other ZPL code will prevent us from writing to snapshots. 899503ad85cSMatthew Ahrens */ 900503ad85cSMatthew Ahrens error = dmu_objset_own(osname, DMU_OST_ZFS, B_TRUE, zfsvfs, &os); 901503ad85cSMatthew Ahrens if (error) { 902503ad85cSMatthew Ahrens kmem_free(zfsvfs, sizeof (zfsvfs_t)); 90314843421SMatthew Ahrens return (error); 904503ad85cSMatthew Ahrens } 90514843421SMatthew Ahrens 90614843421SMatthew Ahrens /* 90714843421SMatthew Ahrens * Initialize the zfs-specific filesystem structure. 90814843421SMatthew Ahrens * Should probably make this a kmem cache, shuffle fields, 90914843421SMatthew Ahrens * and just bzero up to z_hold_mtx[]. 91014843421SMatthew Ahrens */ 91114843421SMatthew Ahrens zfsvfs->z_vfs = NULL; 91214843421SMatthew Ahrens zfsvfs->z_parent = zfsvfs; 913b5152584SMatthew Ahrens zfsvfs->z_max_blksz = SPA_OLD_MAXBLOCKSIZE; 91414843421SMatthew Ahrens zfsvfs->z_show_ctldir = ZFS_SNAPDIR_VISIBLE; 91514843421SMatthew Ahrens zfsvfs->z_os = os; 91614843421SMatthew Ahrens 91714843421SMatthew Ahrens error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zfsvfs->z_version); 91814843421SMatthew Ahrens if (error) { 91914843421SMatthew Ahrens goto out; 920dc7cd546SMark Shellenbaum } else if (zfsvfs->z_version > 921dc7cd546SMark Shellenbaum zfs_zpl_version_map(spa_version(dmu_objset_spa(os)))) { 922dc7cd546SMark Shellenbaum (void) printf("Can't mount a version %lld file system " 923dc7cd546SMark Shellenbaum "on a version %lld pool\n. Pool must be upgraded to mount " 924dc7cd546SMark Shellenbaum "this file system.", (u_longlong_t)zfsvfs->z_version, 925dc7cd546SMark Shellenbaum (u_longlong_t)spa_version(dmu_objset_spa(os))); 926be6fd75aSMatthew Ahrens error = SET_ERROR(ENOTSUP); 92714843421SMatthew Ahrens goto out; 92814843421SMatthew Ahrens } 92914843421SMatthew Ahrens if ((error = zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &zval)) != 0) 93014843421SMatthew Ahrens goto out; 93114843421SMatthew Ahrens zfsvfs->z_norm = (int)zval; 93214843421SMatthew Ahrens 93314843421SMatthew Ahrens if ((error = zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &zval)) != 0) 93414843421SMatthew Ahrens goto out; 93514843421SMatthew Ahrens zfsvfs->z_utf8 = (zval != 0); 93614843421SMatthew Ahrens 93714843421SMatthew Ahrens if ((error = zfs_get_zplprop(os, ZFS_PROP_CASE, &zval)) != 0) 93814843421SMatthew Ahrens goto out; 93914843421SMatthew Ahrens zfsvfs->z_case = (uint_t)zval; 94014843421SMatthew Ahrens 94114843421SMatthew Ahrens /* 94214843421SMatthew Ahrens * Fold case on file systems that are always or sometimes case 94314843421SMatthew Ahrens * insensitive. 94414843421SMatthew Ahrens */ 94514843421SMatthew Ahrens if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE || 94614843421SMatthew Ahrens zfsvfs->z_case == ZFS_CASE_MIXED) 94714843421SMatthew Ahrens zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER; 94814843421SMatthew Ahrens 94914843421SMatthew Ahrens zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os); 9500a586ceaSMark Shellenbaum zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os); 9510a586ceaSMark Shellenbaum 9520a586ceaSMark Shellenbaum if (zfsvfs->z_use_sa) { 9530a586ceaSMark Shellenbaum /* should either have both of these objects or none */ 9540a586ceaSMark Shellenbaum error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, 9550a586ceaSMark Shellenbaum &sa_obj); 9560a586ceaSMark Shellenbaum if (error) 957a2cdcdd2SPaul Dagnelie goto out; 9580a586ceaSMark Shellenbaum } else { 9590a586ceaSMark Shellenbaum /* 9600a586ceaSMark Shellenbaum * Pre SA versions file systems should never touch 9610a586ceaSMark Shellenbaum * either the attribute registration or layout objects. 9620a586ceaSMark Shellenbaum */ 9630a586ceaSMark Shellenbaum sa_obj = 0; 9640a586ceaSMark Shellenbaum } 9650a586ceaSMark Shellenbaum 9661d8ccc7bSMark Shellenbaum error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END, 9671d8ccc7bSMark Shellenbaum &zfsvfs->z_attr_table); 9681d8ccc7bSMark Shellenbaum if (error) 9691d8ccc7bSMark Shellenbaum goto out; 9700a586ceaSMark Shellenbaum 9710a586ceaSMark Shellenbaum if (zfsvfs->z_version >= ZPL_VERSION_SA) 9720a586ceaSMark Shellenbaum sa_register_update_callback(os, zfs_sa_upgrade); 97314843421SMatthew Ahrens 97414843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, 97514843421SMatthew Ahrens &zfsvfs->z_root); 97614843421SMatthew Ahrens if (error) 97714843421SMatthew Ahrens goto out; 97814843421SMatthew Ahrens ASSERT(zfsvfs->z_root != 0); 97914843421SMatthew Ahrens 98014843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET, 8, 1, 98114843421SMatthew Ahrens &zfsvfs->z_unlinkedobj); 98214843421SMatthew Ahrens if (error) 98314843421SMatthew Ahrens goto out; 98414843421SMatthew Ahrens 98514843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, 98614843421SMatthew Ahrens zfs_userquota_prop_prefixes[ZFS_PROP_USERQUOTA], 98714843421SMatthew Ahrens 8, 1, &zfsvfs->z_userquota_obj); 98814843421SMatthew Ahrens if (error && error != ENOENT) 98914843421SMatthew Ahrens goto out; 99014843421SMatthew Ahrens 99114843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, 99214843421SMatthew Ahrens zfs_userquota_prop_prefixes[ZFS_PROP_GROUPQUOTA], 99314843421SMatthew Ahrens 8, 1, &zfsvfs->z_groupquota_obj); 99414843421SMatthew Ahrens if (error && error != ENOENT) 99514843421SMatthew Ahrens goto out; 99614843421SMatthew Ahrens 99714843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES, 8, 1, 99814843421SMatthew Ahrens &zfsvfs->z_fuid_obj); 99914843421SMatthew Ahrens if (error && error != ENOENT) 100014843421SMatthew Ahrens goto out; 100114843421SMatthew Ahrens 100214843421SMatthew Ahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SHARES_DIR, 8, 1, 100314843421SMatthew Ahrens &zfsvfs->z_shares_dir); 100414843421SMatthew Ahrens if (error && error != ENOENT) 100514843421SMatthew Ahrens goto out; 100614843421SMatthew Ahrens 100714843421SMatthew Ahrens mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); 100814843421SMatthew Ahrens mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL); 100914843421SMatthew Ahrens list_create(&zfsvfs->z_all_znodes, sizeof (znode_t), 101014843421SMatthew Ahrens offsetof(znode_t, z_link_node)); 1011c9030f6cSAlexander Motin rrm_init(&zfsvfs->z_teardown_lock, B_FALSE); 101214843421SMatthew Ahrens rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL); 101314843421SMatthew Ahrens rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL); 101414843421SMatthew Ahrens for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) 101514843421SMatthew Ahrens mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); 101614843421SMatthew Ahrens 1017af4c679fSSean McEnroe *zfvp = zfsvfs; 101814843421SMatthew Ahrens return (0); 101914843421SMatthew Ahrens 102014843421SMatthew Ahrens out: 1021503ad85cSMatthew Ahrens dmu_objset_disown(os, zfsvfs); 1022af4c679fSSean McEnroe *zfvp = NULL; 102314843421SMatthew Ahrens kmem_free(zfsvfs, sizeof (zfsvfs_t)); 102414843421SMatthew Ahrens return (error); 102514843421SMatthew Ahrens } 102614843421SMatthew Ahrens 1027ea8dc4b6Seschrock static int 1028f18faf3fSek110237 zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) 1029f18faf3fSek110237 { 1030f18faf3fSek110237 int error; 1031f18faf3fSek110237 1032f18faf3fSek110237 error = zfs_register_callbacks(zfsvfs->z_vfs); 1033f18faf3fSek110237 if (error) 1034f18faf3fSek110237 return (error); 1035f18faf3fSek110237 1036f18faf3fSek110237 /* 1037f18faf3fSek110237 * Set the objset user_ptr to track its zfsvfs. 1038f18faf3fSek110237 */ 1039503ad85cSMatthew Ahrens mutex_enter(&zfsvfs->z_os->os_user_ptr_lock); 1040f18faf3fSek110237 dmu_objset_set_user(zfsvfs->z_os, zfsvfs); 1041503ad85cSMatthew Ahrens mutex_exit(&zfsvfs->z_os->os_user_ptr_lock); 1042f18faf3fSek110237 1043377c02aaSNeil Perrin zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data); 1044377c02aaSNeil Perrin 1045f18faf3fSek110237 /* 1046f18faf3fSek110237 * If we are not mounting (ie: online recv), then we don't 1047f18faf3fSek110237 * have to worry about replaying the log as we blocked all 1048f18faf3fSek110237 * operations out since we closed the ZIL. 1049f18faf3fSek110237 */ 1050f18faf3fSek110237 if (mounting) { 1051a6e57bd4SNeil Perrin boolean_t readonly; 1052a6e57bd4SNeil Perrin 1053f18faf3fSek110237 /* 1054f18faf3fSek110237 * During replay we remove the read only flag to 1055f18faf3fSek110237 * allow replays to succeed. 1056f18faf3fSek110237 */ 1057f18faf3fSek110237 readonly = zfsvfs->z_vfs->vfs_flag & VFS_RDONLY; 10581209a471SNeil Perrin if (readonly != 0) 1059f18faf3fSek110237 zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 10601209a471SNeil Perrin else 10611209a471SNeil Perrin zfs_unlinked_drain(zfsvfs); 1062f18faf3fSek110237 1063f18faf3fSek110237 /* 1064f18faf3fSek110237 * Parse and replay the intent log. 10651209a471SNeil Perrin * 10661209a471SNeil Perrin * Because of ziltest, this must be done after 10671209a471SNeil Perrin * zfs_unlinked_drain(). (Further note: ziltest 10681209a471SNeil Perrin * doesn't use readonly mounts, where 10691209a471SNeil Perrin * zfs_unlinked_drain() isn't called.) This is because 10701209a471SNeil Perrin * ziltest causes spa_sync() to think it's committed, 10711209a471SNeil Perrin * but actually it is not, so the intent log contains 10721209a471SNeil Perrin * many txg's worth of changes. 10731209a471SNeil Perrin * 10741209a471SNeil Perrin * In particular, if object N is in the unlinked set in 10751209a471SNeil Perrin * the last txg to actually sync, then it could be 10761209a471SNeil Perrin * actually freed in a later txg and then reallocated 10771209a471SNeil Perrin * in a yet later txg. This would write a "create 10781209a471SNeil Perrin * object N" record to the intent log. Normally, this 10791209a471SNeil Perrin * would be fine because the spa_sync() would have 10801209a471SNeil Perrin * written out the fact that object N is free, before 10811209a471SNeil Perrin * we could write the "create object N" intent log 10821209a471SNeil Perrin * record. 10831209a471SNeil Perrin * 10841209a471SNeil Perrin * But when we are in ziltest mode, we advance the "open 10851209a471SNeil Perrin * txg" without actually spa_sync()-ing the changes to 10861209a471SNeil Perrin * disk. So we would see that object N is still 10871209a471SNeil Perrin * allocated and in the unlinked set, and there is an 10881209a471SNeil Perrin * intent log record saying to allocate it. 1089f18faf3fSek110237 */ 1090f9af39baSGeorge Wilson if (spa_writeable(dmu_objset_spa(zfsvfs->z_os))) { 109155da60b9SMark J Musante if (zil_replay_disable) { 109255da60b9SMark J Musante zil_destroy(zfsvfs->z_log, B_FALSE); 109355da60b9SMark J Musante } else { 10941209a471SNeil Perrin zfsvfs->z_replay = B_TRUE; 1095f9af39baSGeorge Wilson zil_replay(zfsvfs->z_os, zfsvfs, 1096f9af39baSGeorge Wilson zfs_replay_vector); 10971209a471SNeil Perrin zfsvfs->z_replay = B_FALSE; 10981209a471SNeil Perrin } 1099f9af39baSGeorge Wilson } 1100f18faf3fSek110237 zfsvfs->z_vfs->vfs_flag |= readonly; /* restore readonly bit */ 1101f18faf3fSek110237 } 1102f18faf3fSek110237 1103f18faf3fSek110237 return (0); 1104f18faf3fSek110237 } 1105f18faf3fSek110237 110614843421SMatthew Ahrens void 110714843421SMatthew Ahrens zfsvfs_free(zfsvfs_t *zfsvfs) 110847f263f4Sek110237 { 110914843421SMatthew Ahrens int i; 11104e9583b2STom Erickson extern krwlock_t zfsvfs_lock; /* in zfs_znode.c */ 11114e9583b2STom Erickson 11124e9583b2STom Erickson /* 11134e9583b2STom Erickson * This is a barrier to prevent the filesystem from going away in 11144e9583b2STom Erickson * zfs_znode_move() until we can safely ensure that the filesystem is 11154e9583b2STom Erickson * not unmounted. We consider the filesystem valid before the barrier 11164e9583b2STom Erickson * and invalid after the barrier. 11174e9583b2STom Erickson */ 11184e9583b2STom Erickson rw_enter(&zfsvfs_lock, RW_READER); 11194e9583b2STom Erickson rw_exit(&zfsvfs_lock); 112014843421SMatthew Ahrens 112114843421SMatthew Ahrens zfs_fuid_destroy(zfsvfs); 112214843421SMatthew Ahrens 112347f263f4Sek110237 mutex_destroy(&zfsvfs->z_znodes_lock); 11249e1320c0SMark Shellenbaum mutex_destroy(&zfsvfs->z_lock); 112547f263f4Sek110237 list_destroy(&zfsvfs->z_all_znodes); 1126c9030f6cSAlexander Motin rrm_destroy(&zfsvfs->z_teardown_lock); 112747f263f4Sek110237 rw_destroy(&zfsvfs->z_teardown_inactive_lock); 112847f263f4Sek110237 rw_destroy(&zfsvfs->z_fuid_lock); 112914843421SMatthew Ahrens for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) 113014843421SMatthew Ahrens mutex_destroy(&zfsvfs->z_hold_mtx[i]); 113147f263f4Sek110237 kmem_free(zfsvfs, sizeof (zfsvfs_t)); 113247f263f4Sek110237 } 113347f263f4Sek110237 113414843421SMatthew Ahrens static void 113514843421SMatthew Ahrens zfs_set_fuid_feature(zfsvfs_t *zfsvfs) 113614843421SMatthew Ahrens { 113714843421SMatthew Ahrens zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os); 113844bffe01SMark Shellenbaum if (zfsvfs->z_vfs) { 113944bffe01SMark Shellenbaum if (zfsvfs->z_use_fuids) { 114014843421SMatthew Ahrens vfs_set_feature(zfsvfs->z_vfs, VFSFT_XVATTR); 114114843421SMatthew Ahrens vfs_set_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS); 114214843421SMatthew Ahrens vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS); 114314843421SMatthew Ahrens vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE); 1144e802abbdSTim Haley vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER); 11457a286c47SDai Ngo vfs_set_feature(zfsvfs->z_vfs, VFSFT_REPARSE); 114644bffe01SMark Shellenbaum } else { 114744bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_XVATTR); 114844bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS); 114944bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS); 115044bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE); 115144bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER); 115244bffe01SMark Shellenbaum vfs_clear_feature(zfsvfs->z_vfs, VFSFT_REPARSE); 115344bffe01SMark Shellenbaum } 115414843421SMatthew Ahrens } 11550a586ceaSMark Shellenbaum zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os); 115614843421SMatthew Ahrens } 115714843421SMatthew Ahrens 1158f18faf3fSek110237 static int 1159088f3894Sahrens zfs_domount(vfs_t *vfsp, char *osname) 1160ea8dc4b6Seschrock { 1161ea8dc4b6Seschrock dev_t mount_dev; 116214843421SMatthew Ahrens uint64_t recordsize, fsid_guid; 1163ea8dc4b6Seschrock int error = 0; 1164ea8dc4b6Seschrock zfsvfs_t *zfsvfs; 1165ea8dc4b6Seschrock 1166ea8dc4b6Seschrock ASSERT(vfsp); 1167ea8dc4b6Seschrock ASSERT(osname); 1168ea8dc4b6Seschrock 1169503ad85cSMatthew Ahrens error = zfsvfs_create(osname, &zfsvfs); 117014843421SMatthew Ahrens if (error) 117114843421SMatthew Ahrens return (error); 1172ea8dc4b6Seschrock zfsvfs->z_vfs = vfsp; 1173ea8dc4b6Seschrock 1174ea8dc4b6Seschrock /* Initialize the generic filesystem structure. */ 1175ea8dc4b6Seschrock vfsp->vfs_bcount = 0; 1176ea8dc4b6Seschrock vfsp->vfs_data = NULL; 1177ea8dc4b6Seschrock 1178ea8dc4b6Seschrock if (zfs_create_unique_device(&mount_dev) == -1) { 1179be6fd75aSMatthew Ahrens error = SET_ERROR(ENODEV); 1180ea8dc4b6Seschrock goto out; 1181ea8dc4b6Seschrock } 1182ea8dc4b6Seschrock ASSERT(vfs_devismounted(mount_dev) == 0); 1183ea8dc4b6Seschrock 1184ea8dc4b6Seschrock if (error = dsl_prop_get_integer(osname, "recordsize", &recordsize, 1185ea8dc4b6Seschrock NULL)) 1186ea8dc4b6Seschrock goto out; 1187ea8dc4b6Seschrock 1188ea8dc4b6Seschrock vfsp->vfs_dev = mount_dev; 1189ea8dc4b6Seschrock vfsp->vfs_fstype = zfsfstype; 1190ea8dc4b6Seschrock vfsp->vfs_bsize = recordsize; 1191ea8dc4b6Seschrock vfsp->vfs_flag |= VFS_NOTRUNC; 1192ea8dc4b6Seschrock vfsp->vfs_data = zfsvfs; 1193ea8dc4b6Seschrock 119414843421SMatthew Ahrens /* 119514843421SMatthew Ahrens * The fsid is 64 bits, composed of an 8-bit fs type, which 119614843421SMatthew Ahrens * separates our fsid from any other filesystem types, and a 119714843421SMatthew Ahrens * 56-bit objset unique ID. The objset unique ID is unique to 119814843421SMatthew Ahrens * all objsets open on this system, provided by unique_create(). 119914843421SMatthew Ahrens * The 8-bit fs type must be put in the low bits of fsid[1] 120014843421SMatthew Ahrens * because that's where other Solaris filesystems put it. 120114843421SMatthew Ahrens */ 120214843421SMatthew Ahrens fsid_guid = dmu_objset_fsid_guid(zfsvfs->z_os); 120314843421SMatthew Ahrens ASSERT((fsid_guid & ~((1ULL<<56)-1)) == 0); 120414843421SMatthew Ahrens vfsp->vfs_fsid.val[0] = fsid_guid; 120514843421SMatthew Ahrens vfsp->vfs_fsid.val[1] = ((fsid_guid>>32) << 8) | 120614843421SMatthew Ahrens zfsfstype & 0xFF; 1207ea8dc4b6Seschrock 1208da6c28aaSamw /* 1209da6c28aaSamw * Set features for file system. 1210da6c28aaSamw */ 121114843421SMatthew Ahrens zfs_set_fuid_feature(zfsvfs); 1212de8267e0Stimh if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) { 1213de8267e0Stimh vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS); 1214de8267e0Stimh vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE); 1215de8267e0Stimh vfs_set_feature(vfsp, VFSFT_NOCASESENSITIVE); 1216de8267e0Stimh } else if (zfsvfs->z_case == ZFS_CASE_MIXED) { 1217de8267e0Stimh vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS); 1218de8267e0Stimh vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE); 1219de8267e0Stimh } 1220c242f9a0Schunli zhang - Sun Microsystems - Irvine United States vfs_set_feature(vfsp, VFSFT_ZEROCOPY_SUPPORTED); 1221da6c28aaSamw 1222ea8dc4b6Seschrock if (dmu_objset_is_snapshot(zfsvfs->z_os)) { 1223da6c28aaSamw uint64_t pval; 12247b55fa8eSck153898 1225ea8dc4b6Seschrock atime_changed_cb(zfsvfs, B_FALSE); 1226ea8dc4b6Seschrock readonly_changed_cb(zfsvfs, B_TRUE); 1227da6c28aaSamw if (error = dsl_prop_get_integer(osname, "xattr", &pval, NULL)) 12287b55fa8eSck153898 goto out; 1229da6c28aaSamw xattr_changed_cb(zfsvfs, pval); 1230ea8dc4b6Seschrock zfsvfs->z_issnap = B_TRUE; 1231b9deb9cbSMark J Musante zfsvfs->z_os->os_sync = ZFS_SYNC_DISABLED; 1232777badbaSMatthew Ahrens 1233503ad85cSMatthew Ahrens mutex_enter(&zfsvfs->z_os->os_user_ptr_lock); 1234777badbaSMatthew Ahrens dmu_objset_set_user(zfsvfs->z_os, zfsvfs); 1235503ad85cSMatthew Ahrens mutex_exit(&zfsvfs->z_os->os_user_ptr_lock); 1236ea8dc4b6Seschrock } else { 1237f18faf3fSek110237 error = zfsvfs_setup(zfsvfs, B_TRUE); 1238ea8dc4b6Seschrock } 1239ea8dc4b6Seschrock 1240fa9e4066Sahrens if (!zfsvfs->z_issnap) 1241fa9e4066Sahrens zfsctl_create(zfsvfs); 1242fa9e4066Sahrens out: 1243fa9e4066Sahrens if (error) { 1244503ad85cSMatthew Ahrens dmu_objset_disown(zfsvfs->z_os, zfsvfs); 124514843421SMatthew Ahrens zfsvfs_free(zfsvfs); 1246fa9e4066Sahrens } else { 12471a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&zfs_active_fs_count); 1248fa9e4066Sahrens } 1249fa9e4066Sahrens 1250ea8dc4b6Seschrock return (error); 1251ea8dc4b6Seschrock } 1252ea8dc4b6Seschrock 1253ea8dc4b6Seschrock void 1254ea8dc4b6Seschrock zfs_unregister_callbacks(zfsvfs_t *zfsvfs) 1255ea8dc4b6Seschrock { 1256ea8dc4b6Seschrock objset_t *os = zfsvfs->z_os; 1257ea8dc4b6Seschrock 125803bad06fSJustin Gibbs if (!dmu_objset_is_snapshot(os)) 125903bad06fSJustin Gibbs dsl_prop_unregister_all(dmu_objset_ds(os), zfsvfs); 1260ea8dc4b6Seschrock } 1261ea8dc4b6Seschrock 1262b1b8ab34Slling /* 1263b1b8ab34Slling * Convert a decimal digit string to a uint64_t integer. 1264b1b8ab34Slling */ 1265b1b8ab34Slling static int 1266b1b8ab34Slling str_to_uint64(char *str, uint64_t *objnum) 1267b1b8ab34Slling { 1268b1b8ab34Slling uint64_t num = 0; 1269b1b8ab34Slling 1270b1b8ab34Slling while (*str) { 1271b1b8ab34Slling if (*str < '0' || *str > '9') 1272be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 1273b1b8ab34Slling 1274b1b8ab34Slling num = num*10 + *str++ - '0'; 1275b1b8ab34Slling } 1276b1b8ab34Slling 1277b1b8ab34Slling *objnum = num; 1278b1b8ab34Slling return (0); 1279b1b8ab34Slling } 1280b1b8ab34Slling 1281b1b8ab34Slling /* 1282b1b8ab34Slling * The boot path passed from the boot loader is in the form of 1283b1b8ab34Slling * "rootpool-name/root-filesystem-object-number'. Convert this 1284b1b8ab34Slling * string to a dataset name: "rootpool-name/root-filesystem-name". 1285b1b8ab34Slling */ 1286b1b8ab34Slling static int 1287e7cbe64fSgw25295 zfs_parse_bootfs(char *bpath, char *outpath) 1288b1b8ab34Slling { 1289b1b8ab34Slling char *slashp; 1290b1b8ab34Slling uint64_t objnum; 1291b1b8ab34Slling int error; 1292b1b8ab34Slling 1293b1b8ab34Slling if (*bpath == 0 || *bpath == '/') 1294be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 1295b1b8ab34Slling 129619397407SSherry Moore (void) strcpy(outpath, bpath); 129719397407SSherry Moore 1298b1b8ab34Slling slashp = strchr(bpath, '/'); 1299b1b8ab34Slling 1300b1b8ab34Slling /* if no '/', just return the pool name */ 1301b1b8ab34Slling if (slashp == NULL) { 1302b1b8ab34Slling return (0); 1303b1b8ab34Slling } 1304b1b8ab34Slling 130519397407SSherry Moore /* if not a number, just return the root dataset name */ 130619397407SSherry Moore if (str_to_uint64(slashp+1, &objnum)) { 130719397407SSherry Moore return (0); 130819397407SSherry Moore } 1309b1b8ab34Slling 1310b1b8ab34Slling *slashp = '\0'; 1311b1b8ab34Slling error = dsl_dsobj_to_dsname(bpath, objnum, outpath); 1312b1b8ab34Slling *slashp = '/'; 1313b1b8ab34Slling 1314b1b8ab34Slling return (error); 1315b1b8ab34Slling } 1316b1b8ab34Slling 13174201a95eSRic Aleshire /* 1318f7170741SWill Andrews * Check that the hex label string is appropriate for the dataset being 1319f7170741SWill Andrews * mounted into the global_zone proper. 13204201a95eSRic Aleshire * 13214201a95eSRic Aleshire * Return an error if the hex label string is not default or 13224201a95eSRic Aleshire * admin_low/admin_high. For admin_low labels, the corresponding 13234201a95eSRic Aleshire * dataset must be readonly. 13244201a95eSRic Aleshire */ 13254201a95eSRic Aleshire int 13264201a95eSRic Aleshire zfs_check_global_label(const char *dsname, const char *hexsl) 13274201a95eSRic Aleshire { 13284201a95eSRic Aleshire if (strcasecmp(hexsl, ZFS_MLSLABEL_DEFAULT) == 0) 13294201a95eSRic Aleshire return (0); 13304201a95eSRic Aleshire if (strcasecmp(hexsl, ADMIN_HIGH) == 0) 13314201a95eSRic Aleshire return (0); 13324201a95eSRic Aleshire if (strcasecmp(hexsl, ADMIN_LOW) == 0) { 13334201a95eSRic Aleshire /* must be readonly */ 13344201a95eSRic Aleshire uint64_t rdonly; 13354201a95eSRic Aleshire 13364201a95eSRic Aleshire if (dsl_prop_get_integer(dsname, 13374201a95eSRic Aleshire zfs_prop_to_name(ZFS_PROP_READONLY), &rdonly, NULL)) 1338be6fd75aSMatthew Ahrens return (SET_ERROR(EACCES)); 13394201a95eSRic Aleshire return (rdonly ? 0 : EACCES); 13404201a95eSRic Aleshire } 1341be6fd75aSMatthew Ahrens return (SET_ERROR(EACCES)); 13424201a95eSRic Aleshire } 13434201a95eSRic Aleshire 13444201a95eSRic Aleshire /* 13454201a95eSRic Aleshire * Determine whether the mount is allowed according to MAC check. 13464201a95eSRic Aleshire * by comparing (where appropriate) label of the dataset against 13474201a95eSRic Aleshire * the label of the zone being mounted into. If the dataset has 13484201a95eSRic Aleshire * no label, create one. 13494201a95eSRic Aleshire * 1350f7170741SWill Andrews * Returns 0 if access allowed, error otherwise (e.g. EACCES) 13514201a95eSRic Aleshire */ 13524201a95eSRic Aleshire static int 13534201a95eSRic Aleshire zfs_mount_label_policy(vfs_t *vfsp, char *osname) 13544201a95eSRic Aleshire { 13554201a95eSRic Aleshire int error, retv; 13564201a95eSRic Aleshire zone_t *mntzone = NULL; 13574201a95eSRic Aleshire ts_label_t *mnt_tsl; 13584201a95eSRic Aleshire bslabel_t *mnt_sl; 13594201a95eSRic Aleshire bslabel_t ds_sl; 13604201a95eSRic Aleshire char ds_hexsl[MAXNAMELEN]; 13614201a95eSRic Aleshire 13624201a95eSRic Aleshire retv = EACCES; /* assume the worst */ 13634201a95eSRic Aleshire 13644201a95eSRic Aleshire /* 13654201a95eSRic Aleshire * Start by getting the dataset label if it exists. 13664201a95eSRic Aleshire */ 13674201a95eSRic Aleshire error = dsl_prop_get(osname, zfs_prop_to_name(ZFS_PROP_MLSLABEL), 13684201a95eSRic Aleshire 1, sizeof (ds_hexsl), &ds_hexsl, NULL); 13694201a95eSRic Aleshire if (error) 1370be6fd75aSMatthew Ahrens return (SET_ERROR(EACCES)); 13714201a95eSRic Aleshire 13724201a95eSRic Aleshire /* 13734201a95eSRic Aleshire * If labeling is NOT enabled, then disallow the mount of datasets 13744201a95eSRic Aleshire * which have a non-default label already. No other label checks 13754201a95eSRic Aleshire * are needed. 13764201a95eSRic Aleshire */ 13774201a95eSRic Aleshire if (!is_system_labeled()) { 13784201a95eSRic Aleshire if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0) 13794201a95eSRic Aleshire return (0); 1380be6fd75aSMatthew Ahrens return (SET_ERROR(EACCES)); 13814201a95eSRic Aleshire } 13824201a95eSRic Aleshire 13834201a95eSRic Aleshire /* 13844201a95eSRic Aleshire * Get the label of the mountpoint. If mounting into the global 13854201a95eSRic Aleshire * zone (i.e. mountpoint is not within an active zone and the 13864201a95eSRic Aleshire * zoned property is off), the label must be default or 13874201a95eSRic Aleshire * admin_low/admin_high only; no other checks are needed. 13884201a95eSRic Aleshire */ 13894201a95eSRic Aleshire mntzone = zone_find_by_any_path(refstr_value(vfsp->vfs_mntpt), B_FALSE); 13904201a95eSRic Aleshire if (mntzone->zone_id == GLOBAL_ZONEID) { 13914201a95eSRic Aleshire uint64_t zoned; 13924201a95eSRic Aleshire 13934201a95eSRic Aleshire zone_rele(mntzone); 13944201a95eSRic Aleshire 13954201a95eSRic Aleshire if (dsl_prop_get_integer(osname, 13964201a95eSRic Aleshire zfs_prop_to_name(ZFS_PROP_ZONED), &zoned, NULL)) 1397be6fd75aSMatthew Ahrens return (SET_ERROR(EACCES)); 13984201a95eSRic Aleshire if (!zoned) 13994201a95eSRic Aleshire return (zfs_check_global_label(osname, ds_hexsl)); 14004201a95eSRic Aleshire else 14014201a95eSRic Aleshire /* 14024201a95eSRic Aleshire * This is the case of a zone dataset being mounted 14034201a95eSRic Aleshire * initially, before the zone has been fully created; 14044201a95eSRic Aleshire * allow this mount into global zone. 14054201a95eSRic Aleshire */ 14064201a95eSRic Aleshire return (0); 14074201a95eSRic Aleshire } 14084201a95eSRic Aleshire 14094201a95eSRic Aleshire mnt_tsl = mntzone->zone_slabel; 14104201a95eSRic Aleshire ASSERT(mnt_tsl != NULL); 14114201a95eSRic Aleshire label_hold(mnt_tsl); 14124201a95eSRic Aleshire mnt_sl = label2bslabel(mnt_tsl); 14134201a95eSRic Aleshire 14144201a95eSRic Aleshire if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0) { 14154201a95eSRic Aleshire /* 14164201a95eSRic Aleshire * The dataset doesn't have a real label, so fabricate one. 14174201a95eSRic Aleshire */ 14184201a95eSRic Aleshire char *str = NULL; 14194201a95eSRic Aleshire 14204201a95eSRic Aleshire if (l_to_str_internal(mnt_sl, &str) == 0 && 14213b2aab18SMatthew Ahrens dsl_prop_set_string(osname, 14223b2aab18SMatthew Ahrens zfs_prop_to_name(ZFS_PROP_MLSLABEL), 14233b2aab18SMatthew Ahrens ZPROP_SRC_LOCAL, str) == 0) 14244201a95eSRic Aleshire retv = 0; 14254201a95eSRic Aleshire if (str != NULL) 14264201a95eSRic Aleshire kmem_free(str, strlen(str) + 1); 14274201a95eSRic Aleshire } else if (hexstr_to_label(ds_hexsl, &ds_sl) == 0) { 14284201a95eSRic Aleshire /* 14294201a95eSRic Aleshire * Now compare labels to complete the MAC check. If the 14304201a95eSRic Aleshire * labels are equal then allow access. If the mountpoint 14314201a95eSRic Aleshire * label dominates the dataset label, allow readonly access. 14324201a95eSRic Aleshire * Otherwise, access is denied. 14334201a95eSRic Aleshire */ 14344201a95eSRic Aleshire if (blequal(mnt_sl, &ds_sl)) 14354201a95eSRic Aleshire retv = 0; 14364201a95eSRic Aleshire else if (bldominates(mnt_sl, &ds_sl)) { 14374201a95eSRic Aleshire vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0); 14384201a95eSRic Aleshire retv = 0; 14394201a95eSRic Aleshire } 14404201a95eSRic Aleshire } 14414201a95eSRic Aleshire 14424201a95eSRic Aleshire label_rele(mnt_tsl); 14434201a95eSRic Aleshire zone_rele(mntzone); 14444201a95eSRic Aleshire return (retv); 14454201a95eSRic Aleshire } 14464201a95eSRic Aleshire 1447ea8dc4b6Seschrock static int 1448ea8dc4b6Seschrock zfs_mountroot(vfs_t *vfsp, enum whymountroot why) 1449ea8dc4b6Seschrock { 1450ea8dc4b6Seschrock int error = 0; 1451ea8dc4b6Seschrock static int zfsrootdone = 0; 1452ea8dc4b6Seschrock zfsvfs_t *zfsvfs = NULL; 1453ea8dc4b6Seschrock znode_t *zp = NULL; 1454ea8dc4b6Seschrock vnode_t *vp = NULL; 1455e7cbe64fSgw25295 char *zfs_bootfs; 1456051aabe6Staylor char *zfs_devid; 1457ea8dc4b6Seschrock 1458ea8dc4b6Seschrock ASSERT(vfsp); 1459ea8dc4b6Seschrock 1460ea8dc4b6Seschrock /* 1461b1b8ab34Slling * The filesystem that we mount as root is defined in the 1462e7cbe64fSgw25295 * boot property "zfs-bootfs" with a format of 1463e7cbe64fSgw25295 * "poolname/root-dataset-objnum". 1464ea8dc4b6Seschrock */ 1465ea8dc4b6Seschrock if (why == ROOT_INIT) { 1466ea8dc4b6Seschrock if (zfsrootdone++) 1467be6fd75aSMatthew Ahrens return (SET_ERROR(EBUSY)); 1468e7cbe64fSgw25295 /* 1469e7cbe64fSgw25295 * the process of doing a spa_load will require the 1470e7cbe64fSgw25295 * clock to be set before we could (for example) do 1471e7cbe64fSgw25295 * something better by looking at the timestamp on 1472e7cbe64fSgw25295 * an uberblock, so just set it to -1. 1473e7cbe64fSgw25295 */ 1474e7cbe64fSgw25295 clkset(-1); 1475ea8dc4b6Seschrock 1476051aabe6Staylor if ((zfs_bootfs = spa_get_bootprop("zfs-bootfs")) == NULL) { 1477051aabe6Staylor cmn_err(CE_NOTE, "spa_get_bootfs: can not get " 1478051aabe6Staylor "bootfs name"); 1479be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 1480986fd29aSsetje } 1481051aabe6Staylor zfs_devid = spa_get_bootprop("diskdevid"); 1482051aabe6Staylor error = spa_import_rootpool(rootfs.bo_name, zfs_devid); 1483051aabe6Staylor if (zfs_devid) 1484051aabe6Staylor spa_free_bootprop(zfs_devid); 1485051aabe6Staylor if (error) { 1486051aabe6Staylor spa_free_bootprop(zfs_bootfs); 1487051aabe6Staylor cmn_err(CE_NOTE, "spa_import_rootpool: error %d", 1488e7cbe64fSgw25295 error); 1489b1b8ab34Slling return (error); 1490e7cbe64fSgw25295 } 1491e7cbe64fSgw25295 if (error = zfs_parse_bootfs(zfs_bootfs, rootfs.bo_name)) { 1492051aabe6Staylor spa_free_bootprop(zfs_bootfs); 1493051aabe6Staylor cmn_err(CE_NOTE, "zfs_parse_bootfs: error %d", 1494e7cbe64fSgw25295 error); 1495e7cbe64fSgw25295 return (error); 1496e7cbe64fSgw25295 } 1497e7cbe64fSgw25295 1498051aabe6Staylor spa_free_bootprop(zfs_bootfs); 1499ea8dc4b6Seschrock 1500ea8dc4b6Seschrock if (error = vfs_lock(vfsp)) 1501ea8dc4b6Seschrock return (error); 1502ea8dc4b6Seschrock 1503088f3894Sahrens if (error = zfs_domount(vfsp, rootfs.bo_name)) { 1504051aabe6Staylor cmn_err(CE_NOTE, "zfs_domount: error %d", error); 1505ea8dc4b6Seschrock goto out; 1506e7cbe64fSgw25295 } 1507ea8dc4b6Seschrock 1508ea8dc4b6Seschrock zfsvfs = (zfsvfs_t *)vfsp->vfs_data; 1509ea8dc4b6Seschrock ASSERT(zfsvfs); 1510e7cbe64fSgw25295 if (error = zfs_zget(zfsvfs, zfsvfs->z_root, &zp)) { 1511051aabe6Staylor cmn_err(CE_NOTE, "zfs_zget: error %d", error); 1512ea8dc4b6Seschrock goto out; 1513e7cbe64fSgw25295 } 1514ea8dc4b6Seschrock 1515ea8dc4b6Seschrock vp = ZTOV(zp); 1516ea8dc4b6Seschrock mutex_enter(&vp->v_lock); 1517ea8dc4b6Seschrock vp->v_flag |= VROOT; 1518ea8dc4b6Seschrock mutex_exit(&vp->v_lock); 1519ea8dc4b6Seschrock rootvp = vp; 1520ea8dc4b6Seschrock 1521ea8dc4b6Seschrock /* 152240d3dfe1Smarks * Leave rootvp held. The root file system is never unmounted. 1523ea8dc4b6Seschrock */ 1524ea8dc4b6Seschrock 1525ea8dc4b6Seschrock vfs_add((struct vnode *)0, vfsp, 1526ea8dc4b6Seschrock (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0); 1527ea8dc4b6Seschrock out: 1528ea8dc4b6Seschrock vfs_unlock(vfsp); 1529e7cbe64fSgw25295 return (error); 1530ea8dc4b6Seschrock } else if (why == ROOT_REMOUNT) { 1531ea8dc4b6Seschrock readonly_changed_cb(vfsp->vfs_data, B_FALSE); 1532ea8dc4b6Seschrock vfsp->vfs_flag |= VFS_REMOUNT; 1533b510d378Slling 1534b510d378Slling /* refresh mount options */ 1535b510d378Slling zfs_unregister_callbacks(vfsp->vfs_data); 1536b510d378Slling return (zfs_register_callbacks(vfsp)); 1537b510d378Slling 1538ea8dc4b6Seschrock } else if (why == ROOT_UNMOUNT) { 1539ea8dc4b6Seschrock zfs_unregister_callbacks((zfsvfs_t *)vfsp->vfs_data); 1540ea8dc4b6Seschrock (void) zfs_sync(vfsp, 0, 0); 1541ea8dc4b6Seschrock return (0); 1542ea8dc4b6Seschrock } 1543ea8dc4b6Seschrock 1544ea8dc4b6Seschrock /* 1545ea8dc4b6Seschrock * if "why" is equal to anything else other than ROOT_INIT, 1546ea8dc4b6Seschrock * ROOT_REMOUNT, or ROOT_UNMOUNT, we do not support it. 1547ea8dc4b6Seschrock */ 1548be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 1549ea8dc4b6Seschrock } 1550ea8dc4b6Seschrock 1551ea8dc4b6Seschrock /*ARGSUSED*/ 1552ea8dc4b6Seschrock static int 1553ea8dc4b6Seschrock zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) 1554ea8dc4b6Seschrock { 1555ea8dc4b6Seschrock char *osname; 1556ea8dc4b6Seschrock pathname_t spn; 1557ea8dc4b6Seschrock int error = 0; 1558ea8dc4b6Seschrock uio_seg_t fromspace = (uap->flags & MS_SYSSPACE) ? 1559ea8dc4b6Seschrock UIO_SYSSPACE : UIO_USERSPACE; 1560ea8dc4b6Seschrock int canwrite; 1561ea8dc4b6Seschrock 1562ea8dc4b6Seschrock if (mvp->v_type != VDIR) 1563be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTDIR)); 1564ea8dc4b6Seschrock 1565ea8dc4b6Seschrock mutex_enter(&mvp->v_lock); 1566ea8dc4b6Seschrock if ((uap->flags & MS_REMOUNT) == 0 && 1567ea8dc4b6Seschrock (uap->flags & MS_OVERLAY) == 0 && 1568ea8dc4b6Seschrock (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { 1569ea8dc4b6Seschrock mutex_exit(&mvp->v_lock); 1570be6fd75aSMatthew Ahrens return (SET_ERROR(EBUSY)); 1571ea8dc4b6Seschrock } 1572ea8dc4b6Seschrock mutex_exit(&mvp->v_lock); 1573ea8dc4b6Seschrock 1574ea8dc4b6Seschrock /* 1575ea8dc4b6Seschrock * ZFS does not support passing unparsed data in via MS_DATA. 1576ea8dc4b6Seschrock * Users should use the MS_OPTIONSTR interface; this means 1577ea8dc4b6Seschrock * that all option parsing is already done and the options struct 1578ea8dc4b6Seschrock * can be interrogated. 1579ea8dc4b6Seschrock */ 1580ea8dc4b6Seschrock if ((uap->flags & MS_DATA) && uap->datalen > 0) 1581be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 1582ea8dc4b6Seschrock 1583ea8dc4b6Seschrock /* 1584ea8dc4b6Seschrock * Get the objset name (the "special" mount argument). 1585ea8dc4b6Seschrock */ 1586ea8dc4b6Seschrock if (error = pn_get(uap->spec, fromspace, &spn)) 1587ea8dc4b6Seschrock return (error); 1588ea8dc4b6Seschrock 1589ea8dc4b6Seschrock osname = spn.pn_path; 1590ea8dc4b6Seschrock 1591ecd6cf80Smarks /* 1592ecd6cf80Smarks * Check for mount privilege? 1593ecd6cf80Smarks * 1594ecd6cf80Smarks * If we don't have privilege then see if 1595ecd6cf80Smarks * we have local permission to allow it 1596ecd6cf80Smarks */ 1597ecd6cf80Smarks error = secpolicy_fs_mount(cr, mvp, vfsp); 1598ecd6cf80Smarks if (error) { 159998679b56SMark Shellenbaum if (dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) == 0) { 1600ecd6cf80Smarks vattr_t vattr; 1601ecd6cf80Smarks 1602ecd6cf80Smarks /* 1603ecd6cf80Smarks * Make sure user is the owner of the mount point 1604ecd6cf80Smarks * or has sufficient privileges. 1605ecd6cf80Smarks */ 1606ecd6cf80Smarks 1607ecd6cf80Smarks vattr.va_mask = AT_UID; 1608ecd6cf80Smarks 160998679b56SMark Shellenbaum if (VOP_GETATTR(mvp, &vattr, 0, cr, NULL)) { 1610ea8dc4b6Seschrock goto out; 1611ecd6cf80Smarks } 1612ecd6cf80Smarks 16132459a9eaSmarks if (secpolicy_vnode_owner(cr, vattr.va_uid) != 0 && 16142459a9eaSmarks VOP_ACCESS(mvp, VWRITE, 0, cr, NULL) != 0) { 1615ecd6cf80Smarks goto out; 1616ecd6cf80Smarks } 1617ecd6cf80Smarks secpolicy_fs_mount_clearopts(cr, vfsp); 1618ecd6cf80Smarks } else { 1619ecd6cf80Smarks goto out; 1620ecd6cf80Smarks } 1621ecd6cf80Smarks } 1622ea8dc4b6Seschrock 1623ea8dc4b6Seschrock /* 1624ea8dc4b6Seschrock * Refuse to mount a filesystem if we are in a local zone and the 1625ea8dc4b6Seschrock * dataset is not visible. 1626ea8dc4b6Seschrock */ 1627ea8dc4b6Seschrock if (!INGLOBALZONE(curproc) && 1628ea8dc4b6Seschrock (!zone_dataset_visible(osname, &canwrite) || !canwrite)) { 1629be6fd75aSMatthew Ahrens error = SET_ERROR(EPERM); 1630ea8dc4b6Seschrock goto out; 1631ea8dc4b6Seschrock } 1632ea8dc4b6Seschrock 16334201a95eSRic Aleshire error = zfs_mount_label_policy(vfsp, osname); 16344201a95eSRic Aleshire if (error) 16354201a95eSRic Aleshire goto out; 16364201a95eSRic Aleshire 1637b510d378Slling /* 1638b510d378Slling * When doing a remount, we simply refresh our temporary properties 1639b510d378Slling * according to those options set in the current VFS options. 1640b510d378Slling */ 1641b510d378Slling if (uap->flags & MS_REMOUNT) { 1642b510d378Slling /* refresh mount options */ 1643b510d378Slling zfs_unregister_callbacks(vfsp->vfs_data); 1644b510d378Slling error = zfs_register_callbacks(vfsp); 1645b510d378Slling goto out; 1646b510d378Slling } 1647b510d378Slling 1648088f3894Sahrens error = zfs_domount(vfsp, osname); 1649ea8dc4b6Seschrock 1650142ae85dSChris Kirby /* 1651142ae85dSChris Kirby * Add an extra VFS_HOLD on our parent vfs so that it can't 1652142ae85dSChris Kirby * disappear due to a forced unmount. 1653142ae85dSChris Kirby */ 1654984a131bSChris Kirby if (error == 0 && ((zfsvfs_t *)vfsp->vfs_data)->z_issnap) 1655142ae85dSChris Kirby VFS_HOLD(mvp->v_vfsp); 1656142ae85dSChris Kirby 1657ea8dc4b6Seschrock out: 1658f0fa03f5SAndreas Jaekel if (error == 0) { 1659d78b796cSAndreas Jaekel rw_enter(&rz_zev_rwlock, RW_READER); 1660d78b796cSAndreas Jaekel if (rz_zev_callbacks && rz_zev_callbacks->rz_zev_zfs_mount) 1661d78b796cSAndreas Jaekel rz_zev_callbacks->rz_zev_zfs_mount(vfsp, mvp, osname, 1662d78b796cSAndreas Jaekel uap->flags & MS_REMOUNT ? B_TRUE : B_FALSE); 1663d78b796cSAndreas Jaekel rw_exit(&rz_zev_rwlock); 1664f0fa03f5SAndreas Jaekel } 1665fa9e4066Sahrens pn_free(&spn); 1666fa9e4066Sahrens return (error); 1667fa9e4066Sahrens } 1668fa9e4066Sahrens 1669fa9e4066Sahrens static int 1670fa9e4066Sahrens zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp) 1671fa9e4066Sahrens { 1672fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1673fa9e4066Sahrens dev32_t d32; 1674a2eea2e1Sahrens uint64_t refdbytes, availbytes, usedobjs, availobjs; 1675fa9e4066Sahrens 1676fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1677fa9e4066Sahrens 1678a2eea2e1Sahrens dmu_objset_space(zfsvfs->z_os, 1679a2eea2e1Sahrens &refdbytes, &availbytes, &usedobjs, &availobjs); 1680fa9e4066Sahrens 1681fa9e4066Sahrens /* 1682fa9e4066Sahrens * The underlying storage pool actually uses multiple block sizes. 1683fa9e4066Sahrens * We report the fragsize as the smallest block size we support, 1684fa9e4066Sahrens * and we report our blocksize as the filesystem's maximum blocksize. 1685fa9e4066Sahrens */ 1686fa9e4066Sahrens statp->f_frsize = 1UL << SPA_MINBLOCKSHIFT; 1687fa9e4066Sahrens statp->f_bsize = zfsvfs->z_max_blksz; 1688fa9e4066Sahrens 1689fa9e4066Sahrens /* 1690fa9e4066Sahrens * The following report "total" blocks of various kinds in the 1691fa9e4066Sahrens * file system, but reported in terms of f_frsize - the 1692fa9e4066Sahrens * "fragment" size. 1693fa9e4066Sahrens */ 1694fa9e4066Sahrens 1695a2eea2e1Sahrens statp->f_blocks = (refdbytes + availbytes) >> SPA_MINBLOCKSHIFT; 1696a2eea2e1Sahrens statp->f_bfree = availbytes >> SPA_MINBLOCKSHIFT; 1697fa9e4066Sahrens statp->f_bavail = statp->f_bfree; /* no root reservation */ 1698fa9e4066Sahrens 1699fa9e4066Sahrens /* 1700fa9e4066Sahrens * statvfs() should really be called statufs(), because it assumes 1701fa9e4066Sahrens * static metadata. ZFS doesn't preallocate files, so the best 1702fa9e4066Sahrens * we can do is report the max that could possibly fit in f_files, 1703fa9e4066Sahrens * and that minus the number actually used in f_ffree. 1704fa9e4066Sahrens * For f_ffree, report the smaller of the number of object available 1705fa9e4066Sahrens * and the number of blocks (each object will take at least a block). 1706fa9e4066Sahrens */ 1707a2eea2e1Sahrens statp->f_ffree = MIN(availobjs, statp->f_bfree); 1708fa9e4066Sahrens statp->f_favail = statp->f_ffree; /* no "root reservation" */ 1709a2eea2e1Sahrens statp->f_files = statp->f_ffree + usedobjs; 1710fa9e4066Sahrens 1711fa9e4066Sahrens (void) cmpldev(&d32, vfsp->vfs_dev); 1712fa9e4066Sahrens statp->f_fsid = d32; 1713fa9e4066Sahrens 1714fa9e4066Sahrens /* 1715fa9e4066Sahrens * We're a zfs filesystem. 1716fa9e4066Sahrens */ 1717fa9e4066Sahrens (void) strcpy(statp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 1718fa9e4066Sahrens 1719a5be7ebbSmarks statp->f_flag = vf_to_stf(vfsp->vfs_flag); 1720fa9e4066Sahrens 172140a5c998SMatthew Ahrens statp->f_namemax = MAXNAMELEN - 1; 1722fa9e4066Sahrens 1723fa9e4066Sahrens /* 1724fa9e4066Sahrens * We have all of 32 characters to stuff a string here. 1725fa9e4066Sahrens * Is there anything useful we could/should provide? 1726fa9e4066Sahrens */ 1727fa9e4066Sahrens bzero(statp->f_fstr, sizeof (statp->f_fstr)); 1728fa9e4066Sahrens 1729fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1730fa9e4066Sahrens return (0); 1731fa9e4066Sahrens } 1732fa9e4066Sahrens 1733fa9e4066Sahrens static int 1734fa9e4066Sahrens zfs_root(vfs_t *vfsp, vnode_t **vpp) 1735fa9e4066Sahrens { 1736fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1737fa9e4066Sahrens znode_t *rootzp; 1738fa9e4066Sahrens int error; 1739fa9e4066Sahrens 1740fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1741fa9e4066Sahrens 1742fa9e4066Sahrens error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); 1743fa9e4066Sahrens if (error == 0) 1744fa9e4066Sahrens *vpp = ZTOV(rootzp); 1745fa9e4066Sahrens 1746fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1747fa9e4066Sahrens return (error); 1748fa9e4066Sahrens } 1749fa9e4066Sahrens 1750f18faf3fSek110237 /* 1751f18faf3fSek110237 * Teardown the zfsvfs::z_os. 1752f18faf3fSek110237 * 1753f18faf3fSek110237 * Note, if 'unmounting' if FALSE, we return with the 'z_teardown_lock' 1754f18faf3fSek110237 * and 'z_teardown_inactive_lock' held. 1755f18faf3fSek110237 */ 1756f18faf3fSek110237 static int 1757f18faf3fSek110237 zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting) 1758f18faf3fSek110237 { 1759874395d5Smaybee znode_t *zp; 1760f18faf3fSek110237 1761c9030f6cSAlexander Motin rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); 1762f18faf3fSek110237 1763f18faf3fSek110237 if (!unmounting) { 1764f18faf3fSek110237 /* 1765f18faf3fSek110237 * We purge the parent filesystem's vfsp as the parent 1766f18faf3fSek110237 * filesystem and all of its snapshots have their vnode's 1767f18faf3fSek110237 * v_vfsp set to the parent's filesystem's vfsp. Note, 1768f18faf3fSek110237 * 'z_parent' is self referential for non-snapshots. 1769f18faf3fSek110237 */ 1770f18faf3fSek110237 (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0); 1771f18faf3fSek110237 } 1772f18faf3fSek110237 1773f18faf3fSek110237 /* 1774f18faf3fSek110237 * Close the zil. NB: Can't close the zil while zfs_inactive 1775f18faf3fSek110237 * threads are blocked as zil_close can call zfs_inactive. 1776f18faf3fSek110237 */ 1777f18faf3fSek110237 if (zfsvfs->z_log) { 1778f18faf3fSek110237 zil_close(zfsvfs->z_log); 1779f18faf3fSek110237 zfsvfs->z_log = NULL; 1780f18faf3fSek110237 } 1781f18faf3fSek110237 1782f18faf3fSek110237 rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_WRITER); 1783f18faf3fSek110237 1784f18faf3fSek110237 /* 1785f18faf3fSek110237 * If we are not unmounting (ie: online recv) and someone already 1786f18faf3fSek110237 * unmounted this file system while we were doing the switcheroo, 1787f18faf3fSek110237 * or a reopen of z_os failed then just bail out now. 1788f18faf3fSek110237 */ 1789f18faf3fSek110237 if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) { 1790f18faf3fSek110237 rw_exit(&zfsvfs->z_teardown_inactive_lock); 1791c9030f6cSAlexander Motin rrm_exit(&zfsvfs->z_teardown_lock, FTAG); 1792be6fd75aSMatthew Ahrens return (SET_ERROR(EIO)); 1793f18faf3fSek110237 } 1794f18faf3fSek110237 1795f18faf3fSek110237 /* 1796f18faf3fSek110237 * At this point there are no vops active, and any new vops will 1797f18faf3fSek110237 * fail with EIO since we have z_teardown_lock for writer (only 1798f18faf3fSek110237 * relavent for forced unmount). 1799f18faf3fSek110237 * 1800f18faf3fSek110237 * Release all holds on dbufs. 1801f18faf3fSek110237 */ 1802f18faf3fSek110237 mutex_enter(&zfsvfs->z_znodes_lock); 1803874395d5Smaybee for (zp = list_head(&zfsvfs->z_all_znodes); zp != NULL; 1804874395d5Smaybee zp = list_next(&zfsvfs->z_all_znodes, zp)) 18050a586ceaSMark Shellenbaum if (zp->z_sa_hdl) { 1806874395d5Smaybee ASSERT(ZTOV(zp)->v_count > 0); 1807874395d5Smaybee zfs_znode_dmu_fini(zp); 1808f18faf3fSek110237 } 1809f18faf3fSek110237 mutex_exit(&zfsvfs->z_znodes_lock); 1810f18faf3fSek110237 1811f18faf3fSek110237 /* 1812f18faf3fSek110237 * If we are unmounting, set the unmounted flag and let new vops 1813f18faf3fSek110237 * unblock. zfs_inactive will have the unmounted behavior, and all 1814f18faf3fSek110237 * other vops will fail with EIO. 1815f18faf3fSek110237 */ 1816f18faf3fSek110237 if (unmounting) { 1817f18faf3fSek110237 zfsvfs->z_unmounted = B_TRUE; 1818c9030f6cSAlexander Motin rrm_exit(&zfsvfs->z_teardown_lock, FTAG); 1819f18faf3fSek110237 rw_exit(&zfsvfs->z_teardown_inactive_lock); 1820f18faf3fSek110237 } 1821f18faf3fSek110237 1822f18faf3fSek110237 /* 1823f18faf3fSek110237 * z_os will be NULL if there was an error in attempting to reopen 1824f18faf3fSek110237 * zfsvfs, so just return as the properties had already been 1825f18faf3fSek110237 * unregistered and cached data had been evicted before. 1826f18faf3fSek110237 */ 1827f18faf3fSek110237 if (zfsvfs->z_os == NULL) 1828f18faf3fSek110237 return (0); 1829f18faf3fSek110237 1830f18faf3fSek110237 /* 1831f18faf3fSek110237 * Unregister properties. 1832f18faf3fSek110237 */ 1833f18faf3fSek110237 zfs_unregister_callbacks(zfsvfs); 1834f18faf3fSek110237 1835f18faf3fSek110237 /* 1836f18faf3fSek110237 * Evict cached data 1837f18faf3fSek110237 */ 18382e2c1355SMatthew Ahrens if (dsl_dataset_is_dirty(dmu_objset_ds(zfsvfs->z_os)) && 18392e2c1355SMatthew Ahrens !(zfsvfs->z_vfs->vfs_flag & VFS_RDONLY)) 1840d3248e8bSmaybee txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0); 18413b2aab18SMatthew Ahrens dmu_objset_evict_dbufs(zfsvfs->z_os); 1842f18faf3fSek110237 1843f18faf3fSek110237 return (0); 1844f18faf3fSek110237 } 1845f18faf3fSek110237 1846fa9e4066Sahrens /*ARGSUSED*/ 1847fa9e4066Sahrens static int 1848fa9e4066Sahrens zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr) 1849fa9e4066Sahrens { 1850fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1851f18faf3fSek110237 objset_t *os; 1852fa9e4066Sahrens int ret; 1853fa9e4066Sahrens 1854ecd6cf80Smarks ret = secpolicy_fs_unmount(cr, vfsp); 1855ecd6cf80Smarks if (ret) { 185698679b56SMark Shellenbaum if (dsl_deleg_access((char *)refstr_value(vfsp->vfs_resource), 185798679b56SMark Shellenbaum ZFS_DELEG_PERM_MOUNT, cr)) 1858fa9e4066Sahrens return (ret); 1859ecd6cf80Smarks } 1860033f9833Sek110237 1861ed097989Sek110237 /* 1862ed097989Sek110237 * We purge the parent filesystem's vfsp as the parent filesystem 1863ed097989Sek110237 * and all of its snapshots have their vnode's v_vfsp set to the 1864ed097989Sek110237 * parent's filesystem's vfsp. Note, 'z_parent' is self 1865ed097989Sek110237 * referential for non-snapshots. 1866ed097989Sek110237 */ 1867ed097989Sek110237 (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0); 1868033f9833Sek110237 1869fa9e4066Sahrens /* 1870fa9e4066Sahrens * Unmount any snapshots mounted under .zfs before unmounting the 1871fa9e4066Sahrens * dataset itself. 1872fa9e4066Sahrens */ 1873fa9e4066Sahrens if (zfsvfs->z_ctldir != NULL && 1874ecd6cf80Smarks (ret = zfsctl_umount_snapshots(vfsp, fflag, cr)) != 0) { 1875fa9e4066Sahrens return (ret); 1876ecd6cf80Smarks } 1877fa9e4066Sahrens 187891ebeef5Sahrens if (!(fflag & MS_FORCE)) { 1879fa9e4066Sahrens /* 1880fa9e4066Sahrens * Check the number of active vnodes in the file system. 188191ebeef5Sahrens * Our count is maintained in the vfs structure, but the 188291ebeef5Sahrens * number is off by 1 to indicate a hold on the vfs 188391ebeef5Sahrens * structure itself. 1884fa9e4066Sahrens * 188591ebeef5Sahrens * The '.zfs' directory maintains a reference of its 188691ebeef5Sahrens * own, and any active references underneath are 188791ebeef5Sahrens * reflected in the vnode count. 1888fa9e4066Sahrens */ 1889fa9e4066Sahrens if (zfsvfs->z_ctldir == NULL) { 1890893a6d32Sahrens if (vfsp->vfs_count > 1) 1891be6fd75aSMatthew Ahrens return (SET_ERROR(EBUSY)); 1892fa9e4066Sahrens } else { 1893fa9e4066Sahrens if (vfsp->vfs_count > 2 || 1894f18faf3fSek110237 zfsvfs->z_ctldir->v_count > 1) 1895be6fd75aSMatthew Ahrens return (SET_ERROR(EBUSY)); 1896fa9e4066Sahrens } 1897fa9e4066Sahrens } 1898fa9e4066Sahrens 1899fa9e4066Sahrens vfsp->vfs_flag |= VFS_UNMOUNTED; 190091ebeef5Sahrens 190110874358SAndreas Jaekel rw_enter(&rz_zev_rwlock, RW_READER); 190210874358SAndreas Jaekel if (rz_zev_callbacks && rz_zev_callbacks->rz_zev_zfs_umount) 190310874358SAndreas Jaekel rz_zev_callbacks->rz_zev_zfs_umount(vfsp); 190410874358SAndreas Jaekel rw_exit(&rz_zev_rwlock); 190510874358SAndreas Jaekel 1906f18faf3fSek110237 VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0); 1907f18faf3fSek110237 os = zfsvfs->z_os; 190891ebeef5Sahrens 190991ebeef5Sahrens /* 1910f18faf3fSek110237 * z_os will be NULL if there was an error in 1911f18faf3fSek110237 * attempting to reopen zfsvfs. 191291ebeef5Sahrens */ 1913f18faf3fSek110237 if (os != NULL) { 191491ebeef5Sahrens /* 1915f18faf3fSek110237 * Unset the objset user_ptr. 191691ebeef5Sahrens */ 1917503ad85cSMatthew Ahrens mutex_enter(&os->os_user_ptr_lock); 1918f18faf3fSek110237 dmu_objset_set_user(os, NULL); 1919503ad85cSMatthew Ahrens mutex_exit(&os->os_user_ptr_lock); 192091ebeef5Sahrens 192191ebeef5Sahrens /* 1922745cd3c5Smaybee * Finally release the objset 192391ebeef5Sahrens */ 1924503ad85cSMatthew Ahrens dmu_objset_disown(os, zfsvfs); 1925f18faf3fSek110237 } 192691ebeef5Sahrens 192791ebeef5Sahrens /* 192891ebeef5Sahrens * We can now safely destroy the '.zfs' directory node. 192991ebeef5Sahrens */ 193091ebeef5Sahrens if (zfsvfs->z_ctldir != NULL) 193191ebeef5Sahrens zfsctl_destroy(zfsvfs); 1932fa9e4066Sahrens 1933fa9e4066Sahrens return (0); 1934fa9e4066Sahrens } 1935fa9e4066Sahrens 1936fa9e4066Sahrens static int 1937fa9e4066Sahrens zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp) 1938fa9e4066Sahrens { 1939fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1940fa9e4066Sahrens znode_t *zp; 1941fa9e4066Sahrens uint64_t object = 0; 1942fa9e4066Sahrens uint64_t fid_gen = 0; 1943fa9e4066Sahrens uint64_t gen_mask; 1944fa9e4066Sahrens uint64_t zp_gen; 1945fa9e4066Sahrens int i, err; 1946fa9e4066Sahrens 1947fa9e4066Sahrens *vpp = NULL; 1948fa9e4066Sahrens 1949fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1950fa9e4066Sahrens 1951fa9e4066Sahrens if (fidp->fid_len == LONG_FID_LEN) { 1952fa9e4066Sahrens zfid_long_t *zlfid = (zfid_long_t *)fidp; 1953fa9e4066Sahrens uint64_t objsetid = 0; 1954fa9e4066Sahrens uint64_t setgen = 0; 1955fa9e4066Sahrens 1956fa9e4066Sahrens for (i = 0; i < sizeof (zlfid->zf_setid); i++) 1957fa9e4066Sahrens objsetid |= ((uint64_t)zlfid->zf_setid[i]) << (8 * i); 1958fa9e4066Sahrens 1959fa9e4066Sahrens for (i = 0; i < sizeof (zlfid->zf_setgen); i++) 1960fa9e4066Sahrens setgen |= ((uint64_t)zlfid->zf_setgen[i]) << (8 * i); 1961fa9e4066Sahrens 1962fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1963fa9e4066Sahrens 1964fa9e4066Sahrens err = zfsctl_lookup_objset(vfsp, objsetid, &zfsvfs); 1965fa9e4066Sahrens if (err) 1966be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 1967fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1968fa9e4066Sahrens } 1969fa9e4066Sahrens 1970fa9e4066Sahrens if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) { 1971fa9e4066Sahrens zfid_short_t *zfid = (zfid_short_t *)fidp; 1972fa9e4066Sahrens 1973fa9e4066Sahrens for (i = 0; i < sizeof (zfid->zf_object); i++) 1974fa9e4066Sahrens object |= ((uint64_t)zfid->zf_object[i]) << (8 * i); 1975fa9e4066Sahrens 1976fa9e4066Sahrens for (i = 0; i < sizeof (zfid->zf_gen); i++) 1977fa9e4066Sahrens fid_gen |= ((uint64_t)zfid->zf_gen[i]) << (8 * i); 1978fa9e4066Sahrens } else { 1979fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1980be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 1981fa9e4066Sahrens } 1982fa9e4066Sahrens 1983fa9e4066Sahrens /* A zero fid_gen means we are in the .zfs control directories */ 1984fa9e4066Sahrens if (fid_gen == 0 && 1985fa9e4066Sahrens (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) { 1986fa9e4066Sahrens *vpp = zfsvfs->z_ctldir; 1987fa9e4066Sahrens ASSERT(*vpp != NULL); 1988fa9e4066Sahrens if (object == ZFSCTL_INO_SNAPDIR) { 1989fa9e4066Sahrens VERIFY(zfsctl_root_lookup(*vpp, "snapshot", vpp, NULL, 1990da6c28aaSamw 0, NULL, NULL, NULL, NULL, NULL) == 0); 1991fa9e4066Sahrens } else { 1992fa9e4066Sahrens VN_HOLD(*vpp); 1993fa9e4066Sahrens } 1994fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1995fa9e4066Sahrens return (0); 1996fa9e4066Sahrens } 1997fa9e4066Sahrens 1998fa9e4066Sahrens gen_mask = -1ULL >> (64 - 8 * i); 1999fa9e4066Sahrens 2000fa9e4066Sahrens dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask); 2001fa9e4066Sahrens if (err = zfs_zget(zfsvfs, object, &zp)) { 2002fa9e4066Sahrens ZFS_EXIT(zfsvfs); 2003fa9e4066Sahrens return (err); 2004fa9e4066Sahrens } 20050a586ceaSMark Shellenbaum (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &zp_gen, 20060a586ceaSMark Shellenbaum sizeof (uint64_t)); 20070a586ceaSMark Shellenbaum zp_gen = zp_gen & gen_mask; 2008fa9e4066Sahrens if (zp_gen == 0) 2009fa9e4066Sahrens zp_gen = 1; 2010893a6d32Sahrens if (zp->z_unlinked || zp_gen != fid_gen) { 2011fa9e4066Sahrens dprintf("znode gen (%u) != fid gen (%u)\n", zp_gen, fid_gen); 2012fa9e4066Sahrens VN_RELE(ZTOV(zp)); 2013fa9e4066Sahrens ZFS_EXIT(zfsvfs); 2014be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 2015fa9e4066Sahrens } 2016fa9e4066Sahrens 2017fa9e4066Sahrens *vpp = ZTOV(zp); 2018fa9e4066Sahrens ZFS_EXIT(zfsvfs); 2019fa9e4066Sahrens return (0); 2020fa9e4066Sahrens } 2021fa9e4066Sahrens 2022f18faf3fSek110237 /* 2023f18faf3fSek110237 * Block out VOPs and close zfsvfs_t::z_os 2024f18faf3fSek110237 * 2025f18faf3fSek110237 * Note, if successful, then we return with the 'z_teardown_lock' and 202691948b51SKeith M Wesolowski * 'z_teardown_inactive_lock' write held. We leave ownership of the underlying 202791948b51SKeith M Wesolowski * dataset and objset intact so that they can be atomically handed off during 202891948b51SKeith M Wesolowski * a subsequent rollback or recv operation and the resume thereafter. 2029f18faf3fSek110237 */ 2030f18faf3fSek110237 int 2031503ad85cSMatthew Ahrens zfs_suspend_fs(zfsvfs_t *zfsvfs) 2032f18faf3fSek110237 { 2033f18faf3fSek110237 int error; 2034f18faf3fSek110237 2035f18faf3fSek110237 if ((error = zfsvfs_teardown(zfsvfs, B_FALSE)) != 0) 2036f18faf3fSek110237 return (error); 2037f18faf3fSek110237 2038f18faf3fSek110237 return (0); 2039f18faf3fSek110237 } 2040f18faf3fSek110237 2041f18faf3fSek110237 /* 204291948b51SKeith M Wesolowski * Rebuild SA and release VOPs. Note that ownership of the underlying dataset 204391948b51SKeith M Wesolowski * is an invariant across any of the operations that can be performed while the 204491948b51SKeith M Wesolowski * filesystem was suspended. Whether it succeeded or failed, the preconditions 204591948b51SKeith M Wesolowski * are the same: the relevant objset and associated dataset are owned by 204691948b51SKeith M Wesolowski * zfsvfs, held, and long held on entry. 2047f18faf3fSek110237 */ 2048f18faf3fSek110237 int 2049503ad85cSMatthew Ahrens zfs_resume_fs(zfsvfs_t *zfsvfs, const char *osname) 2050f18faf3fSek110237 { 205144bffe01SMark Shellenbaum int err; 205291948b51SKeith M Wesolowski znode_t *zp; 205391948b51SKeith M Wesolowski uint64_t sa_obj = 0; 2054f18faf3fSek110237 2055c9030f6cSAlexander Motin ASSERT(RRM_WRITE_HELD(&zfsvfs->z_teardown_lock)); 2056f18faf3fSek110237 ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock)); 2057f18faf3fSek110237 205891948b51SKeith M Wesolowski /* 205991948b51SKeith M Wesolowski * We already own this, so just hold and rele it to update the 206091948b51SKeith M Wesolowski * objset_t, as the one we had before may have been evicted. 206191948b51SKeith M Wesolowski */ 206291948b51SKeith M Wesolowski VERIFY0(dmu_objset_hold(osname, zfsvfs, &zfsvfs->z_os)); 206391948b51SKeith M Wesolowski VERIFY3P(zfsvfs->z_os->os_dsl_dataset->ds_owner, ==, zfsvfs); 206491948b51SKeith M Wesolowski VERIFY(dsl_dataset_long_held(zfsvfs->z_os->os_dsl_dataset)); 206591948b51SKeith M Wesolowski dmu_objset_rele(zfsvfs->z_os, zfsvfs); 20660a586ceaSMark Shellenbaum 206744bffe01SMark Shellenbaum /* 206844bffe01SMark Shellenbaum * Make sure version hasn't changed 206944bffe01SMark Shellenbaum */ 20700a586ceaSMark Shellenbaum 207144bffe01SMark Shellenbaum err = zfs_get_zplprop(zfsvfs->z_os, ZFS_PROP_VERSION, 207244bffe01SMark Shellenbaum &zfsvfs->z_version); 207344bffe01SMark Shellenbaum 207444bffe01SMark Shellenbaum if (err) 20750a586ceaSMark Shellenbaum goto bail; 20760a586ceaSMark Shellenbaum 207744bffe01SMark Shellenbaum err = zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ, 207844bffe01SMark Shellenbaum ZFS_SA_ATTRS, 8, 1, &sa_obj); 207944bffe01SMark Shellenbaum 208044bffe01SMark Shellenbaum if (err && zfsvfs->z_version >= ZPL_VERSION_SA) 208144bffe01SMark Shellenbaum goto bail; 20820a586ceaSMark Shellenbaum 20831d8ccc7bSMark Shellenbaum if ((err = sa_setup(zfsvfs->z_os, sa_obj, 20841d8ccc7bSMark Shellenbaum zfs_attr_table, ZPL_END, &zfsvfs->z_attr_table)) != 0) 20851d8ccc7bSMark Shellenbaum goto bail; 2086f18faf3fSek110237 208744bffe01SMark Shellenbaum if (zfsvfs->z_version >= ZPL_VERSION_SA) 208844bffe01SMark Shellenbaum sa_register_update_callback(zfsvfs->z_os, 208944bffe01SMark Shellenbaum zfs_sa_upgrade); 209044bffe01SMark Shellenbaum 2091f18faf3fSek110237 VERIFY(zfsvfs_setup(zfsvfs, B_FALSE) == 0); 2092f18faf3fSek110237 209344bffe01SMark Shellenbaum zfs_set_fuid_feature(zfsvfs); 209444bffe01SMark Shellenbaum 2095f18faf3fSek110237 /* 2096f18faf3fSek110237 * Attempt to re-establish all the active znodes with 2097f18faf3fSek110237 * their dbufs. If a zfs_rezget() fails, then we'll let 2098f18faf3fSek110237 * any potential callers discover that via ZFS_ENTER_VERIFY_VP 2099f18faf3fSek110237 * when they try to use their znode. 2100f18faf3fSek110237 */ 2101f18faf3fSek110237 mutex_enter(&zfsvfs->z_znodes_lock); 2102f18faf3fSek110237 for (zp = list_head(&zfsvfs->z_all_znodes); zp; 2103f18faf3fSek110237 zp = list_next(&zfsvfs->z_all_znodes, zp)) { 2104f18faf3fSek110237 (void) zfs_rezget(zp); 2105f18faf3fSek110237 } 2106f18faf3fSek110237 mutex_exit(&zfsvfs->z_znodes_lock); 2107f18faf3fSek110237 21080a586ceaSMark Shellenbaum bail: 2109f18faf3fSek110237 /* release the VOPs */ 2110f18faf3fSek110237 rw_exit(&zfsvfs->z_teardown_inactive_lock); 2111c9030f6cSAlexander Motin rrm_exit(&zfsvfs->z_teardown_lock, FTAG); 2112f18faf3fSek110237 2113f18faf3fSek110237 if (err) { 2114f18faf3fSek110237 /* 211591948b51SKeith M Wesolowski * Since we couldn't setup the sa framework, try to force 211691948b51SKeith M Wesolowski * unmount this file system. 2117f18faf3fSek110237 */ 2118f18faf3fSek110237 if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0) 2119f18faf3fSek110237 (void) dounmount(zfsvfs->z_vfs, MS_FORCE, CRED()); 2120f18faf3fSek110237 } 2121f18faf3fSek110237 return (err); 2122f18faf3fSek110237 } 2123f18faf3fSek110237 2124fa9e4066Sahrens static void 2125fa9e4066Sahrens zfs_freevfs(vfs_t *vfsp) 2126fa9e4066Sahrens { 2127fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 2128142ae85dSChris Kirby 2129142ae85dSChris Kirby /* 2130142ae85dSChris Kirby * If this is a snapshot, we have an extra VFS_HOLD on our parent 2131f80ce222SChris Kirby * from zfs_mount(). Release it here. If we came through 2132f80ce222SChris Kirby * zfs_mountroot() instead, we didn't grab an extra hold, so 2133f80ce222SChris Kirby * skip the VFS_RELE for rootvfs. 2134142ae85dSChris Kirby */ 2135f80ce222SChris Kirby if (zfsvfs->z_issnap && (vfsp != rootvfs)) 2136142ae85dSChris Kirby VFS_RELE(zfsvfs->z_parent->z_vfs); 2137142ae85dSChris Kirby 213814843421SMatthew Ahrens zfsvfs_free(zfsvfs); 2139fa9e4066Sahrens 21401a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&zfs_active_fs_count); 2141fa9e4066Sahrens } 2142fa9e4066Sahrens 2143fa9e4066Sahrens /* 2144fa9e4066Sahrens * VFS_INIT() initialization. Note that there is no VFS_FINI(), 2145fa9e4066Sahrens * so we can't safely do any non-idempotent initialization here. 2146fa9e4066Sahrens * Leave that to zfs_init() and zfs_fini(), which are called 2147fa9e4066Sahrens * from the module's _init() and _fini() entry points. 2148fa9e4066Sahrens */ 2149fa9e4066Sahrens /*ARGSUSED*/ 2150fa9e4066Sahrens static int 2151fa9e4066Sahrens zfs_vfsinit(int fstype, char *name) 2152fa9e4066Sahrens { 2153fa9e4066Sahrens int error; 2154fa9e4066Sahrens 2155fa9e4066Sahrens zfsfstype = fstype; 2156fa9e4066Sahrens 2157fa9e4066Sahrens /* 2158fa9e4066Sahrens * Setup vfsops and vnodeops tables. 2159fa9e4066Sahrens */ 2160fa9e4066Sahrens error = vfs_setfsops(fstype, zfs_vfsops_template, &zfs_vfsops); 2161fa9e4066Sahrens if (error != 0) { 2162fa9e4066Sahrens cmn_err(CE_WARN, "zfs: bad vfs ops template"); 2163fa9e4066Sahrens } 2164fa9e4066Sahrens 2165fa9e4066Sahrens error = zfs_create_op_tables(); 2166fa9e4066Sahrens if (error) { 2167fa9e4066Sahrens zfs_remove_op_tables(); 2168fa9e4066Sahrens cmn_err(CE_WARN, "zfs: bad vnode ops template"); 2169fa9e4066Sahrens (void) vfs_freevfsops_by_type(zfsfstype); 2170fa9e4066Sahrens return (error); 2171fa9e4066Sahrens } 2172fa9e4066Sahrens 2173fa9e4066Sahrens mutex_init(&zfs_dev_mtx, NULL, MUTEX_DEFAULT, NULL); 2174fa9e4066Sahrens 2175fa9e4066Sahrens /* 2176a0965f35Sbonwick * Unique major number for all zfs mounts. 2177a0965f35Sbonwick * If we run out of 32-bit minors, we'll getudev() another major. 2178fa9e4066Sahrens */ 2179a0965f35Sbonwick zfs_major = ddi_name_to_major(ZFS_DRIVER); 2180a0965f35Sbonwick zfs_minor = ZFS_MIN_MINOR; 2181fa9e4066Sahrens 2182fa9e4066Sahrens return (0); 2183fa9e4066Sahrens } 2184fa9e4066Sahrens 2185fa9e4066Sahrens void 2186fa9e4066Sahrens zfs_init(void) 2187fa9e4066Sahrens { 2188fa9e4066Sahrens /* 2189fa9e4066Sahrens * Initialize .zfs directory structures 2190fa9e4066Sahrens */ 2191fa9e4066Sahrens zfsctl_init(); 2192fa9e4066Sahrens 2193fa9e4066Sahrens /* 2194fa9e4066Sahrens * Initialize znode cache, vnode ops, etc... 2195fa9e4066Sahrens */ 2196fa9e4066Sahrens zfs_znode_init(); 219714843421SMatthew Ahrens 219814843421SMatthew Ahrens dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb); 2199fa9e4066Sahrens } 2200fa9e4066Sahrens 2201fa9e4066Sahrens void 2202fa9e4066Sahrens zfs_fini(void) 2203fa9e4066Sahrens { 2204fa9e4066Sahrens zfsctl_fini(); 2205fa9e4066Sahrens zfs_znode_fini(); 2206fa9e4066Sahrens } 2207fa9e4066Sahrens 2208fa9e4066Sahrens int 2209fa9e4066Sahrens zfs_busy(void) 2210fa9e4066Sahrens { 2211fa9e4066Sahrens return (zfs_active_fs_count != 0); 2212fa9e4066Sahrens } 2213fa9e4066Sahrens 2214e7437265Sahrens int 221514843421SMatthew Ahrens zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers) 2216e7437265Sahrens { 2217e7437265Sahrens int error; 221814843421SMatthew Ahrens objset_t *os = zfsvfs->z_os; 2219e7437265Sahrens dmu_tx_t *tx; 2220e7437265Sahrens 2221e7437265Sahrens if (newvers < ZPL_VERSION_INITIAL || newvers > ZPL_VERSION) 2222be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 2223e7437265Sahrens 222414843421SMatthew Ahrens if (newvers < zfsvfs->z_version) 2225be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 2226e7437265Sahrens 22270a586ceaSMark Shellenbaum if (zfs_spa_version_map(newvers) > 22280a586ceaSMark Shellenbaum spa_version(dmu_objset_spa(zfsvfs->z_os))) 2229be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 22300a586ceaSMark Shellenbaum 2231e7437265Sahrens tx = dmu_tx_create(os); 223214843421SMatthew Ahrens dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_FALSE, ZPL_VERSION_STR); 22330a586ceaSMark Shellenbaum if (newvers >= ZPL_VERSION_SA && !zfsvfs->z_use_sa) { 22340a586ceaSMark Shellenbaum dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE, 22350a586ceaSMark Shellenbaum ZFS_SA_ATTRS); 22360a586ceaSMark Shellenbaum dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL); 22370a586ceaSMark Shellenbaum } 2238e7437265Sahrens error = dmu_tx_assign(tx, TXG_WAIT); 2239e7437265Sahrens if (error) { 2240e7437265Sahrens dmu_tx_abort(tx); 224114843421SMatthew Ahrens return (error); 2242e7437265Sahrens } 22430a586ceaSMark Shellenbaum 224414843421SMatthew Ahrens error = zap_update(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 224514843421SMatthew Ahrens 8, 1, &newvers, tx); 224614843421SMatthew Ahrens 224714843421SMatthew Ahrens if (error) { 224814843421SMatthew Ahrens dmu_tx_commit(tx); 224914843421SMatthew Ahrens return (error); 225014843421SMatthew Ahrens } 2251e7437265Sahrens 22520a586ceaSMark Shellenbaum if (newvers >= ZPL_VERSION_SA && !zfsvfs->z_use_sa) { 22530a586ceaSMark Shellenbaum uint64_t sa_obj; 22540a586ceaSMark Shellenbaum 22550a586ceaSMark Shellenbaum ASSERT3U(spa_version(dmu_objset_spa(zfsvfs->z_os)), >=, 22560a586ceaSMark Shellenbaum SPA_VERSION_SA); 22570a586ceaSMark Shellenbaum sa_obj = zap_create(os, DMU_OT_SA_MASTER_NODE, 22580a586ceaSMark Shellenbaum DMU_OT_NONE, 0, tx); 22590a586ceaSMark Shellenbaum 22600a586ceaSMark Shellenbaum error = zap_add(os, MASTER_NODE_OBJ, 22610a586ceaSMark Shellenbaum ZFS_SA_ATTRS, 8, 1, &sa_obj, tx); 2262fb09f5aaSMadhav Suresh ASSERT0(error); 22630a586ceaSMark Shellenbaum 22640a586ceaSMark Shellenbaum VERIFY(0 == sa_set_sa_object(os, sa_obj)); 22650a586ceaSMark Shellenbaum sa_register_update_callback(os, zfs_sa_upgrade); 22660a586ceaSMark Shellenbaum } 22670a586ceaSMark Shellenbaum 22684445fffbSMatthew Ahrens spa_history_log_internal_ds(dmu_objset_ds(os), "upgrade", tx, 22694445fffbSMatthew Ahrens "from %llu to %llu", zfsvfs->z_version, newvers); 227014843421SMatthew Ahrens 2271e7437265Sahrens dmu_tx_commit(tx); 2272e7437265Sahrens 227314843421SMatthew Ahrens zfsvfs->z_version = newvers; 227414843421SMatthew Ahrens 227514843421SMatthew Ahrens zfs_set_fuid_feature(zfsvfs); 227614843421SMatthew Ahrens 227714843421SMatthew Ahrens return (0); 2278e7437265Sahrens } 2279e7437265Sahrens 2280de8267e0Stimh /* 2281de8267e0Stimh * Read a property stored within the master node. 2282de8267e0Stimh */ 2283de8267e0Stimh int 2284de8267e0Stimh zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value) 2285de8267e0Stimh { 2286de8267e0Stimh const char *pname; 22870a48a24eStimh int error = ENOENT; 2288de8267e0Stimh 2289de8267e0Stimh /* 2290de8267e0Stimh * Look up the file system's value for the property. For the 2291de8267e0Stimh * version property, we look up a slightly different string. 2292de8267e0Stimh */ 2293de8267e0Stimh if (prop == ZFS_PROP_VERSION) 2294de8267e0Stimh pname = ZPL_VERSION_STR; 2295de8267e0Stimh else 2296de8267e0Stimh pname = zfs_prop_to_name(prop); 2297de8267e0Stimh 22980a48a24eStimh if (os != NULL) 2299de8267e0Stimh error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value); 2300de8267e0Stimh 2301aa60ed0eSmaybee if (error == ENOENT) { 2302de8267e0Stimh /* No value set, use the default value */ 2303de8267e0Stimh switch (prop) { 2304aa60ed0eSmaybee case ZFS_PROP_VERSION: 2305aa60ed0eSmaybee *value = ZPL_VERSION; 2306aa60ed0eSmaybee break; 2307de8267e0Stimh case ZFS_PROP_NORMALIZE: 2308de8267e0Stimh case ZFS_PROP_UTF8ONLY: 2309de8267e0Stimh *value = 0; 2310de8267e0Stimh break; 2311de8267e0Stimh case ZFS_PROP_CASE: 2312de8267e0Stimh *value = ZFS_CASE_SENSITIVE; 2313de8267e0Stimh break; 2314de8267e0Stimh default: 2315aa60ed0eSmaybee return (error); 2316de8267e0Stimh } 2317aa60ed0eSmaybee error = 0; 2318de8267e0Stimh } 2319aa60ed0eSmaybee return (error); 2320de8267e0Stimh } 2321de8267e0Stimh 2322fa9e4066Sahrens static vfsdef_t vfw = { 2323fa9e4066Sahrens VFSDEF_VERSION, 2324fa9e4066Sahrens MNTTYPE_ZFS, 2325fa9e4066Sahrens zfs_vfsinit, 2326da6c28aaSamw VSW_HASPROTO|VSW_CANRWRO|VSW_CANREMOUNT|VSW_VOLATILEDEV|VSW_STATS| 23270fbb751dSJohn Levon VSW_XID|VSW_ZMOUNT, 2328fa9e4066Sahrens &zfs_mntopts 2329fa9e4066Sahrens }; 2330fa9e4066Sahrens 2331fa9e4066Sahrens struct modlfs zfs_modlfs = { 2332e7437265Sahrens &mod_fsops, "ZFS filesystem version " SPA_VERSION_STRING, &vfw 2333fa9e4066Sahrens }; 2334