1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5033f9833Sek * Common Development and Distribution License (the "License"). 6033f9833Sek * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 22893a6d32Sahrens * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23fa9e4066Sahrens * Use is subject to license terms. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 2678077464Sck #pragma ident "%Z%%M% %I% %E% SMI" 27fa9e4066Sahrens 28fa9e4066Sahrens #include <sys/types.h> 29fa9e4066Sahrens #include <sys/param.h> 30fa9e4066Sahrens #include <sys/systm.h> 31fa9e4066Sahrens #include <sys/sysmacros.h> 32fa9e4066Sahrens #include <sys/kmem.h> 33fa9e4066Sahrens #include <sys/pathname.h> 34fa9e4066Sahrens #include <sys/acl.h> 35fa9e4066Sahrens #include <sys/vnode.h> 36fa9e4066Sahrens #include <sys/vfs.h> 37*aa59c4cbSrsb #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> 48fa9e4066Sahrens #include <sys/spa.h> 49fa9e4066Sahrens #include <sys/zap.h> 50fa9e4066Sahrens #include <sys/varargs.h> 51fa9e4066Sahrens #include <sys/policy.h> 52fa9e4066Sahrens #include <sys/atomic.h> 53fa9e4066Sahrens #include <sys/mkdev.h> 54fa9e4066Sahrens #include <sys/modctl.h> 55fa9e4066Sahrens #include <sys/zfs_ioctl.h> 56fa9e4066Sahrens #include <sys/zfs_ctldir.h> 57ea8dc4b6Seschrock #include <sys/bootconf.h> 58a0965f35Sbonwick #include <sys/sunddi.h> 59033f9833Sek #include <sys/dnlc.h> 60fa9e4066Sahrens 61fa9e4066Sahrens int zfsfstype; 62fa9e4066Sahrens vfsops_t *zfs_vfsops = NULL; 63a0965f35Sbonwick static major_t zfs_major; 64fa9e4066Sahrens static minor_t zfs_minor; 65fa9e4066Sahrens static kmutex_t zfs_dev_mtx; 66fa9e4066Sahrens 67ea8dc4b6Seschrock extern char zfs_bootpath[BO_MAXOBJNAME]; 68ea8dc4b6Seschrock 69fa9e4066Sahrens static int zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr); 70fa9e4066Sahrens static int zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr); 71ea8dc4b6Seschrock static int zfs_mountroot(vfs_t *vfsp, enum whymountroot); 72fa9e4066Sahrens static int zfs_root(vfs_t *vfsp, vnode_t **vpp); 73fa9e4066Sahrens static int zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp); 74fa9e4066Sahrens static int zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp); 75fa9e4066Sahrens static void zfs_freevfs(vfs_t *vfsp); 76fa9e4066Sahrens static void zfs_objset_close(zfsvfs_t *zfsvfs); 77fa9e4066Sahrens 78fa9e4066Sahrens static const fs_operation_def_t zfs_vfsops_template[] = { 79*aa59c4cbSrsb VFSNAME_MOUNT, { .vfs_mount = zfs_mount }, 80*aa59c4cbSrsb VFSNAME_MOUNTROOT, { .vfs_mountroot = zfs_mountroot }, 81*aa59c4cbSrsb VFSNAME_UNMOUNT, { .vfs_unmount = zfs_umount }, 82*aa59c4cbSrsb VFSNAME_ROOT, { .vfs_root = zfs_root }, 83*aa59c4cbSrsb VFSNAME_STATVFS, { .vfs_statvfs = zfs_statvfs }, 84*aa59c4cbSrsb VFSNAME_SYNC, { .vfs_sync = zfs_sync }, 85*aa59c4cbSrsb VFSNAME_VGET, { .vfs_vget = zfs_vget }, 86*aa59c4cbSrsb VFSNAME_FREEVFS, { .vfs_freevfs = zfs_freevfs }, 87*aa59c4cbSrsb NULL, NULL 88fa9e4066Sahrens }; 89fa9e4066Sahrens 90fa9e4066Sahrens static const fs_operation_def_t zfs_vfsops_eio_template[] = { 91*aa59c4cbSrsb VFSNAME_FREEVFS, { .vfs_freevfs = zfs_freevfs }, 92*aa59c4cbSrsb NULL, NULL 93fa9e4066Sahrens }; 94fa9e4066Sahrens 95fa9e4066Sahrens /* 96fa9e4066Sahrens * We need to keep a count of active fs's. 97fa9e4066Sahrens * This is necessary to prevent our module 98fa9e4066Sahrens * from being unloaded after a umount -f 99fa9e4066Sahrens */ 100fa9e4066Sahrens static uint32_t zfs_active_fs_count = 0; 101fa9e4066Sahrens 102fa9e4066Sahrens static char *noatime_cancel[] = { MNTOPT_ATIME, NULL }; 103fa9e4066Sahrens static char *atime_cancel[] = { MNTOPT_NOATIME, NULL }; 1047b55fa8eSck static char *noxattr_cancel[] = { MNTOPT_XATTR, NULL }; 1057b55fa8eSck static char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL }; 106fa9e4066Sahrens 1077b55fa8eSck /* 1087b55fa8eSck * MNTOPT_DEFAULT was removed from MNTOPT_XATTR, since the 1097b55fa8eSck * default value is now determined by the xattr property. 1107b55fa8eSck */ 111fa9e4066Sahrens static mntopt_t mntopts[] = { 1127b55fa8eSck { MNTOPT_NOXATTR, noxattr_cancel, NULL, 0, NULL }, 1137b55fa8eSck { MNTOPT_XATTR, xattr_cancel, NULL, 0, NULL }, 114fa9e4066Sahrens { MNTOPT_NOATIME, noatime_cancel, NULL, MO_DEFAULT, NULL }, 115fa9e4066Sahrens { MNTOPT_ATIME, atime_cancel, NULL, 0, NULL } 116fa9e4066Sahrens }; 117fa9e4066Sahrens 118fa9e4066Sahrens static mntopts_t zfs_mntopts = { 119fa9e4066Sahrens sizeof (mntopts) / sizeof (mntopt_t), 120fa9e4066Sahrens mntopts 121fa9e4066Sahrens }; 122fa9e4066Sahrens 123fa9e4066Sahrens /*ARGSUSED*/ 124fa9e4066Sahrens int 125fa9e4066Sahrens zfs_sync(vfs_t *vfsp, short flag, cred_t *cr) 126fa9e4066Sahrens { 127fa9e4066Sahrens /* 128fa9e4066Sahrens * Data integrity is job one. We don't want a compromised kernel 129fa9e4066Sahrens * writing to the storage pool, so we never sync during panic. 130fa9e4066Sahrens */ 131fa9e4066Sahrens if (panicstr) 132fa9e4066Sahrens return (0); 133fa9e4066Sahrens 134fa9e4066Sahrens /* 135fa9e4066Sahrens * SYNC_ATTR is used by fsflush() to force old filesystems like UFS 136fa9e4066Sahrens * to sync metadata, which they would otherwise cache indefinitely. 137fa9e4066Sahrens * Semantically, the only requirement is that the sync be initiated. 138fa9e4066Sahrens * The DMU syncs out txgs frequently, so there's nothing to do. 139fa9e4066Sahrens */ 140fa9e4066Sahrens if (flag & SYNC_ATTR) 141fa9e4066Sahrens return (0); 142fa9e4066Sahrens 143fa9e4066Sahrens if (vfsp != NULL) { 144fa9e4066Sahrens /* 145fa9e4066Sahrens * Sync a specific filesystem. 146fa9e4066Sahrens */ 147fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 148fa9e4066Sahrens 149fa9e4066Sahrens ZFS_ENTER(zfsvfs); 150fa9e4066Sahrens if (zfsvfs->z_log != NULL) 151b19a79ecSperrin zil_commit(zfsvfs->z_log, UINT64_MAX, 0); 152fa9e4066Sahrens else 153fa9e4066Sahrens txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0); 154fa9e4066Sahrens ZFS_EXIT(zfsvfs); 155fa9e4066Sahrens } else { 156fa9e4066Sahrens /* 157fa9e4066Sahrens * Sync all ZFS filesystems. This is what happens when you 158fa9e4066Sahrens * run sync(1M). Unlike other filesystems, ZFS honors the 159fa9e4066Sahrens * request by waiting for all pools to commit all dirty data. 160fa9e4066Sahrens */ 161fa9e4066Sahrens spa_sync_allpools(); 162fa9e4066Sahrens } 163fa9e4066Sahrens 164fa9e4066Sahrens return (0); 165fa9e4066Sahrens } 166fa9e4066Sahrens 167ea8dc4b6Seschrock static int 168ea8dc4b6Seschrock zfs_create_unique_device(dev_t *dev) 169ea8dc4b6Seschrock { 170ea8dc4b6Seschrock major_t new_major; 171ea8dc4b6Seschrock 172ea8dc4b6Seschrock do { 173ea8dc4b6Seschrock ASSERT3U(zfs_minor, <=, MAXMIN32); 174ea8dc4b6Seschrock minor_t start = zfs_minor; 175ea8dc4b6Seschrock do { 176ea8dc4b6Seschrock mutex_enter(&zfs_dev_mtx); 177ea8dc4b6Seschrock if (zfs_minor >= MAXMIN32) { 178ea8dc4b6Seschrock /* 179ea8dc4b6Seschrock * If we're still using the real major 180ea8dc4b6Seschrock * keep out of /dev/zfs and /dev/zvol minor 181ea8dc4b6Seschrock * number space. If we're using a getudev()'ed 182ea8dc4b6Seschrock * major number, we can use all of its minors. 183ea8dc4b6Seschrock */ 184ea8dc4b6Seschrock if (zfs_major == ddi_name_to_major(ZFS_DRIVER)) 185ea8dc4b6Seschrock zfs_minor = ZFS_MIN_MINOR; 186ea8dc4b6Seschrock else 187ea8dc4b6Seschrock zfs_minor = 0; 188ea8dc4b6Seschrock } else { 189ea8dc4b6Seschrock zfs_minor++; 190ea8dc4b6Seschrock } 191ea8dc4b6Seschrock *dev = makedevice(zfs_major, zfs_minor); 192ea8dc4b6Seschrock mutex_exit(&zfs_dev_mtx); 193ea8dc4b6Seschrock } while (vfs_devismounted(*dev) && zfs_minor != start); 194ea8dc4b6Seschrock if (zfs_minor == start) { 195ea8dc4b6Seschrock /* 196ea8dc4b6Seschrock * We are using all ~262,000 minor numbers for the 197ea8dc4b6Seschrock * current major number. Create a new major number. 198ea8dc4b6Seschrock */ 199ea8dc4b6Seschrock if ((new_major = getudev()) == (major_t)-1) { 200ea8dc4b6Seschrock cmn_err(CE_WARN, 201ea8dc4b6Seschrock "zfs_mount: Can't get unique major " 202ea8dc4b6Seschrock "device number."); 203ea8dc4b6Seschrock return (-1); 204ea8dc4b6Seschrock } 205ea8dc4b6Seschrock mutex_enter(&zfs_dev_mtx); 206ea8dc4b6Seschrock zfs_major = new_major; 207ea8dc4b6Seschrock zfs_minor = 0; 208ea8dc4b6Seschrock 209ea8dc4b6Seschrock mutex_exit(&zfs_dev_mtx); 210ea8dc4b6Seschrock } else { 211ea8dc4b6Seschrock break; 212ea8dc4b6Seschrock } 213ea8dc4b6Seschrock /* CONSTANTCONDITION */ 214ea8dc4b6Seschrock } while (1); 215ea8dc4b6Seschrock 216ea8dc4b6Seschrock return (0); 217ea8dc4b6Seschrock } 218ea8dc4b6Seschrock 219fa9e4066Sahrens static void 220fa9e4066Sahrens atime_changed_cb(void *arg, uint64_t newval) 221fa9e4066Sahrens { 222fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 223fa9e4066Sahrens 224fa9e4066Sahrens if (newval == TRUE) { 225fa9e4066Sahrens zfsvfs->z_atime = TRUE; 226fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME); 227fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_ATIME, NULL, 0); 228fa9e4066Sahrens } else { 229fa9e4066Sahrens zfsvfs->z_atime = FALSE; 230fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_ATIME); 231fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME, NULL, 0); 232fa9e4066Sahrens } 233fa9e4066Sahrens } 234fa9e4066Sahrens 2357b55fa8eSck static void 2367b55fa8eSck xattr_changed_cb(void *arg, uint64_t newval) 2377b55fa8eSck { 2387b55fa8eSck zfsvfs_t *zfsvfs = arg; 2397b55fa8eSck 2407b55fa8eSck if (newval == TRUE) { 2417b55fa8eSck /* XXX locking on vfs_flag? */ 2427b55fa8eSck zfsvfs->z_vfs->vfs_flag |= VFS_XATTR; 2437b55fa8eSck vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR); 2447b55fa8eSck vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_XATTR, NULL, 0); 2457b55fa8eSck } else { 2467b55fa8eSck /* XXX locking on vfs_flag? */ 2477b55fa8eSck zfsvfs->z_vfs->vfs_flag &= ~VFS_XATTR; 2487b55fa8eSck vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_XATTR); 2497b55fa8eSck vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR, NULL, 0); 2507b55fa8eSck } 2517b55fa8eSck } 2527b55fa8eSck 253fa9e4066Sahrens static void 254fa9e4066Sahrens blksz_changed_cb(void *arg, uint64_t newval) 255fa9e4066Sahrens { 256fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 257fa9e4066Sahrens 258fa9e4066Sahrens if (newval < SPA_MINBLOCKSIZE || 259fa9e4066Sahrens newval > SPA_MAXBLOCKSIZE || !ISP2(newval)) 260fa9e4066Sahrens newval = SPA_MAXBLOCKSIZE; 261fa9e4066Sahrens 262fa9e4066Sahrens zfsvfs->z_max_blksz = newval; 263fa9e4066Sahrens zfsvfs->z_vfs->vfs_bsize = newval; 264fa9e4066Sahrens } 265fa9e4066Sahrens 266fa9e4066Sahrens static void 267fa9e4066Sahrens readonly_changed_cb(void *arg, uint64_t newval) 268fa9e4066Sahrens { 269fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 270fa9e4066Sahrens 271fa9e4066Sahrens if (newval) { 272fa9e4066Sahrens /* XXX locking on vfs_flag? */ 273fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY; 274fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RW); 275fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RO, NULL, 0); 276fa9e4066Sahrens } else { 277fa9e4066Sahrens /* XXX locking on vfs_flag? */ 278fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 279fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RO); 280fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RW, NULL, 0); 281fa9e4066Sahrens } 282fa9e4066Sahrens } 283fa9e4066Sahrens 284fa9e4066Sahrens static void 285fa9e4066Sahrens devices_changed_cb(void *arg, uint64_t newval) 286fa9e4066Sahrens { 287fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 288fa9e4066Sahrens 289fa9e4066Sahrens if (newval == FALSE) { 290fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NODEVICES; 291fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES); 292fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES, NULL, 0); 293fa9e4066Sahrens } else { 294fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NODEVICES; 295fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES); 296fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES, NULL, 0); 297fa9e4066Sahrens } 298fa9e4066Sahrens } 299fa9e4066Sahrens 300fa9e4066Sahrens static void 301fa9e4066Sahrens setuid_changed_cb(void *arg, uint64_t newval) 302fa9e4066Sahrens { 303fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 304fa9e4066Sahrens 305fa9e4066Sahrens if (newval == FALSE) { 306fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NOSETUID; 307fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_SETUID); 308fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID, NULL, 0); 309fa9e4066Sahrens } else { 310fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NOSETUID; 311fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID); 312fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_SETUID, NULL, 0); 313fa9e4066Sahrens } 314fa9e4066Sahrens } 315fa9e4066Sahrens 316fa9e4066Sahrens static void 317fa9e4066Sahrens exec_changed_cb(void *arg, uint64_t newval) 318fa9e4066Sahrens { 319fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 320fa9e4066Sahrens 321fa9e4066Sahrens if (newval == FALSE) { 322fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NOEXEC; 323fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_EXEC); 324fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC, NULL, 0); 325fa9e4066Sahrens } else { 326fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NOEXEC; 327fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC); 328fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_EXEC, NULL, 0); 329fa9e4066Sahrens } 330fa9e4066Sahrens } 331fa9e4066Sahrens 332fa9e4066Sahrens static void 333fa9e4066Sahrens snapdir_changed_cb(void *arg, uint64_t newval) 334fa9e4066Sahrens { 335fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 336fa9e4066Sahrens 337fa9e4066Sahrens zfsvfs->z_show_ctldir = newval; 338fa9e4066Sahrens } 339fa9e4066Sahrens 340fa9e4066Sahrens static void 341fa9e4066Sahrens acl_mode_changed_cb(void *arg, uint64_t newval) 342fa9e4066Sahrens { 343fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 344fa9e4066Sahrens 345fa9e4066Sahrens zfsvfs->z_acl_mode = newval; 346fa9e4066Sahrens } 347fa9e4066Sahrens 348fa9e4066Sahrens static void 349fa9e4066Sahrens acl_inherit_changed_cb(void *arg, uint64_t newval) 350fa9e4066Sahrens { 351fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 352fa9e4066Sahrens 353fa9e4066Sahrens zfsvfs->z_acl_inherit = newval; 354fa9e4066Sahrens } 355fa9e4066Sahrens 356fa9e4066Sahrens static int 357ea8dc4b6Seschrock zfs_refresh_properties(vfs_t *vfsp) 358fa9e4066Sahrens { 359ea8dc4b6Seschrock zfsvfs_t *zfsvfs = vfsp->vfs_data; 360fa9e4066Sahrens 3614981797aStabriz /* 3624981797aStabriz * Remount operations default to "rw" unless "ro" is explicitly 3634981797aStabriz * specified. 3644981797aStabriz */ 365ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_RO, NULL)) { 366ea8dc4b6Seschrock readonly_changed_cb(zfsvfs, B_TRUE); 3674981797aStabriz } else { 3684981797aStabriz if (!dmu_objset_is_snapshot(zfsvfs->z_os)) 3694981797aStabriz readonly_changed_cb(zfsvfs, B_FALSE); 3704981797aStabriz else if (vfs_optionisset(vfsp, MNTOPT_RW, NULL)) 3714981797aStabriz return (EROFS); 372ea8dc4b6Seschrock } 373fa9e4066Sahrens 374ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL)) { 375ea8dc4b6Seschrock devices_changed_cb(zfsvfs, B_FALSE); 376ea8dc4b6Seschrock setuid_changed_cb(zfsvfs, B_FALSE); 377ea8dc4b6Seschrock } else { 378ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL)) 379ea8dc4b6Seschrock devices_changed_cb(zfsvfs, B_FALSE); 380ea8dc4b6Seschrock else if (vfs_optionisset(vfsp, MNTOPT_DEVICES, NULL)) 381ea8dc4b6Seschrock devices_changed_cb(zfsvfs, B_TRUE); 382ea8dc4b6Seschrock 383ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) 384ea8dc4b6Seschrock setuid_changed_cb(zfsvfs, B_FALSE); 385ea8dc4b6Seschrock else if (vfs_optionisset(vfsp, MNTOPT_SETUID, NULL)) 386ea8dc4b6Seschrock setuid_changed_cb(zfsvfs, B_TRUE); 387fa9e4066Sahrens } 388fa9e4066Sahrens 389ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) 390ea8dc4b6Seschrock exec_changed_cb(zfsvfs, B_FALSE); 391ea8dc4b6Seschrock else if (vfs_optionisset(vfsp, MNTOPT_EXEC, NULL)) 392ea8dc4b6Seschrock exec_changed_cb(zfsvfs, B_TRUE); 393ea8dc4b6Seschrock 3943bb79becSeschrock if (vfs_optionisset(vfsp, MNTOPT_ATIME, NULL)) 3953bb79becSeschrock atime_changed_cb(zfsvfs, B_TRUE); 3963bb79becSeschrock else if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) 3973bb79becSeschrock atime_changed_cb(zfsvfs, B_FALSE); 3983bb79becSeschrock 3997b55fa8eSck if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) 4007b55fa8eSck xattr_changed_cb(zfsvfs, B_TRUE); 4017b55fa8eSck else if (vfs_optionisset(vfsp, MNTOPT_NOXATTR, NULL)) 4027b55fa8eSck xattr_changed_cb(zfsvfs, B_FALSE); 4037b55fa8eSck 404ea8dc4b6Seschrock return (0); 405ea8dc4b6Seschrock } 406ea8dc4b6Seschrock 407ea8dc4b6Seschrock static int 408ea8dc4b6Seschrock zfs_register_callbacks(vfs_t *vfsp) 409ea8dc4b6Seschrock { 410ea8dc4b6Seschrock struct dsl_dataset *ds = NULL; 411ea8dc4b6Seschrock objset_t *os = NULL; 412ea8dc4b6Seschrock zfsvfs_t *zfsvfs = NULL; 4133ccfa83cSahrens int readonly, do_readonly = FALSE; 4143ccfa83cSahrens int setuid, do_setuid = FALSE; 4153ccfa83cSahrens int exec, do_exec = FALSE; 4163ccfa83cSahrens int devices, do_devices = FALSE; 4173ccfa83cSahrens int xattr, do_xattr = FALSE; 418ea8dc4b6Seschrock int error = 0; 419ea8dc4b6Seschrock 420ea8dc4b6Seschrock ASSERT(vfsp); 421ea8dc4b6Seschrock zfsvfs = vfsp->vfs_data; 422ea8dc4b6Seschrock ASSERT(zfsvfs); 423ea8dc4b6Seschrock os = zfsvfs->z_os; 424fa9e4066Sahrens 425fa9e4066Sahrens /* 426ea8dc4b6Seschrock * The act of registering our callbacks will destroy any mount 427ea8dc4b6Seschrock * options we may have. In order to enable temporary overrides 4287b55fa8eSck * of mount options, we stash away the current values and 429ea8dc4b6Seschrock * restore them after we register the callbacks. 430fa9e4066Sahrens */ 431ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_RO, NULL)) { 432ea8dc4b6Seschrock readonly = B_TRUE; 433ea8dc4b6Seschrock do_readonly = B_TRUE; 434ea8dc4b6Seschrock } else if (vfs_optionisset(vfsp, MNTOPT_RW, NULL)) { 435ea8dc4b6Seschrock readonly = B_FALSE; 436ea8dc4b6Seschrock do_readonly = B_TRUE; 437ea8dc4b6Seschrock } 438ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL)) { 439ea8dc4b6Seschrock devices = B_FALSE; 440ea8dc4b6Seschrock setuid = B_FALSE; 441ea8dc4b6Seschrock do_devices = B_TRUE; 442ea8dc4b6Seschrock do_setuid = B_TRUE; 443ea8dc4b6Seschrock } else { 444ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL)) { 445ea8dc4b6Seschrock devices = B_FALSE; 446ea8dc4b6Seschrock do_devices = B_TRUE; 447ea8dc4b6Seschrock } else if (vfs_optionisset(vfsp, 448ea8dc4b6Seschrock MNTOPT_DEVICES, NULL)) { 449ea8dc4b6Seschrock devices = B_TRUE; 450ea8dc4b6Seschrock do_devices = B_TRUE; 451fa9e4066Sahrens } 452fa9e4066Sahrens 453ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) { 454ea8dc4b6Seschrock setuid = B_FALSE; 455ea8dc4b6Seschrock do_setuid = B_TRUE; 456ea8dc4b6Seschrock } else if (vfs_optionisset(vfsp, MNTOPT_SETUID, NULL)) { 457ea8dc4b6Seschrock setuid = B_TRUE; 458ea8dc4b6Seschrock do_setuid = B_TRUE; 459fa9e4066Sahrens } 460ea8dc4b6Seschrock } 461ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) { 462ea8dc4b6Seschrock exec = B_FALSE; 463ea8dc4b6Seschrock do_exec = B_TRUE; 464ea8dc4b6Seschrock } else if (vfs_optionisset(vfsp, MNTOPT_EXEC, NULL)) { 465ea8dc4b6Seschrock exec = B_TRUE; 466ea8dc4b6Seschrock do_exec = B_TRUE; 467fa9e4066Sahrens } 4687b55fa8eSck if (vfs_optionisset(vfsp, MNTOPT_NOXATTR, NULL)) { 4697b55fa8eSck xattr = B_FALSE; 4707b55fa8eSck do_xattr = B_TRUE; 4717b55fa8eSck } else if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) { 4727b55fa8eSck xattr = B_TRUE; 4737b55fa8eSck do_xattr = B_TRUE; 4747b55fa8eSck } 475fa9e4066Sahrens 476fa9e4066Sahrens /* 477ea8dc4b6Seschrock * Register property callbacks. 478ea8dc4b6Seschrock * 479ea8dc4b6Seschrock * It would probably be fine to just check for i/o error from 480ea8dc4b6Seschrock * the first prop_register(), but I guess I like to go 481ea8dc4b6Seschrock * overboard... 482fa9e4066Sahrens */ 483ea8dc4b6Seschrock ds = dmu_objset_ds(os); 484ea8dc4b6Seschrock error = dsl_prop_register(ds, "atime", atime_changed_cb, zfsvfs); 4857b55fa8eSck error = error ? error : dsl_prop_register(ds, 4867b55fa8eSck "xattr", xattr_changed_cb, zfsvfs); 487ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 488ea8dc4b6Seschrock "recordsize", blksz_changed_cb, zfsvfs); 489ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 490ea8dc4b6Seschrock "readonly", readonly_changed_cb, zfsvfs); 491ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 492ea8dc4b6Seschrock "devices", devices_changed_cb, zfsvfs); 493ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 494ea8dc4b6Seschrock "setuid", setuid_changed_cb, zfsvfs); 495ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 496ea8dc4b6Seschrock "exec", exec_changed_cb, zfsvfs); 497ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 498ea8dc4b6Seschrock "snapdir", snapdir_changed_cb, zfsvfs); 499ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 500ea8dc4b6Seschrock "aclmode", acl_mode_changed_cb, zfsvfs); 501ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 502ea8dc4b6Seschrock "aclinherit", acl_inherit_changed_cb, zfsvfs); 503ea8dc4b6Seschrock if (error) 504ea8dc4b6Seschrock goto unregister; 505fa9e4066Sahrens 506ea8dc4b6Seschrock /* 507ea8dc4b6Seschrock * Invoke our callbacks to restore temporary mount options. 508ea8dc4b6Seschrock */ 509ea8dc4b6Seschrock if (do_readonly) 510ea8dc4b6Seschrock readonly_changed_cb(zfsvfs, readonly); 511ea8dc4b6Seschrock if (do_setuid) 512ea8dc4b6Seschrock setuid_changed_cb(zfsvfs, setuid); 513ea8dc4b6Seschrock if (do_exec) 514ea8dc4b6Seschrock exec_changed_cb(zfsvfs, exec); 515ea8dc4b6Seschrock if (do_devices) 516ea8dc4b6Seschrock devices_changed_cb(zfsvfs, devices); 5177b55fa8eSck if (do_xattr) 5187b55fa8eSck xattr_changed_cb(zfsvfs, xattr); 519fa9e4066Sahrens 520ea8dc4b6Seschrock return (0); 521fa9e4066Sahrens 522ea8dc4b6Seschrock unregister: 523fa9e4066Sahrens /* 524ea8dc4b6Seschrock * We may attempt to unregister some callbacks that are not 525ea8dc4b6Seschrock * registered, but this is OK; it will simply return ENOMSG, 526ea8dc4b6Seschrock * which we will ignore. 527fa9e4066Sahrens */ 528ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "atime", atime_changed_cb, zfsvfs); 5297b55fa8eSck (void) dsl_prop_unregister(ds, "xattr", xattr_changed_cb, zfsvfs); 530ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, zfsvfs); 531ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "readonly", readonly_changed_cb, zfsvfs); 532ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "devices", devices_changed_cb, zfsvfs); 533ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "setuid", setuid_changed_cb, zfsvfs); 534ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "exec", exec_changed_cb, zfsvfs); 535ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, zfsvfs); 536ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, zfsvfs); 537ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "aclinherit", acl_inherit_changed_cb, 538ea8dc4b6Seschrock zfsvfs); 539ea8dc4b6Seschrock return (error); 540ea8dc4b6Seschrock 541ea8dc4b6Seschrock } 542ea8dc4b6Seschrock 543ea8dc4b6Seschrock static int 544ea8dc4b6Seschrock zfs_domount(vfs_t *vfsp, char *osname, cred_t *cr) 545ea8dc4b6Seschrock { 546ea8dc4b6Seschrock dev_t mount_dev; 547ea8dc4b6Seschrock uint64_t recordsize, readonly; 548ea8dc4b6Seschrock int error = 0; 549ea8dc4b6Seschrock int mode; 550ea8dc4b6Seschrock zfsvfs_t *zfsvfs; 551ea8dc4b6Seschrock znode_t *zp = NULL; 552ea8dc4b6Seschrock 553ea8dc4b6Seschrock ASSERT(vfsp); 554ea8dc4b6Seschrock ASSERT(osname); 555fa9e4066Sahrens 556fa9e4066Sahrens /* 557fa9e4066Sahrens * Initialize the zfs-specific filesystem structure. 558fa9e4066Sahrens * Should probably make this a kmem cache, shuffle fields, 559ea8dc4b6Seschrock * and just bzero up to z_hold_mtx[]. 560fa9e4066Sahrens */ 561fa9e4066Sahrens zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); 562fa9e4066Sahrens zfsvfs->z_vfs = vfsp; 563fa9e4066Sahrens zfsvfs->z_parent = zfsvfs; 564fa9e4066Sahrens zfsvfs->z_assign = TXG_NOWAIT; 565fa9e4066Sahrens zfsvfs->z_max_blksz = SPA_MAXBLOCKSIZE; 566a0965f35Sbonwick zfsvfs->z_show_ctldir = ZFS_SNAPDIR_VISIBLE; 567fa9e4066Sahrens 568fa9e4066Sahrens mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); 569fa9e4066Sahrens list_create(&zfsvfs->z_all_znodes, sizeof (znode_t), 570fa9e4066Sahrens offsetof(znode_t, z_link_node)); 571fa9e4066Sahrens rw_init(&zfsvfs->z_um_lock, NULL, RW_DEFAULT, NULL); 572fa9e4066Sahrens 573ea8dc4b6Seschrock /* Initialize the generic filesystem structure. */ 574fa9e4066Sahrens vfsp->vfs_bcount = 0; 575fa9e4066Sahrens vfsp->vfs_data = NULL; 576fa9e4066Sahrens 577ea8dc4b6Seschrock if (zfs_create_unique_device(&mount_dev) == -1) { 578ea8dc4b6Seschrock error = ENODEV; 579ea8dc4b6Seschrock goto out; 580ea8dc4b6Seschrock } 581fa9e4066Sahrens ASSERT(vfs_devismounted(mount_dev) == 0); 582fa9e4066Sahrens 583ea8dc4b6Seschrock if (error = dsl_prop_get_integer(osname, "recordsize", &recordsize, 584ea8dc4b6Seschrock NULL)) 585ea8dc4b6Seschrock goto out; 586fa9e4066Sahrens 587fa9e4066Sahrens vfsp->vfs_dev = mount_dev; 588fa9e4066Sahrens vfsp->vfs_fstype = zfsfstype; 589fa9e4066Sahrens vfsp->vfs_bsize = recordsize; 590fa9e4066Sahrens vfsp->vfs_flag |= VFS_NOTRUNC; 591fa9e4066Sahrens vfsp->vfs_data = zfsvfs; 592fa9e4066Sahrens 593ea8dc4b6Seschrock if (error = dsl_prop_get_integer(osname, "readonly", &readonly, NULL)) 594fa9e4066Sahrens goto out; 595fa9e4066Sahrens 596fa9e4066Sahrens if (readonly) 597fa9e4066Sahrens mode = DS_MODE_PRIMARY | DS_MODE_READONLY; 598fa9e4066Sahrens else 599fa9e4066Sahrens mode = DS_MODE_PRIMARY; 600fa9e4066Sahrens 601fa9e4066Sahrens error = dmu_objset_open(osname, DMU_OST_ZFS, mode, &zfsvfs->z_os); 602fa9e4066Sahrens if (error == EROFS) { 603fa9e4066Sahrens mode = DS_MODE_PRIMARY | DS_MODE_READONLY; 604fa9e4066Sahrens error = dmu_objset_open(osname, DMU_OST_ZFS, mode, 605fa9e4066Sahrens &zfsvfs->z_os); 606fa9e4066Sahrens } 607fa9e4066Sahrens 608fa9e4066Sahrens if (error) 609fa9e4066Sahrens goto out; 610fa9e4066Sahrens 611fa9e4066Sahrens if (error = zfs_init_fs(zfsvfs, &zp, cr)) 612fa9e4066Sahrens goto out; 613fa9e4066Sahrens 614ea8dc4b6Seschrock /* The call to zfs_init_fs leaves the vnode held, release it here. */ 615ea8dc4b6Seschrock VN_RELE(ZTOV(zp)); 616ea8dc4b6Seschrock 617ea8dc4b6Seschrock if (dmu_objset_is_snapshot(zfsvfs->z_os)) { 6187b55fa8eSck uint64_t xattr; 6197b55fa8eSck 620fa9e4066Sahrens ASSERT(mode & DS_MODE_READONLY); 621fa9e4066Sahrens atime_changed_cb(zfsvfs, B_FALSE); 622fa9e4066Sahrens readonly_changed_cb(zfsvfs, B_TRUE); 6237b55fa8eSck if (error = dsl_prop_get_integer(osname, "xattr", &xattr, NULL)) 6247b55fa8eSck goto out; 6257b55fa8eSck xattr_changed_cb(zfsvfs, xattr); 626fa9e4066Sahrens zfsvfs->z_issnap = B_TRUE; 627fa9e4066Sahrens } else { 628ea8dc4b6Seschrock error = zfs_register_callbacks(vfsp); 629ea8dc4b6Seschrock if (error) 630ea8dc4b6Seschrock goto out; 631fa9e4066Sahrens 632893a6d32Sahrens zfs_unlinked_drain(zfsvfs); 633fa9e4066Sahrens 634fa9e4066Sahrens /* 635fa9e4066Sahrens * Parse and replay the intent log. 636fa9e4066Sahrens */ 637ea8dc4b6Seschrock zil_replay(zfsvfs->z_os, zfsvfs, &zfsvfs->z_assign, 638893a6d32Sahrens zfs_replay_vector); 639fa9e4066Sahrens 640fa9e4066Sahrens if (!zil_disable) 641ea8dc4b6Seschrock zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data); 642ea8dc4b6Seschrock } 643fa9e4066Sahrens 644ea8dc4b6Seschrock if (!zfsvfs->z_issnap) 645ea8dc4b6Seschrock zfsctl_create(zfsvfs); 646ea8dc4b6Seschrock out: 647ea8dc4b6Seschrock if (error) { 648ea8dc4b6Seschrock if (zfsvfs->z_os) 649ea8dc4b6Seschrock dmu_objset_close(zfsvfs->z_os); 650ea8dc4b6Seschrock kmem_free(zfsvfs, sizeof (zfsvfs_t)); 651ea8dc4b6Seschrock } else { 652ea8dc4b6Seschrock atomic_add_32(&zfs_active_fs_count, 1); 653ea8dc4b6Seschrock } 654fa9e4066Sahrens 655ea8dc4b6Seschrock return (error); 656fa9e4066Sahrens 657ea8dc4b6Seschrock } 658ea8dc4b6Seschrock 659ea8dc4b6Seschrock void 660ea8dc4b6Seschrock zfs_unregister_callbacks(zfsvfs_t *zfsvfs) 661ea8dc4b6Seschrock { 662ea8dc4b6Seschrock objset_t *os = zfsvfs->z_os; 663ea8dc4b6Seschrock struct dsl_dataset *ds; 664ea8dc4b6Seschrock 665ea8dc4b6Seschrock /* 666ea8dc4b6Seschrock * Unregister properties. 667ea8dc4b6Seschrock */ 668ea8dc4b6Seschrock if (!dmu_objset_is_snapshot(os)) { 669fa9e4066Sahrens ds = dmu_objset_ds(os); 670ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "atime", atime_changed_cb, 671fa9e4066Sahrens zfsvfs) == 0); 672fa9e4066Sahrens 6737b55fa8eSck VERIFY(dsl_prop_unregister(ds, "xattr", xattr_changed_cb, 6747b55fa8eSck zfsvfs) == 0); 6757b55fa8eSck 676ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, 677fa9e4066Sahrens zfsvfs) == 0); 678fa9e4066Sahrens 679ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "readonly", readonly_changed_cb, 680fa9e4066Sahrens zfsvfs) == 0); 681fa9e4066Sahrens 682ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "devices", devices_changed_cb, 683fa9e4066Sahrens zfsvfs) == 0); 684fa9e4066Sahrens 685ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "setuid", setuid_changed_cb, 686fa9e4066Sahrens zfsvfs) == 0); 687fa9e4066Sahrens 688ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "exec", exec_changed_cb, 689fa9e4066Sahrens zfsvfs) == 0); 690fa9e4066Sahrens 691ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, 692fa9e4066Sahrens zfsvfs) == 0); 693fa9e4066Sahrens 694ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, 695fa9e4066Sahrens zfsvfs) == 0); 696fa9e4066Sahrens 697ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "aclinherit", 698fa9e4066Sahrens acl_inherit_changed_cb, zfsvfs) == 0); 699ea8dc4b6Seschrock } 700ea8dc4b6Seschrock } 701fa9e4066Sahrens 702ea8dc4b6Seschrock static int 703ea8dc4b6Seschrock zfs_mountroot(vfs_t *vfsp, enum whymountroot why) 704ea8dc4b6Seschrock { 705ea8dc4b6Seschrock int error = 0; 706ea8dc4b6Seschrock int ret = 0; 707ea8dc4b6Seschrock static int zfsrootdone = 0; 708ea8dc4b6Seschrock zfsvfs_t *zfsvfs = NULL; 709ea8dc4b6Seschrock znode_t *zp = NULL; 710ea8dc4b6Seschrock vnode_t *vp = NULL; 711ea8dc4b6Seschrock 712ea8dc4b6Seschrock ASSERT(vfsp); 713ea8dc4b6Seschrock 714ea8dc4b6Seschrock /* 715ea8dc4b6Seschrock * The filesystem that we mount as root is defined in 716ea8dc4b6Seschrock * /etc/system using the zfsroot variable. The value defined 717ea8dc4b6Seschrock * there is copied early in startup code to zfs_bootpath 718ea8dc4b6Seschrock * (defined in modsysfile.c). 719ea8dc4b6Seschrock */ 720ea8dc4b6Seschrock if (why == ROOT_INIT) { 721ea8dc4b6Seschrock if (zfsrootdone++) 722ea8dc4b6Seschrock return (EBUSY); 723fa9e4066Sahrens 724fa9e4066Sahrens /* 725ea8dc4b6Seschrock * This needs to be done here, so that when we return from 726ea8dc4b6Seschrock * mountroot, the vfs resource name will be set correctly. 727fa9e4066Sahrens */ 728ea8dc4b6Seschrock if (snprintf(rootfs.bo_name, BO_MAXOBJNAME, "%s", zfs_bootpath) 729ea8dc4b6Seschrock >= BO_MAXOBJNAME) 730ea8dc4b6Seschrock return (ENAMETOOLONG); 731fa9e4066Sahrens 732ea8dc4b6Seschrock if (error = vfs_lock(vfsp)) 733ea8dc4b6Seschrock return (error); 734fa9e4066Sahrens 735ea8dc4b6Seschrock if (error = zfs_domount(vfsp, zfs_bootpath, CRED())) 736ea8dc4b6Seschrock goto out; 737ea8dc4b6Seschrock 738ea8dc4b6Seschrock zfsvfs = (zfsvfs_t *)vfsp->vfs_data; 739ea8dc4b6Seschrock ASSERT(zfsvfs); 740ea8dc4b6Seschrock if (error = zfs_zget(zfsvfs, zfsvfs->z_root, &zp)) 741ea8dc4b6Seschrock goto out; 742ea8dc4b6Seschrock 743ea8dc4b6Seschrock vp = ZTOV(zp); 744ea8dc4b6Seschrock mutex_enter(&vp->v_lock); 745ea8dc4b6Seschrock vp->v_flag |= VROOT; 746ea8dc4b6Seschrock mutex_exit(&vp->v_lock); 747ea8dc4b6Seschrock rootvp = vp; 748ea8dc4b6Seschrock 749ea8dc4b6Seschrock /* 750ea8dc4b6Seschrock * The zfs_zget call above returns with a hold on vp, we release 751ea8dc4b6Seschrock * it here. 752ea8dc4b6Seschrock */ 753fa9e4066Sahrens VN_RELE(vp); 754ea8dc4b6Seschrock 755ea8dc4b6Seschrock /* 756ea8dc4b6Seschrock * Mount root as readonly initially, it will be remouted 757ea8dc4b6Seschrock * read/write by /lib/svc/method/fs-usr. 758ea8dc4b6Seschrock */ 759ea8dc4b6Seschrock readonly_changed_cb(vfsp->vfs_data, B_TRUE); 760ea8dc4b6Seschrock vfs_add((struct vnode *)0, vfsp, 761ea8dc4b6Seschrock (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0); 762ea8dc4b6Seschrock out: 763ea8dc4b6Seschrock vfs_unlock(vfsp); 764ea8dc4b6Seschrock ret = (error) ? error : 0; 765ea8dc4b6Seschrock return (ret); 766ea8dc4b6Seschrock 767ea8dc4b6Seschrock } else if (why == ROOT_REMOUNT) { 768ea8dc4b6Seschrock 769ea8dc4b6Seschrock readonly_changed_cb(vfsp->vfs_data, B_FALSE); 770ea8dc4b6Seschrock vfsp->vfs_flag |= VFS_REMOUNT; 771ea8dc4b6Seschrock return (zfs_refresh_properties(vfsp)); 772ea8dc4b6Seschrock 773ea8dc4b6Seschrock } else if (why == ROOT_UNMOUNT) { 774ea8dc4b6Seschrock zfs_unregister_callbacks((zfsvfs_t *)vfsp->vfs_data); 775ea8dc4b6Seschrock (void) zfs_sync(vfsp, 0, 0); 776ea8dc4b6Seschrock return (0); 777ea8dc4b6Seschrock } 778ea8dc4b6Seschrock 779ea8dc4b6Seschrock /* 780ea8dc4b6Seschrock * if "why" is equal to anything else other than ROOT_INIT, 781ea8dc4b6Seschrock * ROOT_REMOUNT, or ROOT_UNMOUNT, we do not support it. 782ea8dc4b6Seschrock */ 783ea8dc4b6Seschrock return (ENOTSUP); 784ea8dc4b6Seschrock } 785ea8dc4b6Seschrock 786ea8dc4b6Seschrock /*ARGSUSED*/ 787ea8dc4b6Seschrock static int 788ea8dc4b6Seschrock zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) 789ea8dc4b6Seschrock { 790ea8dc4b6Seschrock char *osname; 791ea8dc4b6Seschrock pathname_t spn; 792ea8dc4b6Seschrock int error = 0; 793ea8dc4b6Seschrock uio_seg_t fromspace = (uap->flags & MS_SYSSPACE) ? 794ea8dc4b6Seschrock UIO_SYSSPACE : UIO_USERSPACE; 795ea8dc4b6Seschrock int canwrite; 796ea8dc4b6Seschrock 797ea8dc4b6Seschrock if (mvp->v_type != VDIR) 798ea8dc4b6Seschrock return (ENOTDIR); 799ea8dc4b6Seschrock 800ea8dc4b6Seschrock mutex_enter(&mvp->v_lock); 801ea8dc4b6Seschrock if ((uap->flags & MS_REMOUNT) == 0 && 802ea8dc4b6Seschrock (uap->flags & MS_OVERLAY) == 0 && 803ea8dc4b6Seschrock (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { 804ea8dc4b6Seschrock mutex_exit(&mvp->v_lock); 805ea8dc4b6Seschrock return (EBUSY); 806ea8dc4b6Seschrock } 807ea8dc4b6Seschrock mutex_exit(&mvp->v_lock); 808ea8dc4b6Seschrock 809ea8dc4b6Seschrock /* 810ea8dc4b6Seschrock * ZFS does not support passing unparsed data in via MS_DATA. 811ea8dc4b6Seschrock * Users should use the MS_OPTIONSTR interface; this means 812ea8dc4b6Seschrock * that all option parsing is already done and the options struct 813ea8dc4b6Seschrock * can be interrogated. 814ea8dc4b6Seschrock */ 815ea8dc4b6Seschrock if ((uap->flags & MS_DATA) && uap->datalen > 0) 816ea8dc4b6Seschrock return (EINVAL); 817ea8dc4b6Seschrock 818ea8dc4b6Seschrock /* 819ea8dc4b6Seschrock * When doing a remount, we simply refresh our temporary properties 820ea8dc4b6Seschrock * according to those options set in the current VFS options. 821ea8dc4b6Seschrock */ 822ea8dc4b6Seschrock if (uap->flags & MS_REMOUNT) { 823ea8dc4b6Seschrock return (zfs_refresh_properties(vfsp)); 824fa9e4066Sahrens } 825fa9e4066Sahrens 826ea8dc4b6Seschrock /* 827ea8dc4b6Seschrock * Get the objset name (the "special" mount argument). 828ea8dc4b6Seschrock */ 829ea8dc4b6Seschrock if (error = pn_get(uap->spec, fromspace, &spn)) 830ea8dc4b6Seschrock return (error); 831ea8dc4b6Seschrock 832ea8dc4b6Seschrock osname = spn.pn_path; 833ea8dc4b6Seschrock 834ea8dc4b6Seschrock if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) 835ea8dc4b6Seschrock goto out; 836ea8dc4b6Seschrock 837ea8dc4b6Seschrock /* 838ea8dc4b6Seschrock * Refuse to mount a filesystem if we are in a local zone and the 839ea8dc4b6Seschrock * dataset is not visible. 840ea8dc4b6Seschrock */ 841ea8dc4b6Seschrock if (!INGLOBALZONE(curproc) && 842ea8dc4b6Seschrock (!zone_dataset_visible(osname, &canwrite) || !canwrite)) { 843ea8dc4b6Seschrock error = EPERM; 844ea8dc4b6Seschrock goto out; 845ea8dc4b6Seschrock } 846ea8dc4b6Seschrock 847ea8dc4b6Seschrock error = zfs_domount(vfsp, osname, cr); 848ea8dc4b6Seschrock 849ea8dc4b6Seschrock out: 850fa9e4066Sahrens pn_free(&spn); 851fa9e4066Sahrens return (error); 852fa9e4066Sahrens } 853fa9e4066Sahrens 854fa9e4066Sahrens static int 855fa9e4066Sahrens zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp) 856fa9e4066Sahrens { 857fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 858fa9e4066Sahrens dev32_t d32; 859a2eea2e1Sahrens uint64_t refdbytes, availbytes, usedobjs, availobjs; 860fa9e4066Sahrens 861fa9e4066Sahrens ZFS_ENTER(zfsvfs); 862fa9e4066Sahrens 863a2eea2e1Sahrens dmu_objset_space(zfsvfs->z_os, 864a2eea2e1Sahrens &refdbytes, &availbytes, &usedobjs, &availobjs); 865fa9e4066Sahrens 866fa9e4066Sahrens /* 867fa9e4066Sahrens * The underlying storage pool actually uses multiple block sizes. 868fa9e4066Sahrens * We report the fragsize as the smallest block size we support, 869fa9e4066Sahrens * and we report our blocksize as the filesystem's maximum blocksize. 870fa9e4066Sahrens */ 871fa9e4066Sahrens statp->f_frsize = 1UL << SPA_MINBLOCKSHIFT; 872fa9e4066Sahrens statp->f_bsize = zfsvfs->z_max_blksz; 873fa9e4066Sahrens 874fa9e4066Sahrens /* 875fa9e4066Sahrens * The following report "total" blocks of various kinds in the 876fa9e4066Sahrens * file system, but reported in terms of f_frsize - the 877fa9e4066Sahrens * "fragment" size. 878fa9e4066Sahrens */ 879fa9e4066Sahrens 880a2eea2e1Sahrens statp->f_blocks = (refdbytes + availbytes) >> SPA_MINBLOCKSHIFT; 881a2eea2e1Sahrens statp->f_bfree = availbytes >> SPA_MINBLOCKSHIFT; 882fa9e4066Sahrens statp->f_bavail = statp->f_bfree; /* no root reservation */ 883fa9e4066Sahrens 884fa9e4066Sahrens /* 885fa9e4066Sahrens * statvfs() should really be called statufs(), because it assumes 886fa9e4066Sahrens * static metadata. ZFS doesn't preallocate files, so the best 887fa9e4066Sahrens * we can do is report the max that could possibly fit in f_files, 888fa9e4066Sahrens * and that minus the number actually used in f_ffree. 889fa9e4066Sahrens * For f_ffree, report the smaller of the number of object available 890fa9e4066Sahrens * and the number of blocks (each object will take at least a block). 891fa9e4066Sahrens */ 892a2eea2e1Sahrens statp->f_ffree = MIN(availobjs, statp->f_bfree); 893fa9e4066Sahrens statp->f_favail = statp->f_ffree; /* no "root reservation" */ 894a2eea2e1Sahrens statp->f_files = statp->f_ffree + usedobjs; 895fa9e4066Sahrens 896fa9e4066Sahrens (void) cmpldev(&d32, vfsp->vfs_dev); 897fa9e4066Sahrens statp->f_fsid = d32; 898fa9e4066Sahrens 899fa9e4066Sahrens /* 900fa9e4066Sahrens * We're a zfs filesystem. 901fa9e4066Sahrens */ 902fa9e4066Sahrens (void) strcpy(statp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 903fa9e4066Sahrens 904a5be7ebbSmarks statp->f_flag = vf_to_stf(vfsp->vfs_flag); 905fa9e4066Sahrens 906fa9e4066Sahrens statp->f_namemax = ZFS_MAXNAMELEN; 907fa9e4066Sahrens 908fa9e4066Sahrens /* 909fa9e4066Sahrens * We have all of 32 characters to stuff a string here. 910fa9e4066Sahrens * Is there anything useful we could/should provide? 911fa9e4066Sahrens */ 912fa9e4066Sahrens bzero(statp->f_fstr, sizeof (statp->f_fstr)); 913fa9e4066Sahrens 914fa9e4066Sahrens ZFS_EXIT(zfsvfs); 915fa9e4066Sahrens return (0); 916fa9e4066Sahrens } 917fa9e4066Sahrens 918fa9e4066Sahrens static int 919fa9e4066Sahrens zfs_root(vfs_t *vfsp, vnode_t **vpp) 920fa9e4066Sahrens { 921fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 922fa9e4066Sahrens znode_t *rootzp; 923fa9e4066Sahrens int error; 924fa9e4066Sahrens 925fa9e4066Sahrens ZFS_ENTER(zfsvfs); 926fa9e4066Sahrens 927fa9e4066Sahrens error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); 928fa9e4066Sahrens if (error == 0) 929fa9e4066Sahrens *vpp = ZTOV(rootzp); 930fa9e4066Sahrens 931fa9e4066Sahrens ZFS_EXIT(zfsvfs); 932fa9e4066Sahrens return (error); 933fa9e4066Sahrens } 934fa9e4066Sahrens 935fa9e4066Sahrens /*ARGSUSED*/ 936fa9e4066Sahrens static int 937fa9e4066Sahrens zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr) 938fa9e4066Sahrens { 939fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 940fa9e4066Sahrens int ret; 941fa9e4066Sahrens 942fa9e4066Sahrens if ((ret = secpolicy_fs_unmount(cr, vfsp)) != 0) 943fa9e4066Sahrens return (ret); 944fa9e4066Sahrens 945033f9833Sek 946033f9833Sek (void) dnlc_purge_vfsp(vfsp, 0); 947033f9833Sek 948fa9e4066Sahrens /* 949fa9e4066Sahrens * Unmount any snapshots mounted under .zfs before unmounting the 950fa9e4066Sahrens * dataset itself. 951fa9e4066Sahrens */ 952fa9e4066Sahrens if (zfsvfs->z_ctldir != NULL && 953fa9e4066Sahrens (ret = zfsctl_umount_snapshots(vfsp, fflag, cr)) != 0) 954fa9e4066Sahrens return (ret); 955fa9e4066Sahrens 956fa9e4066Sahrens if (fflag & MS_FORCE) { 957fa9e4066Sahrens vfsp->vfs_flag |= VFS_UNMOUNTED; 958fa9e4066Sahrens zfsvfs->z_unmounted1 = B_TRUE; 959fa9e4066Sahrens 960fa9e4066Sahrens /* 961fa9e4066Sahrens * Wait for all zfs threads to leave zfs. 962fa9e4066Sahrens * Grabbing a rwlock as reader in all vops and 963fa9e4066Sahrens * as writer here doesn't work because it too easy to get 964fa9e4066Sahrens * multiple reader enters as zfs can re-enter itself. 965fa9e4066Sahrens * This can lead to deadlock if there is an intervening 966fa9e4066Sahrens * rw_enter as writer. 967fa9e4066Sahrens * So a file system threads ref count (z_op_cnt) is used. 968fa9e4066Sahrens * A polling loop on z_op_cnt may seem inefficient, but 969fa9e4066Sahrens * - this saves all threads on exit from having to grab a 970fa9e4066Sahrens * mutex in order to cv_signal 971fa9e4066Sahrens * - only occurs on forced unmount in the rare case when 972fa9e4066Sahrens * there are outstanding threads within the file system. 973fa9e4066Sahrens */ 974fa9e4066Sahrens while (zfsvfs->z_op_cnt) { 975fa9e4066Sahrens delay(1); 976fa9e4066Sahrens } 977fa9e4066Sahrens 978fa9e4066Sahrens zfs_objset_close(zfsvfs); 979fa9e4066Sahrens 980fa9e4066Sahrens return (0); 981fa9e4066Sahrens } 982fa9e4066Sahrens /* 983fa9e4066Sahrens * Check the number of active vnodes in the file system. 984fa9e4066Sahrens * Our count is maintained in the vfs structure, but the number 985fa9e4066Sahrens * is off by 1 to indicate a hold on the vfs structure itself. 986fa9e4066Sahrens * 987fa9e4066Sahrens * The '.zfs' directory maintains a reference of its own, and any active 988fa9e4066Sahrens * references underneath are reflected in the vnode count. 989fa9e4066Sahrens */ 990fa9e4066Sahrens if (zfsvfs->z_ctldir == NULL) { 991893a6d32Sahrens if (vfsp->vfs_count > 1) 992fa9e4066Sahrens return (EBUSY); 993fa9e4066Sahrens } else { 994fa9e4066Sahrens if (vfsp->vfs_count > 2 || 995fa9e4066Sahrens (zfsvfs->z_ctldir->v_count > 1 && !(fflag & MS_FORCE))) { 996fa9e4066Sahrens return (EBUSY); 997fa9e4066Sahrens } 998fa9e4066Sahrens } 999fa9e4066Sahrens 1000fa9e4066Sahrens vfsp->vfs_flag |= VFS_UNMOUNTED; 1001fa9e4066Sahrens zfs_objset_close(zfsvfs); 1002fa9e4066Sahrens 1003fa9e4066Sahrens return (0); 1004fa9e4066Sahrens } 1005fa9e4066Sahrens 1006fa9e4066Sahrens static int 1007fa9e4066Sahrens zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp) 1008fa9e4066Sahrens { 1009fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1010fa9e4066Sahrens znode_t *zp; 1011fa9e4066Sahrens uint64_t object = 0; 1012fa9e4066Sahrens uint64_t fid_gen = 0; 1013fa9e4066Sahrens uint64_t gen_mask; 1014fa9e4066Sahrens uint64_t zp_gen; 1015fa9e4066Sahrens int i, err; 1016fa9e4066Sahrens 1017fa9e4066Sahrens *vpp = NULL; 1018fa9e4066Sahrens 1019fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1020fa9e4066Sahrens 1021fa9e4066Sahrens if (fidp->fid_len == LONG_FID_LEN) { 1022fa9e4066Sahrens zfid_long_t *zlfid = (zfid_long_t *)fidp; 1023fa9e4066Sahrens uint64_t objsetid = 0; 1024fa9e4066Sahrens uint64_t setgen = 0; 1025fa9e4066Sahrens 1026fa9e4066Sahrens for (i = 0; i < sizeof (zlfid->zf_setid); i++) 1027fa9e4066Sahrens objsetid |= ((uint64_t)zlfid->zf_setid[i]) << (8 * i); 1028fa9e4066Sahrens 1029fa9e4066Sahrens for (i = 0; i < sizeof (zlfid->zf_setgen); i++) 1030fa9e4066Sahrens setgen |= ((uint64_t)zlfid->zf_setgen[i]) << (8 * i); 1031fa9e4066Sahrens 1032fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1033fa9e4066Sahrens 1034fa9e4066Sahrens err = zfsctl_lookup_objset(vfsp, objsetid, &zfsvfs); 1035fa9e4066Sahrens if (err) 1036fa9e4066Sahrens return (EINVAL); 1037fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1038fa9e4066Sahrens } 1039fa9e4066Sahrens 1040fa9e4066Sahrens if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) { 1041fa9e4066Sahrens zfid_short_t *zfid = (zfid_short_t *)fidp; 1042fa9e4066Sahrens 1043fa9e4066Sahrens for (i = 0; i < sizeof (zfid->zf_object); i++) 1044fa9e4066Sahrens object |= ((uint64_t)zfid->zf_object[i]) << (8 * i); 1045fa9e4066Sahrens 1046fa9e4066Sahrens for (i = 0; i < sizeof (zfid->zf_gen); i++) 1047fa9e4066Sahrens fid_gen |= ((uint64_t)zfid->zf_gen[i]) << (8 * i); 1048fa9e4066Sahrens } else { 1049fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1050fa9e4066Sahrens return (EINVAL); 1051fa9e4066Sahrens } 1052fa9e4066Sahrens 1053fa9e4066Sahrens /* A zero fid_gen means we are in the .zfs control directories */ 1054fa9e4066Sahrens if (fid_gen == 0 && 1055fa9e4066Sahrens (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) { 1056fa9e4066Sahrens *vpp = zfsvfs->z_ctldir; 1057fa9e4066Sahrens ASSERT(*vpp != NULL); 1058fa9e4066Sahrens if (object == ZFSCTL_INO_SNAPDIR) { 1059fa9e4066Sahrens VERIFY(zfsctl_root_lookup(*vpp, "snapshot", vpp, NULL, 1060fa9e4066Sahrens 0, NULL, NULL) == 0); 1061fa9e4066Sahrens } else { 1062fa9e4066Sahrens VN_HOLD(*vpp); 1063fa9e4066Sahrens } 1064fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1065fa9e4066Sahrens return (0); 1066fa9e4066Sahrens } 1067fa9e4066Sahrens 1068fa9e4066Sahrens gen_mask = -1ULL >> (64 - 8 * i); 1069fa9e4066Sahrens 1070fa9e4066Sahrens dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask); 1071fa9e4066Sahrens if (err = zfs_zget(zfsvfs, object, &zp)) { 1072fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1073fa9e4066Sahrens return (err); 1074fa9e4066Sahrens } 1075fa9e4066Sahrens zp_gen = zp->z_phys->zp_gen & gen_mask; 1076fa9e4066Sahrens if (zp_gen == 0) 1077fa9e4066Sahrens zp_gen = 1; 1078893a6d32Sahrens if (zp->z_unlinked || zp_gen != fid_gen) { 1079fa9e4066Sahrens dprintf("znode gen (%u) != fid gen (%u)\n", zp_gen, fid_gen); 1080fa9e4066Sahrens VN_RELE(ZTOV(zp)); 1081fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1082fa9e4066Sahrens return (EINVAL); 1083fa9e4066Sahrens } 1084fa9e4066Sahrens 1085fa9e4066Sahrens *vpp = ZTOV(zp); 1086fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1087fa9e4066Sahrens return (0); 1088fa9e4066Sahrens } 1089fa9e4066Sahrens 1090fa9e4066Sahrens static void 1091fa9e4066Sahrens zfs_objset_close(zfsvfs_t *zfsvfs) 1092fa9e4066Sahrens { 1093fa9e4066Sahrens znode_t *zp, *nextzp; 1094fa9e4066Sahrens objset_t *os = zfsvfs->z_os; 1095fa9e4066Sahrens 1096fa9e4066Sahrens /* 1097fa9e4066Sahrens * For forced unmount, at this point all vops except zfs_inactive 1098fa9e4066Sahrens * are erroring EIO. We need to now suspend zfs_inactive threads 1099fa9e4066Sahrens * while we are freeing dbufs before switching zfs_inactive 1100fa9e4066Sahrens * to use behaviour without a objset. 1101fa9e4066Sahrens */ 1102fa9e4066Sahrens rw_enter(&zfsvfs->z_um_lock, RW_WRITER); 1103fa9e4066Sahrens 1104fa9e4066Sahrens /* 1105fa9e4066Sahrens * Release all holds on dbufs 1106fa9e4066Sahrens * Note, although we have stopped all other vop threads and 1107fa9e4066Sahrens * zfs_inactive(), the dmu can callback via znode_pageout_func() 1108fa9e4066Sahrens * which can zfs_znode_free() the znode. 1109fa9e4066Sahrens * So we lock z_all_znodes; search the list for a held 1110fa9e4066Sahrens * dbuf; drop the lock (we know zp can't disappear if we hold 1111fa9e4066Sahrens * a dbuf lock; then regrab the lock and restart. 1112fa9e4066Sahrens */ 1113fa9e4066Sahrens mutex_enter(&zfsvfs->z_znodes_lock); 1114fa9e4066Sahrens for (zp = list_head(&zfsvfs->z_all_znodes); zp; zp = nextzp) { 1115fa9e4066Sahrens nextzp = list_next(&zfsvfs->z_all_znodes, zp); 1116fa9e4066Sahrens if (zp->z_dbuf_held) { 1117fa9e4066Sahrens /* dbufs should only be held when force unmounting */ 1118fa9e4066Sahrens zp->z_dbuf_held = 0; 1119fa9e4066Sahrens mutex_exit(&zfsvfs->z_znodes_lock); 1120ea8dc4b6Seschrock dmu_buf_rele(zp->z_dbuf, NULL); 1121fa9e4066Sahrens /* Start again */ 1122fa9e4066Sahrens mutex_enter(&zfsvfs->z_znodes_lock); 1123fa9e4066Sahrens nextzp = list_head(&zfsvfs->z_all_znodes); 1124fa9e4066Sahrens } 1125fa9e4066Sahrens } 1126fa9e4066Sahrens mutex_exit(&zfsvfs->z_znodes_lock); 1127fa9e4066Sahrens 1128fa9e4066Sahrens /* 1129fa9e4066Sahrens * Unregister properties. 1130fa9e4066Sahrens */ 1131ea8dc4b6Seschrock if (!dmu_objset_is_snapshot(os)) 1132ea8dc4b6Seschrock zfs_unregister_callbacks(zfsvfs); 1133fa9e4066Sahrens 1134fa9e4066Sahrens /* 1135fa9e4066Sahrens * Switch zfs_inactive to behaviour without an objset. 1136fa9e4066Sahrens * It just tosses cached pages and frees the znode & vnode. 1137fa9e4066Sahrens * Then re-enable zfs_inactive threads in that new behaviour. 1138fa9e4066Sahrens */ 1139fa9e4066Sahrens zfsvfs->z_unmounted2 = B_TRUE; 1140fa9e4066Sahrens rw_exit(&zfsvfs->z_um_lock); /* re-enable any zfs_inactive threads */ 1141fa9e4066Sahrens 1142fa9e4066Sahrens /* 1143fa9e4066Sahrens * Close the zil. Can't close the zil while zfs_inactive 1144fa9e4066Sahrens * threads are blocked as zil_close can call zfs_inactive. 1145fa9e4066Sahrens */ 1146fa9e4066Sahrens if (zfsvfs->z_log) { 1147fa9e4066Sahrens zil_close(zfsvfs->z_log); 1148fa9e4066Sahrens zfsvfs->z_log = NULL; 1149fa9e4066Sahrens } 1150fa9e4066Sahrens 1151ea8dc4b6Seschrock /* 1152ea8dc4b6Seschrock * Evict all dbufs so that cached znodes will be freed 1153ea8dc4b6Seschrock */ 1154436b2950Sperrin if (dmu_objset_evict_dbufs(os, 1)) { 1155436b2950Sperrin txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0); 1156436b2950Sperrin (void) dmu_objset_evict_dbufs(os, 0); 1157436b2950Sperrin } 1158ea8dc4b6Seschrock 1159fa9e4066Sahrens /* 1160fa9e4066Sahrens * Finally close the objset 1161fa9e4066Sahrens */ 1162fa9e4066Sahrens dmu_objset_close(os); 1163fa9e4066Sahrens 11648afd4dd6Sperrin /* 11658afd4dd6Sperrin * We can now safely destroy the '.zfs' directory node. 11668afd4dd6Sperrin */ 11678afd4dd6Sperrin if (zfsvfs->z_ctldir != NULL) 11688afd4dd6Sperrin zfsctl_destroy(zfsvfs); 11698afd4dd6Sperrin 1170fa9e4066Sahrens } 1171fa9e4066Sahrens 1172fa9e4066Sahrens static void 1173fa9e4066Sahrens zfs_freevfs(vfs_t *vfsp) 1174fa9e4066Sahrens { 1175fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1176fa9e4066Sahrens 1177fa9e4066Sahrens kmem_free(zfsvfs, sizeof (zfsvfs_t)); 1178fa9e4066Sahrens 1179fa9e4066Sahrens atomic_add_32(&zfs_active_fs_count, -1); 1180fa9e4066Sahrens } 1181fa9e4066Sahrens 1182fa9e4066Sahrens /* 1183fa9e4066Sahrens * VFS_INIT() initialization. Note that there is no VFS_FINI(), 1184fa9e4066Sahrens * so we can't safely do any non-idempotent initialization here. 1185fa9e4066Sahrens * Leave that to zfs_init() and zfs_fini(), which are called 1186fa9e4066Sahrens * from the module's _init() and _fini() entry points. 1187fa9e4066Sahrens */ 1188fa9e4066Sahrens /*ARGSUSED*/ 1189fa9e4066Sahrens static int 1190fa9e4066Sahrens zfs_vfsinit(int fstype, char *name) 1191fa9e4066Sahrens { 1192fa9e4066Sahrens int error; 1193fa9e4066Sahrens 1194fa9e4066Sahrens zfsfstype = fstype; 1195fa9e4066Sahrens 1196fa9e4066Sahrens /* 1197fa9e4066Sahrens * Setup vfsops and vnodeops tables. 1198fa9e4066Sahrens */ 1199fa9e4066Sahrens error = vfs_setfsops(fstype, zfs_vfsops_template, &zfs_vfsops); 1200fa9e4066Sahrens if (error != 0) { 1201fa9e4066Sahrens cmn_err(CE_WARN, "zfs: bad vfs ops template"); 1202fa9e4066Sahrens } 1203fa9e4066Sahrens 1204fa9e4066Sahrens error = zfs_create_op_tables(); 1205fa9e4066Sahrens if (error) { 1206fa9e4066Sahrens zfs_remove_op_tables(); 1207fa9e4066Sahrens cmn_err(CE_WARN, "zfs: bad vnode ops template"); 1208fa9e4066Sahrens (void) vfs_freevfsops_by_type(zfsfstype); 1209fa9e4066Sahrens return (error); 1210fa9e4066Sahrens } 1211fa9e4066Sahrens 1212fa9e4066Sahrens mutex_init(&zfs_dev_mtx, NULL, MUTEX_DEFAULT, NULL); 1213fa9e4066Sahrens 1214fa9e4066Sahrens /* 1215a0965f35Sbonwick * Unique major number for all zfs mounts. 1216a0965f35Sbonwick * If we run out of 32-bit minors, we'll getudev() another major. 1217fa9e4066Sahrens */ 1218a0965f35Sbonwick zfs_major = ddi_name_to_major(ZFS_DRIVER); 1219a0965f35Sbonwick zfs_minor = ZFS_MIN_MINOR; 1220fa9e4066Sahrens 1221fa9e4066Sahrens return (0); 1222fa9e4066Sahrens } 1223fa9e4066Sahrens 1224fa9e4066Sahrens void 1225fa9e4066Sahrens zfs_init(void) 1226fa9e4066Sahrens { 1227fa9e4066Sahrens /* 1228fa9e4066Sahrens * Initialize .zfs directory structures 1229fa9e4066Sahrens */ 1230fa9e4066Sahrens zfsctl_init(); 1231fa9e4066Sahrens 1232fa9e4066Sahrens /* 1233fa9e4066Sahrens * Initialize znode cache, vnode ops, etc... 1234fa9e4066Sahrens */ 1235fa9e4066Sahrens zfs_znode_init(); 1236fa9e4066Sahrens } 1237fa9e4066Sahrens 1238fa9e4066Sahrens void 1239fa9e4066Sahrens zfs_fini(void) 1240fa9e4066Sahrens { 1241fa9e4066Sahrens zfsctl_fini(); 1242fa9e4066Sahrens zfs_znode_fini(); 1243fa9e4066Sahrens } 1244fa9e4066Sahrens 1245fa9e4066Sahrens int 1246fa9e4066Sahrens zfs_busy(void) 1247fa9e4066Sahrens { 1248fa9e4066Sahrens return (zfs_active_fs_count != 0); 1249fa9e4066Sahrens } 1250fa9e4066Sahrens 1251fa9e4066Sahrens static vfsdef_t vfw = { 1252fa9e4066Sahrens VFSDEF_VERSION, 1253fa9e4066Sahrens MNTTYPE_ZFS, 1254fa9e4066Sahrens zfs_vfsinit, 12555a59a8b3Srsb VSW_HASPROTO|VSW_CANRWRO|VSW_CANREMOUNT|VSW_VOLATILEDEV|VSW_STATS, 1256fa9e4066Sahrens &zfs_mntopts 1257fa9e4066Sahrens }; 1258fa9e4066Sahrens 1259fa9e4066Sahrens struct modlfs zfs_modlfs = { 1260e9dbad6fSeschrock &mod_fsops, "ZFS filesystem version " ZFS_VERSION_STRING, &vfw 1261fa9e4066Sahrens }; 1262