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 /* 229e1320c0SMark Shellenbaum * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23fa9e4066Sahrens * Use is subject to license terms. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 26fa9e4066Sahrens #include <sys/types.h> 27fa9e4066Sahrens #include <sys/param.h> 28fa9e4066Sahrens #include <sys/systm.h> 29fa9e4066Sahrens #include <sys/sysmacros.h> 30fa9e4066Sahrens #include <sys/kmem.h> 31fa9e4066Sahrens #include <sys/pathname.h> 32fa9e4066Sahrens #include <sys/vnode.h> 33fa9e4066Sahrens #include <sys/vfs.h> 34aa59c4cbSrsb #include <sys/vfs_opreg.h> 35fa9e4066Sahrens #include <sys/mntent.h> 36fa9e4066Sahrens #include <sys/mount.h> 37fa9e4066Sahrens #include <sys/cmn_err.h> 38fa9e4066Sahrens #include "fs/fs_subr.h" 39fa9e4066Sahrens #include <sys/zfs_znode.h> 40893a6d32Sahrens #include <sys/zfs_dir.h> 41fa9e4066Sahrens #include <sys/zil.h> 42fa9e4066Sahrens #include <sys/fs/zfs.h> 43fa9e4066Sahrens #include <sys/dmu.h> 44fa9e4066Sahrens #include <sys/dsl_prop.h> 45b1b8ab34Slling #include <sys/dsl_dataset.h> 46ecd6cf80Smarks #include <sys/dsl_deleg.h> 47fa9e4066Sahrens #include <sys/spa.h> 48fa9e4066Sahrens #include <sys/zap.h> 49fa9e4066Sahrens #include <sys/varargs.h> 50fa9e4066Sahrens #include <sys/policy.h> 51fa9e4066Sahrens #include <sys/atomic.h> 52fa9e4066Sahrens #include <sys/mkdev.h> 53fa9e4066Sahrens #include <sys/modctl.h> 54ecd6cf80Smarks #include <sys/refstr.h> 55fa9e4066Sahrens #include <sys/zfs_ioctl.h> 56fa9e4066Sahrens #include <sys/zfs_ctldir.h> 57da6c28aaSamw #include <sys/zfs_fuid.h> 58ea8dc4b6Seschrock #include <sys/bootconf.h> 59a0965f35Sbonwick #include <sys/sunddi.h> 60033f9833Sek #include <sys/dnlc.h> 61f18faf3fSek #include <sys/dmu_objset.h> 62e7cbe64fSgw #include <sys/spa_boot.h> 63fa9e4066Sahrens 64fa9e4066Sahrens int zfsfstype; 65fa9e4066Sahrens vfsops_t *zfs_vfsops = NULL; 66a0965f35Sbonwick static major_t zfs_major; 67fa9e4066Sahrens static minor_t zfs_minor; 68fa9e4066Sahrens static kmutex_t zfs_dev_mtx; 69fa9e4066Sahrens 70*54d692b7SGeorge Wilson extern int sys_shutdown; 71*54d692b7SGeorge Wilson 72fa9e4066Sahrens static int zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr); 73fa9e4066Sahrens static int zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr); 74ea8dc4b6Seschrock static int zfs_mountroot(vfs_t *vfsp, enum whymountroot); 75fa9e4066Sahrens static int zfs_root(vfs_t *vfsp, vnode_t **vpp); 76fa9e4066Sahrens static int zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp); 77fa9e4066Sahrens static int zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp); 78fa9e4066Sahrens static void zfs_freevfs(vfs_t *vfsp); 79fa9e4066Sahrens 80fa9e4066Sahrens static const fs_operation_def_t zfs_vfsops_template[] = { 81aa59c4cbSrsb VFSNAME_MOUNT, { .vfs_mount = zfs_mount }, 82aa59c4cbSrsb VFSNAME_MOUNTROOT, { .vfs_mountroot = zfs_mountroot }, 83aa59c4cbSrsb VFSNAME_UNMOUNT, { .vfs_unmount = zfs_umount }, 84aa59c4cbSrsb VFSNAME_ROOT, { .vfs_root = zfs_root }, 85aa59c4cbSrsb VFSNAME_STATVFS, { .vfs_statvfs = zfs_statvfs }, 86aa59c4cbSrsb VFSNAME_SYNC, { .vfs_sync = zfs_sync }, 87aa59c4cbSrsb VFSNAME_VGET, { .vfs_vget = zfs_vget }, 88aa59c4cbSrsb VFSNAME_FREEVFS, { .vfs_freevfs = zfs_freevfs }, 89aa59c4cbSrsb NULL, NULL 90fa9e4066Sahrens }; 91fa9e4066Sahrens 92fa9e4066Sahrens static const fs_operation_def_t zfs_vfsops_eio_template[] = { 93aa59c4cbSrsb VFSNAME_FREEVFS, { .vfs_freevfs = zfs_freevfs }, 94aa59c4cbSrsb NULL, NULL 95fa9e4066Sahrens }; 96fa9e4066Sahrens 97fa9e4066Sahrens /* 98fa9e4066Sahrens * We need to keep a count of active fs's. 99fa9e4066Sahrens * This is necessary to prevent our module 100fa9e4066Sahrens * from being unloaded after a umount -f 101fa9e4066Sahrens */ 102fa9e4066Sahrens static uint32_t zfs_active_fs_count = 0; 103fa9e4066Sahrens 104fa9e4066Sahrens static char *noatime_cancel[] = { MNTOPT_ATIME, NULL }; 105fa9e4066Sahrens static char *atime_cancel[] = { MNTOPT_NOATIME, NULL }; 1067b55fa8eSck static char *noxattr_cancel[] = { MNTOPT_XATTR, NULL }; 1077b55fa8eSck static char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL }; 108fa9e4066Sahrens 1097b55fa8eSck /* 110b510d378Slling * MO_DEFAULT is not used since the default value is determined 111b510d378Slling * by the equivalent property. 1127b55fa8eSck */ 113fa9e4066Sahrens static mntopt_t mntopts[] = { 1147b55fa8eSck { MNTOPT_NOXATTR, noxattr_cancel, NULL, 0, NULL }, 1157b55fa8eSck { MNTOPT_XATTR, xattr_cancel, NULL, 0, NULL }, 116b510d378Slling { MNTOPT_NOATIME, noatime_cancel, NULL, 0, NULL }, 117fa9e4066Sahrens { MNTOPT_ATIME, atime_cancel, NULL, 0, NULL } 118fa9e4066Sahrens }; 119fa9e4066Sahrens 120fa9e4066Sahrens static mntopts_t zfs_mntopts = { 121fa9e4066Sahrens sizeof (mntopts) / sizeof (mntopt_t), 122fa9e4066Sahrens mntopts 123fa9e4066Sahrens }; 124fa9e4066Sahrens 125fa9e4066Sahrens /*ARGSUSED*/ 126fa9e4066Sahrens int 127fa9e4066Sahrens zfs_sync(vfs_t *vfsp, short flag, cred_t *cr) 128fa9e4066Sahrens { 129fa9e4066Sahrens /* 130fa9e4066Sahrens * Data integrity is job one. We don't want a compromised kernel 131fa9e4066Sahrens * writing to the storage pool, so we never sync during panic. 132fa9e4066Sahrens */ 133fa9e4066Sahrens if (panicstr) 134fa9e4066Sahrens return (0); 135fa9e4066Sahrens 136fa9e4066Sahrens /* 137fa9e4066Sahrens * SYNC_ATTR is used by fsflush() to force old filesystems like UFS 138fa9e4066Sahrens * to sync metadata, which they would otherwise cache indefinitely. 139fa9e4066Sahrens * Semantically, the only requirement is that the sync be initiated. 140fa9e4066Sahrens * The DMU syncs out txgs frequently, so there's nothing to do. 141fa9e4066Sahrens */ 142fa9e4066Sahrens if (flag & SYNC_ATTR) 143fa9e4066Sahrens return (0); 144fa9e4066Sahrens 145fa9e4066Sahrens if (vfsp != NULL) { 146fa9e4066Sahrens /* 147fa9e4066Sahrens * Sync a specific filesystem. 148fa9e4066Sahrens */ 149fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 150*54d692b7SGeorge Wilson dsl_pool_t *dp; 151fa9e4066Sahrens 152fa9e4066Sahrens ZFS_ENTER(zfsvfs); 153*54d692b7SGeorge Wilson dp = dmu_objset_pool(zfsvfs->z_os); 154*54d692b7SGeorge Wilson 155*54d692b7SGeorge Wilson /* 156*54d692b7SGeorge Wilson * If the system is shutting down, then skip any 157*54d692b7SGeorge Wilson * filesystems which may exist on a suspended pool. 158*54d692b7SGeorge Wilson */ 159*54d692b7SGeorge Wilson if (sys_shutdown && spa_suspended(dp->dp_spa)) { 160*54d692b7SGeorge Wilson ZFS_EXIT(zfsvfs); 161*54d692b7SGeorge Wilson return (0); 162*54d692b7SGeorge Wilson } 163*54d692b7SGeorge Wilson 164fa9e4066Sahrens if (zfsvfs->z_log != NULL) 165b19a79ecSperrin zil_commit(zfsvfs->z_log, UINT64_MAX, 0); 166fa9e4066Sahrens else 167*54d692b7SGeorge Wilson txg_wait_synced(dp, 0); 168fa9e4066Sahrens ZFS_EXIT(zfsvfs); 169fa9e4066Sahrens } else { 170fa9e4066Sahrens /* 171fa9e4066Sahrens * Sync all ZFS filesystems. This is what happens when you 172fa9e4066Sahrens * run sync(1M). Unlike other filesystems, ZFS honors the 173fa9e4066Sahrens * request by waiting for all pools to commit all dirty data. 174fa9e4066Sahrens */ 175fa9e4066Sahrens spa_sync_allpools(); 176fa9e4066Sahrens } 177fa9e4066Sahrens 178fa9e4066Sahrens return (0); 179fa9e4066Sahrens } 180fa9e4066Sahrens 181ea8dc4b6Seschrock static int 182ea8dc4b6Seschrock zfs_create_unique_device(dev_t *dev) 183ea8dc4b6Seschrock { 184ea8dc4b6Seschrock major_t new_major; 185ea8dc4b6Seschrock 186ea8dc4b6Seschrock do { 187ea8dc4b6Seschrock ASSERT3U(zfs_minor, <=, MAXMIN32); 188ea8dc4b6Seschrock minor_t start = zfs_minor; 189ea8dc4b6Seschrock do { 190ea8dc4b6Seschrock mutex_enter(&zfs_dev_mtx); 191ea8dc4b6Seschrock if (zfs_minor >= MAXMIN32) { 192ea8dc4b6Seschrock /* 193ea8dc4b6Seschrock * If we're still using the real major 194ea8dc4b6Seschrock * keep out of /dev/zfs and /dev/zvol minor 195ea8dc4b6Seschrock * number space. If we're using a getudev()'ed 196ea8dc4b6Seschrock * major number, we can use all of its minors. 197ea8dc4b6Seschrock */ 198ea8dc4b6Seschrock if (zfs_major == ddi_name_to_major(ZFS_DRIVER)) 199ea8dc4b6Seschrock zfs_minor = ZFS_MIN_MINOR; 200ea8dc4b6Seschrock else 201ea8dc4b6Seschrock zfs_minor = 0; 202ea8dc4b6Seschrock } else { 203ea8dc4b6Seschrock zfs_minor++; 204ea8dc4b6Seschrock } 205ea8dc4b6Seschrock *dev = makedevice(zfs_major, zfs_minor); 206ea8dc4b6Seschrock mutex_exit(&zfs_dev_mtx); 207ea8dc4b6Seschrock } while (vfs_devismounted(*dev) && zfs_minor != start); 208ea8dc4b6Seschrock if (zfs_minor == start) { 209ea8dc4b6Seschrock /* 210ea8dc4b6Seschrock * We are using all ~262,000 minor numbers for the 211ea8dc4b6Seschrock * current major number. Create a new major number. 212ea8dc4b6Seschrock */ 213ea8dc4b6Seschrock if ((new_major = getudev()) == (major_t)-1) { 214ea8dc4b6Seschrock cmn_err(CE_WARN, 215ea8dc4b6Seschrock "zfs_mount: Can't get unique major " 216ea8dc4b6Seschrock "device number."); 217ea8dc4b6Seschrock return (-1); 218ea8dc4b6Seschrock } 219ea8dc4b6Seschrock mutex_enter(&zfs_dev_mtx); 220ea8dc4b6Seschrock zfs_major = new_major; 221ea8dc4b6Seschrock zfs_minor = 0; 222ea8dc4b6Seschrock 223ea8dc4b6Seschrock mutex_exit(&zfs_dev_mtx); 224ea8dc4b6Seschrock } else { 225ea8dc4b6Seschrock break; 226ea8dc4b6Seschrock } 227ea8dc4b6Seschrock /* CONSTANTCONDITION */ 228ea8dc4b6Seschrock } while (1); 229ea8dc4b6Seschrock 230ea8dc4b6Seschrock return (0); 231ea8dc4b6Seschrock } 232ea8dc4b6Seschrock 233fa9e4066Sahrens static void 234fa9e4066Sahrens atime_changed_cb(void *arg, uint64_t newval) 235fa9e4066Sahrens { 236fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 237fa9e4066Sahrens 238fa9e4066Sahrens if (newval == TRUE) { 239fa9e4066Sahrens zfsvfs->z_atime = TRUE; 240fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME); 241fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_ATIME, NULL, 0); 242fa9e4066Sahrens } else { 243fa9e4066Sahrens zfsvfs->z_atime = FALSE; 244fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_ATIME); 245fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME, NULL, 0); 246fa9e4066Sahrens } 247fa9e4066Sahrens } 248fa9e4066Sahrens 2497b55fa8eSck static void 2507b55fa8eSck xattr_changed_cb(void *arg, uint64_t newval) 2517b55fa8eSck { 2527b55fa8eSck zfsvfs_t *zfsvfs = arg; 2537b55fa8eSck 2547b55fa8eSck if (newval == TRUE) { 2557b55fa8eSck /* XXX locking on vfs_flag? */ 2567b55fa8eSck zfsvfs->z_vfs->vfs_flag |= VFS_XATTR; 2577b55fa8eSck vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR); 2587b55fa8eSck vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_XATTR, NULL, 0); 2597b55fa8eSck } else { 2607b55fa8eSck /* XXX locking on vfs_flag? */ 2617b55fa8eSck zfsvfs->z_vfs->vfs_flag &= ~VFS_XATTR; 2627b55fa8eSck vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_XATTR); 2637b55fa8eSck vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR, NULL, 0); 2647b55fa8eSck } 2657b55fa8eSck } 2667b55fa8eSck 267fa9e4066Sahrens static void 268fa9e4066Sahrens blksz_changed_cb(void *arg, uint64_t newval) 269fa9e4066Sahrens { 270fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 271fa9e4066Sahrens 272fa9e4066Sahrens if (newval < SPA_MINBLOCKSIZE || 273fa9e4066Sahrens newval > SPA_MAXBLOCKSIZE || !ISP2(newval)) 274fa9e4066Sahrens newval = SPA_MAXBLOCKSIZE; 275fa9e4066Sahrens 276fa9e4066Sahrens zfsvfs->z_max_blksz = newval; 277fa9e4066Sahrens zfsvfs->z_vfs->vfs_bsize = newval; 278fa9e4066Sahrens } 279fa9e4066Sahrens 280fa9e4066Sahrens static void 281fa9e4066Sahrens readonly_changed_cb(void *arg, uint64_t newval) 282fa9e4066Sahrens { 283fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 284fa9e4066Sahrens 285fa9e4066Sahrens if (newval) { 286fa9e4066Sahrens /* XXX locking on vfs_flag? */ 287fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY; 288fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RW); 289fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RO, NULL, 0); 290fa9e4066Sahrens } else { 291fa9e4066Sahrens /* XXX locking on vfs_flag? */ 292fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 293fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RO); 294fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RW, NULL, 0); 295fa9e4066Sahrens } 296fa9e4066Sahrens } 297fa9e4066Sahrens 298fa9e4066Sahrens static void 299fa9e4066Sahrens devices_changed_cb(void *arg, uint64_t newval) 300fa9e4066Sahrens { 301fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 302fa9e4066Sahrens 303fa9e4066Sahrens if (newval == FALSE) { 304fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NODEVICES; 305fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES); 306fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES, NULL, 0); 307fa9e4066Sahrens } else { 308fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NODEVICES; 309fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES); 310fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES, NULL, 0); 311fa9e4066Sahrens } 312fa9e4066Sahrens } 313fa9e4066Sahrens 314fa9e4066Sahrens static void 315fa9e4066Sahrens setuid_changed_cb(void *arg, uint64_t newval) 316fa9e4066Sahrens { 317fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 318fa9e4066Sahrens 319fa9e4066Sahrens if (newval == FALSE) { 320fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NOSETUID; 321fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_SETUID); 322fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID, NULL, 0); 323fa9e4066Sahrens } else { 324fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NOSETUID; 325fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID); 326fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_SETUID, NULL, 0); 327fa9e4066Sahrens } 328fa9e4066Sahrens } 329fa9e4066Sahrens 330fa9e4066Sahrens static void 331fa9e4066Sahrens exec_changed_cb(void *arg, uint64_t newval) 332fa9e4066Sahrens { 333fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 334fa9e4066Sahrens 335fa9e4066Sahrens if (newval == FALSE) { 336fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag |= VFS_NOEXEC; 337fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_EXEC); 338fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC, NULL, 0); 339fa9e4066Sahrens } else { 340fa9e4066Sahrens zfsvfs->z_vfs->vfs_flag &= ~VFS_NOEXEC; 341fa9e4066Sahrens vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC); 342fa9e4066Sahrens vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_EXEC, NULL, 0); 343fa9e4066Sahrens } 344fa9e4066Sahrens } 345fa9e4066Sahrens 346da6c28aaSamw /* 347da6c28aaSamw * The nbmand mount option can be changed at mount time. 348da6c28aaSamw * We can't allow it to be toggled on live file systems or incorrect 349da6c28aaSamw * behavior may be seen from cifs clients 350da6c28aaSamw * 351da6c28aaSamw * This property isn't registered via dsl_prop_register(), but this callback 352da6c28aaSamw * will be called when a file system is first mounted 353da6c28aaSamw */ 354da6c28aaSamw static void 355da6c28aaSamw nbmand_changed_cb(void *arg, uint64_t newval) 356da6c28aaSamw { 357da6c28aaSamw zfsvfs_t *zfsvfs = arg; 358da6c28aaSamw if (newval == FALSE) { 359da6c28aaSamw vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND); 360da6c28aaSamw vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND, NULL, 0); 361da6c28aaSamw } else { 362da6c28aaSamw vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND); 363da6c28aaSamw vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND, NULL, 0); 364da6c28aaSamw } 365da6c28aaSamw } 366da6c28aaSamw 367fa9e4066Sahrens static void 368fa9e4066Sahrens snapdir_changed_cb(void *arg, uint64_t newval) 369fa9e4066Sahrens { 370fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 371fa9e4066Sahrens 372fa9e4066Sahrens zfsvfs->z_show_ctldir = newval; 373fa9e4066Sahrens } 374fa9e4066Sahrens 375da6c28aaSamw static void 376da6c28aaSamw vscan_changed_cb(void *arg, uint64_t newval) 377da6c28aaSamw { 378da6c28aaSamw zfsvfs_t *zfsvfs = arg; 379da6c28aaSamw 380da6c28aaSamw zfsvfs->z_vscan = newval; 381da6c28aaSamw } 382da6c28aaSamw 383fa9e4066Sahrens static void 384fa9e4066Sahrens acl_mode_changed_cb(void *arg, uint64_t newval) 385fa9e4066Sahrens { 386fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 387fa9e4066Sahrens 388fa9e4066Sahrens zfsvfs->z_acl_mode = newval; 389fa9e4066Sahrens } 390fa9e4066Sahrens 391fa9e4066Sahrens static void 392fa9e4066Sahrens acl_inherit_changed_cb(void *arg, uint64_t newval) 393fa9e4066Sahrens { 394fa9e4066Sahrens zfsvfs_t *zfsvfs = arg; 395fa9e4066Sahrens 396fa9e4066Sahrens zfsvfs->z_acl_inherit = newval; 397fa9e4066Sahrens } 398fa9e4066Sahrens 399ea8dc4b6Seschrock static int 400ea8dc4b6Seschrock zfs_register_callbacks(vfs_t *vfsp) 401ea8dc4b6Seschrock { 402ea8dc4b6Seschrock struct dsl_dataset *ds = NULL; 403ea8dc4b6Seschrock objset_t *os = NULL; 404ea8dc4b6Seschrock zfsvfs_t *zfsvfs = NULL; 405da6c28aaSamw uint64_t nbmand; 406da6c28aaSamw int readonly, do_readonly = B_FALSE; 407da6c28aaSamw int setuid, do_setuid = B_FALSE; 408da6c28aaSamw int exec, do_exec = B_FALSE; 409da6c28aaSamw int devices, do_devices = B_FALSE; 410da6c28aaSamw int xattr, do_xattr = B_FALSE; 411da6c28aaSamw int atime, do_atime = B_FALSE; 412ea8dc4b6Seschrock int error = 0; 413ea8dc4b6Seschrock 414ea8dc4b6Seschrock ASSERT(vfsp); 415ea8dc4b6Seschrock zfsvfs = vfsp->vfs_data; 416ea8dc4b6Seschrock ASSERT(zfsvfs); 417ea8dc4b6Seschrock os = zfsvfs->z_os; 418fa9e4066Sahrens 419fa9e4066Sahrens /* 420ea8dc4b6Seschrock * The act of registering our callbacks will destroy any mount 421ea8dc4b6Seschrock * options we may have. In order to enable temporary overrides 4227b55fa8eSck * of mount options, we stash away the current values and 423ea8dc4b6Seschrock * restore them after we register the callbacks. 424fa9e4066Sahrens */ 425ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_RO, NULL)) { 426ea8dc4b6Seschrock readonly = B_TRUE; 427ea8dc4b6Seschrock do_readonly = B_TRUE; 428ea8dc4b6Seschrock } else if (vfs_optionisset(vfsp, MNTOPT_RW, NULL)) { 429ea8dc4b6Seschrock readonly = B_FALSE; 430ea8dc4b6Seschrock do_readonly = B_TRUE; 431ea8dc4b6Seschrock } 432ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL)) { 433ea8dc4b6Seschrock devices = B_FALSE; 434ea8dc4b6Seschrock setuid = B_FALSE; 435ea8dc4b6Seschrock do_devices = B_TRUE; 436ea8dc4b6Seschrock do_setuid = B_TRUE; 437ea8dc4b6Seschrock } else { 438ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL)) { 439ea8dc4b6Seschrock devices = B_FALSE; 440ea8dc4b6Seschrock do_devices = B_TRUE; 441b1b8ab34Slling } else if (vfs_optionisset(vfsp, MNTOPT_DEVICES, NULL)) { 442ea8dc4b6Seschrock devices = B_TRUE; 443ea8dc4b6Seschrock do_devices = B_TRUE; 444fa9e4066Sahrens } 445fa9e4066Sahrens 446ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) { 447ea8dc4b6Seschrock setuid = B_FALSE; 448ea8dc4b6Seschrock do_setuid = B_TRUE; 449ea8dc4b6Seschrock } else if (vfs_optionisset(vfsp, MNTOPT_SETUID, NULL)) { 450ea8dc4b6Seschrock setuid = B_TRUE; 451ea8dc4b6Seschrock do_setuid = B_TRUE; 452fa9e4066Sahrens } 453ea8dc4b6Seschrock } 454ea8dc4b6Seschrock if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) { 455ea8dc4b6Seschrock exec = B_FALSE; 456ea8dc4b6Seschrock do_exec = B_TRUE; 457ea8dc4b6Seschrock } else if (vfs_optionisset(vfsp, MNTOPT_EXEC, NULL)) { 458ea8dc4b6Seschrock exec = B_TRUE; 459ea8dc4b6Seschrock do_exec = B_TRUE; 460fa9e4066Sahrens } 4617b55fa8eSck if (vfs_optionisset(vfsp, MNTOPT_NOXATTR, NULL)) { 4627b55fa8eSck xattr = B_FALSE; 4637b55fa8eSck do_xattr = B_TRUE; 4647b55fa8eSck } else if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) { 4657b55fa8eSck xattr = B_TRUE; 4667b55fa8eSck do_xattr = B_TRUE; 4677b55fa8eSck } 468b510d378Slling if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) { 469b510d378Slling atime = B_FALSE; 470b510d378Slling do_atime = B_TRUE; 471b510d378Slling } else if (vfs_optionisset(vfsp, MNTOPT_ATIME, NULL)) { 472b510d378Slling atime = B_TRUE; 473b510d378Slling do_atime = B_TRUE; 474b510d378Slling } 475fa9e4066Sahrens 476da6c28aaSamw /* 477da6c28aaSamw * nbmand is a special property. It can only be changed at 478da6c28aaSamw * mount time. 479da6c28aaSamw * 480da6c28aaSamw * This is weird, but it is documented to only be changeable 481da6c28aaSamw * at mount time. 482da6c28aaSamw */ 483da6c28aaSamw if (vfs_optionisset(vfsp, MNTOPT_NONBMAND, NULL)) { 484da6c28aaSamw nbmand = B_FALSE; 485da6c28aaSamw } else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) { 486da6c28aaSamw nbmand = B_TRUE; 487da6c28aaSamw } else { 488da6c28aaSamw char osname[MAXNAMELEN]; 489da6c28aaSamw 490da6c28aaSamw dmu_objset_name(os, osname); 491da6c28aaSamw if (error = dsl_prop_get_integer(osname, "nbmand", &nbmand, 492bb0ade09Sahrens NULL)) { 493bb0ade09Sahrens return (error); 494bb0ade09Sahrens } 495da6c28aaSamw } 496da6c28aaSamw 497fa9e4066Sahrens /* 498ea8dc4b6Seschrock * Register property callbacks. 499ea8dc4b6Seschrock * 500ea8dc4b6Seschrock * It would probably be fine to just check for i/o error from 501ea8dc4b6Seschrock * the first prop_register(), but I guess I like to go 502ea8dc4b6Seschrock * overboard... 503fa9e4066Sahrens */ 504ea8dc4b6Seschrock ds = dmu_objset_ds(os); 505ea8dc4b6Seschrock error = dsl_prop_register(ds, "atime", atime_changed_cb, zfsvfs); 5067b55fa8eSck error = error ? error : dsl_prop_register(ds, 5077b55fa8eSck "xattr", xattr_changed_cb, zfsvfs); 508ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 509ea8dc4b6Seschrock "recordsize", blksz_changed_cb, zfsvfs); 510ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 511ea8dc4b6Seschrock "readonly", readonly_changed_cb, zfsvfs); 512ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 513ea8dc4b6Seschrock "devices", devices_changed_cb, zfsvfs); 514ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 515ea8dc4b6Seschrock "setuid", setuid_changed_cb, zfsvfs); 516ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 517ea8dc4b6Seschrock "exec", exec_changed_cb, zfsvfs); 518ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 519ea8dc4b6Seschrock "snapdir", snapdir_changed_cb, zfsvfs); 520ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 521ea8dc4b6Seschrock "aclmode", acl_mode_changed_cb, zfsvfs); 522ea8dc4b6Seschrock error = error ? error : dsl_prop_register(ds, 523ea8dc4b6Seschrock "aclinherit", acl_inherit_changed_cb, zfsvfs); 524da6c28aaSamw error = error ? error : dsl_prop_register(ds, 525da6c28aaSamw "vscan", vscan_changed_cb, zfsvfs); 526ea8dc4b6Seschrock if (error) 527ea8dc4b6Seschrock goto unregister; 528fa9e4066Sahrens 529ea8dc4b6Seschrock /* 530ea8dc4b6Seschrock * Invoke our callbacks to restore temporary mount options. 531ea8dc4b6Seschrock */ 532ea8dc4b6Seschrock if (do_readonly) 533ea8dc4b6Seschrock readonly_changed_cb(zfsvfs, readonly); 534ea8dc4b6Seschrock if (do_setuid) 535ea8dc4b6Seschrock setuid_changed_cb(zfsvfs, setuid); 536ea8dc4b6Seschrock if (do_exec) 537ea8dc4b6Seschrock exec_changed_cb(zfsvfs, exec); 538ea8dc4b6Seschrock if (do_devices) 539ea8dc4b6Seschrock devices_changed_cb(zfsvfs, devices); 5407b55fa8eSck if (do_xattr) 5417b55fa8eSck xattr_changed_cb(zfsvfs, xattr); 542b510d378Slling if (do_atime) 543b510d378Slling atime_changed_cb(zfsvfs, atime); 544fa9e4066Sahrens 545da6c28aaSamw nbmand_changed_cb(zfsvfs, nbmand); 546da6c28aaSamw 547ea8dc4b6Seschrock return (0); 548fa9e4066Sahrens 549ea8dc4b6Seschrock unregister: 550fa9e4066Sahrens /* 551ea8dc4b6Seschrock * We may attempt to unregister some callbacks that are not 552ea8dc4b6Seschrock * registered, but this is OK; it will simply return ENOMSG, 553ea8dc4b6Seschrock * which we will ignore. 554fa9e4066Sahrens */ 555ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "atime", atime_changed_cb, zfsvfs); 5567b55fa8eSck (void) dsl_prop_unregister(ds, "xattr", xattr_changed_cb, zfsvfs); 557ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, zfsvfs); 558ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "readonly", readonly_changed_cb, zfsvfs); 559ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "devices", devices_changed_cb, zfsvfs); 560ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "setuid", setuid_changed_cb, zfsvfs); 561ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "exec", exec_changed_cb, zfsvfs); 562ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, zfsvfs); 563ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, zfsvfs); 564ea8dc4b6Seschrock (void) dsl_prop_unregister(ds, "aclinherit", acl_inherit_changed_cb, 565ea8dc4b6Seschrock zfsvfs); 566da6c28aaSamw (void) dsl_prop_unregister(ds, "vscan", vscan_changed_cb, zfsvfs); 567ea8dc4b6Seschrock return (error); 568ea8dc4b6Seschrock 569ea8dc4b6Seschrock } 570ea8dc4b6Seschrock 571f18faf3fSek static int 572f18faf3fSek zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) 573f18faf3fSek { 574f18faf3fSek int error; 575f18faf3fSek 576f18faf3fSek error = zfs_register_callbacks(zfsvfs->z_vfs); 577f18faf3fSek if (error) 578f18faf3fSek return (error); 579f18faf3fSek 580f18faf3fSek /* 581f18faf3fSek * Set the objset user_ptr to track its zfsvfs. 582f18faf3fSek */ 583f18faf3fSek mutex_enter(&zfsvfs->z_os->os->os_user_ptr_lock); 584f18faf3fSek dmu_objset_set_user(zfsvfs->z_os, zfsvfs); 585f18faf3fSek mutex_exit(&zfsvfs->z_os->os->os_user_ptr_lock); 586f18faf3fSek 587f18faf3fSek /* 588f18faf3fSek * If we are not mounting (ie: online recv), then we don't 589f18faf3fSek * have to worry about replaying the log as we blocked all 590f18faf3fSek * operations out since we closed the ZIL. 591f18faf3fSek */ 592f18faf3fSek if (mounting) { 593a6e57bd4SNeil Perrin boolean_t readonly; 594a6e57bd4SNeil Perrin 595f18faf3fSek /* 596f18faf3fSek * During replay we remove the read only flag to 597f18faf3fSek * allow replays to succeed. 598f18faf3fSek */ 599f18faf3fSek readonly = zfsvfs->z_vfs->vfs_flag & VFS_RDONLY; 6001209a471SNeil Perrin if (readonly != 0) 6011209a471SNeil Perrin zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY; 6021209a471SNeil Perrin else 6031209a471SNeil Perrin zfs_unlinked_drain(zfsvfs); 604f18faf3fSek 6051209a471SNeil Perrin zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data); 6061209a471SNeil Perrin if (zil_disable) { 6071209a471SNeil Perrin zil_destroy(zfsvfs->z_log, 0); 6081209a471SNeil Perrin zfsvfs->z_log = NULL; 6091209a471SNeil Perrin } else { 6101209a471SNeil Perrin /* 6111209a471SNeil Perrin * Parse and replay the intent log. 6121209a471SNeil Perrin * 6131209a471SNeil Perrin * Because of ziltest, this must be done after 6141209a471SNeil Perrin * zfs_unlinked_drain(). (Further note: ziltest 6151209a471SNeil Perrin * doesn't use readonly mounts, where 6161209a471SNeil Perrin * zfs_unlinked_drain() isn't called.) This is because 6171209a471SNeil Perrin * ziltest causes spa_sync() to think it's committed, 6181209a471SNeil Perrin * but actually it is not, so the intent log contains 6191209a471SNeil Perrin * many txg's worth of changes. 6201209a471SNeil Perrin * 6211209a471SNeil Perrin * In particular, if object N is in the unlinked set in 6221209a471SNeil Perrin * the last txg to actually sync, then it could be 6231209a471SNeil Perrin * actually freed in a later txg and then reallocated 6241209a471SNeil Perrin * in a yet later txg. This would write a "create 6251209a471SNeil Perrin * object N" record to the intent log. Normally, this 6261209a471SNeil Perrin * would be fine because the spa_sync() would have 6271209a471SNeil Perrin * written out the fact that object N is free, before 6281209a471SNeil Perrin * we could write the "create object N" intent log 6291209a471SNeil Perrin * record. 6301209a471SNeil Perrin * 6311209a471SNeil Perrin * But when we are in ziltest mode, we advance the "open 6321209a471SNeil Perrin * txg" without actually spa_sync()-ing the changes to 6331209a471SNeil Perrin * disk. So we would see that object N is still 6341209a471SNeil Perrin * allocated and in the unlinked set, and there is an 6351209a471SNeil Perrin * intent log record saying to allocate it. 6361209a471SNeil Perrin */ 6371209a471SNeil Perrin zfsvfs->z_replay = B_TRUE; 6381209a471SNeil Perrin zil_replay(zfsvfs->z_os, zfsvfs, zfs_replay_vector); 6391209a471SNeil Perrin zfsvfs->z_replay = B_FALSE; 6401209a471SNeil Perrin } 641f18faf3fSek zfsvfs->z_vfs->vfs_flag |= readonly; /* restore readonly bit */ 642f18faf3fSek } 643f18faf3fSek 644f18faf3fSek return (0); 645f18faf3fSek } 646f18faf3fSek 64747f263f4Sek static void 64847f263f4Sek zfs_freezfsvfs(zfsvfs_t *zfsvfs) 64947f263f4Sek { 65047f263f4Sek mutex_destroy(&zfsvfs->z_znodes_lock); 65147f263f4Sek mutex_destroy(&zfsvfs->z_online_recv_lock); 6529e1320c0SMark Shellenbaum mutex_destroy(&zfsvfs->z_lock); 65347f263f4Sek list_destroy(&zfsvfs->z_all_znodes); 65447f263f4Sek rrw_destroy(&zfsvfs->z_teardown_lock); 65547f263f4Sek rw_destroy(&zfsvfs->z_teardown_inactive_lock); 65647f263f4Sek rw_destroy(&zfsvfs->z_fuid_lock); 65747f263f4Sek kmem_free(zfsvfs, sizeof (zfsvfs_t)); 65847f263f4Sek } 65947f263f4Sek 660ea8dc4b6Seschrock static int 661088f3894Sahrens zfs_domount(vfs_t *vfsp, char *osname) 662ea8dc4b6Seschrock { 663ea8dc4b6Seschrock dev_t mount_dev; 664ea8dc4b6Seschrock uint64_t recordsize, readonly; 665ea8dc4b6Seschrock int error = 0; 666ea8dc4b6Seschrock int mode; 667ea8dc4b6Seschrock zfsvfs_t *zfsvfs; 668ea8dc4b6Seschrock znode_t *zp = NULL; 669ea8dc4b6Seschrock 670ea8dc4b6Seschrock ASSERT(vfsp); 671ea8dc4b6Seschrock ASSERT(osname); 672fa9e4066Sahrens 673fa9e4066Sahrens /* 674fa9e4066Sahrens * Initialize the zfs-specific filesystem structure. 675fa9e4066Sahrens * Should probably make this a kmem cache, shuffle fields, 676ea8dc4b6Seschrock * and just bzero up to z_hold_mtx[]. 677fa9e4066Sahrens */ 678fa9e4066Sahrens zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); 679fa9e4066Sahrens zfsvfs->z_vfs = vfsp; 680fa9e4066Sahrens zfsvfs->z_parent = zfsvfs; 681fa9e4066Sahrens zfsvfs->z_max_blksz = SPA_MAXBLOCKSIZE; 682a0965f35Sbonwick zfsvfs->z_show_ctldir = ZFS_SNAPDIR_VISIBLE; 68389459e17SMark Shellenbaum zfsvfs->z_fuid_dirty = B_FALSE; 684fa9e4066Sahrens 685fa9e4066Sahrens mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); 68647f263f4Sek mutex_init(&zfsvfs->z_online_recv_lock, NULL, MUTEX_DEFAULT, NULL); 6879e1320c0SMark Shellenbaum mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL); 688fa9e4066Sahrens list_create(&zfsvfs->z_all_znodes, sizeof (znode_t), 689fa9e4066Sahrens offsetof(znode_t, z_link_node)); 690f18faf3fSek rrw_init(&zfsvfs->z_teardown_lock); 691f18faf3fSek rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL); 692de8267e0Stimh rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL); 693fa9e4066Sahrens 694ea8dc4b6Seschrock /* Initialize the generic filesystem structure. */ 695fa9e4066Sahrens vfsp->vfs_bcount = 0; 696fa9e4066Sahrens vfsp->vfs_data = NULL; 697fa9e4066Sahrens 698ea8dc4b6Seschrock if (zfs_create_unique_device(&mount_dev) == -1) { 699ea8dc4b6Seschrock error = ENODEV; 700ea8dc4b6Seschrock goto out; 701ea8dc4b6Seschrock } 702fa9e4066Sahrens ASSERT(vfs_devismounted(mount_dev) == 0); 703fa9e4066Sahrens 704ea8dc4b6Seschrock if (error = dsl_prop_get_integer(osname, "recordsize", &recordsize, 705ea8dc4b6Seschrock NULL)) 706ea8dc4b6Seschrock goto out; 707fa9e4066Sahrens 708fa9e4066Sahrens vfsp->vfs_dev = mount_dev; 709fa9e4066Sahrens vfsp->vfs_fstype = zfsfstype; 710fa9e4066Sahrens vfsp->vfs_bsize = recordsize; 711fa9e4066Sahrens vfsp->vfs_flag |= VFS_NOTRUNC; 712fa9e4066Sahrens vfsp->vfs_data = zfsvfs; 713fa9e4066Sahrens 714ea8dc4b6Seschrock if (error = dsl_prop_get_integer(osname, "readonly", &readonly, NULL)) 715fa9e4066Sahrens goto out; 716fa9e4066Sahrens 717745cd3c5Smaybee mode = DS_MODE_OWNER; 718fa9e4066Sahrens if (readonly) 719745cd3c5Smaybee mode |= DS_MODE_READONLY; 720fa9e4066Sahrens 721fa9e4066Sahrens error = dmu_objset_open(osname, DMU_OST_ZFS, mode, &zfsvfs->z_os); 722fa9e4066Sahrens if (error == EROFS) { 723745cd3c5Smaybee mode = DS_MODE_OWNER | DS_MODE_READONLY; 724fa9e4066Sahrens error = dmu_objset_open(osname, DMU_OST_ZFS, mode, 725fa9e4066Sahrens &zfsvfs->z_os); 726fa9e4066Sahrens } 727fa9e4066Sahrens 728fa9e4066Sahrens if (error) 729fa9e4066Sahrens goto out; 730fa9e4066Sahrens 731088f3894Sahrens if (error = zfs_init_fs(zfsvfs, &zp)) 732fa9e4066Sahrens goto out; 733fa9e4066Sahrens 734ea8dc4b6Seschrock /* The call to zfs_init_fs leaves the vnode held, release it here. */ 735ea8dc4b6Seschrock VN_RELE(ZTOV(zp)); 736ea8dc4b6Seschrock 737da6c28aaSamw /* 738da6c28aaSamw * Set features for file system. 739da6c28aaSamw */ 740da6c28aaSamw zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os); 741da6c28aaSamw if (zfsvfs->z_use_fuids) { 742da6c28aaSamw vfs_set_feature(vfsp, VFSFT_XVATTR); 7439660e5cbSJanice Chang vfs_set_feature(vfsp, VFSFT_SYSATTR_VIEWS); 744da6c28aaSamw vfs_set_feature(vfsp, VFSFT_ACEMASKONACCESS); 745da6c28aaSamw vfs_set_feature(vfsp, VFSFT_ACLONCREATE); 746da6c28aaSamw } 747de8267e0Stimh if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) { 748de8267e0Stimh vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS); 749de8267e0Stimh vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE); 750de8267e0Stimh vfs_set_feature(vfsp, VFSFT_NOCASESENSITIVE); 751de8267e0Stimh } else if (zfsvfs->z_case == ZFS_CASE_MIXED) { 752de8267e0Stimh vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS); 753de8267e0Stimh vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE); 754de8267e0Stimh } 755da6c28aaSamw 756ea8dc4b6Seschrock if (dmu_objset_is_snapshot(zfsvfs->z_os)) { 757da6c28aaSamw uint64_t pval; 7587b55fa8eSck 759fa9e4066Sahrens ASSERT(mode & DS_MODE_READONLY); 760fa9e4066Sahrens atime_changed_cb(zfsvfs, B_FALSE); 761fa9e4066Sahrens readonly_changed_cb(zfsvfs, B_TRUE); 762da6c28aaSamw if (error = dsl_prop_get_integer(osname, "xattr", &pval, NULL)) 7637b55fa8eSck goto out; 764da6c28aaSamw xattr_changed_cb(zfsvfs, pval); 765fa9e4066Sahrens zfsvfs->z_issnap = B_TRUE; 766fa9e4066Sahrens } else { 767f18faf3fSek error = zfsvfs_setup(zfsvfs, B_TRUE); 768ea8dc4b6Seschrock } 769fa9e4066Sahrens 770ea8dc4b6Seschrock if (!zfsvfs->z_issnap) 771ea8dc4b6Seschrock zfsctl_create(zfsvfs); 772ea8dc4b6Seschrock out: 773ea8dc4b6Seschrock if (error) { 774ea8dc4b6Seschrock if (zfsvfs->z_os) 775ea8dc4b6Seschrock dmu_objset_close(zfsvfs->z_os); 77647f263f4Sek zfs_freezfsvfs(zfsvfs); 777ea8dc4b6Seschrock } else { 778ea8dc4b6Seschrock atomic_add_32(&zfs_active_fs_count, 1); 779ea8dc4b6Seschrock } 780fa9e4066Sahrens 781ea8dc4b6Seschrock return (error); 782ea8dc4b6Seschrock } 783ea8dc4b6Seschrock 784ea8dc4b6Seschrock void 785ea8dc4b6Seschrock zfs_unregister_callbacks(zfsvfs_t *zfsvfs) 786ea8dc4b6Seschrock { 787ea8dc4b6Seschrock objset_t *os = zfsvfs->z_os; 788ea8dc4b6Seschrock struct dsl_dataset *ds; 789ea8dc4b6Seschrock 790ea8dc4b6Seschrock /* 791ea8dc4b6Seschrock * Unregister properties. 792ea8dc4b6Seschrock */ 793ea8dc4b6Seschrock if (!dmu_objset_is_snapshot(os)) { 794fa9e4066Sahrens ds = dmu_objset_ds(os); 795ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "atime", atime_changed_cb, 796fa9e4066Sahrens zfsvfs) == 0); 797fa9e4066Sahrens 7987b55fa8eSck VERIFY(dsl_prop_unregister(ds, "xattr", xattr_changed_cb, 7997b55fa8eSck zfsvfs) == 0); 8007b55fa8eSck 801ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, 802fa9e4066Sahrens zfsvfs) == 0); 803fa9e4066Sahrens 804ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "readonly", readonly_changed_cb, 805fa9e4066Sahrens zfsvfs) == 0); 806fa9e4066Sahrens 807ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "devices", devices_changed_cb, 808fa9e4066Sahrens zfsvfs) == 0); 809fa9e4066Sahrens 810ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "setuid", setuid_changed_cb, 811fa9e4066Sahrens zfsvfs) == 0); 812fa9e4066Sahrens 813ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "exec", exec_changed_cb, 814fa9e4066Sahrens zfsvfs) == 0); 815fa9e4066Sahrens 816ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, 817fa9e4066Sahrens zfsvfs) == 0); 818fa9e4066Sahrens 819ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, 820fa9e4066Sahrens zfsvfs) == 0); 821fa9e4066Sahrens 822ea8dc4b6Seschrock VERIFY(dsl_prop_unregister(ds, "aclinherit", 823fa9e4066Sahrens acl_inherit_changed_cb, zfsvfs) == 0); 824da6c28aaSamw 825da6c28aaSamw VERIFY(dsl_prop_unregister(ds, "vscan", 826da6c28aaSamw vscan_changed_cb, zfsvfs) == 0); 827ea8dc4b6Seschrock } 828ea8dc4b6Seschrock } 829fa9e4066Sahrens 830b1b8ab34Slling /* 831b1b8ab34Slling * Convert a decimal digit string to a uint64_t integer. 832b1b8ab34Slling */ 833b1b8ab34Slling static int 834b1b8ab34Slling str_to_uint64(char *str, uint64_t *objnum) 835b1b8ab34Slling { 836b1b8ab34Slling uint64_t num = 0; 837b1b8ab34Slling 838b1b8ab34Slling while (*str) { 839b1b8ab34Slling if (*str < '0' || *str > '9') 840b1b8ab34Slling return (EINVAL); 841b1b8ab34Slling 842b1b8ab34Slling num = num*10 + *str++ - '0'; 843b1b8ab34Slling } 844b1b8ab34Slling 845b1b8ab34Slling *objnum = num; 846b1b8ab34Slling return (0); 847b1b8ab34Slling } 848b1b8ab34Slling 849b1b8ab34Slling /* 850b1b8ab34Slling * The boot path passed from the boot loader is in the form of 851b1b8ab34Slling * "rootpool-name/root-filesystem-object-number'. Convert this 852b1b8ab34Slling * string to a dataset name: "rootpool-name/root-filesystem-name". 853b1b8ab34Slling */ 854b1b8ab34Slling static int 855e7cbe64fSgw zfs_parse_bootfs(char *bpath, char *outpath) 856b1b8ab34Slling { 857b1b8ab34Slling char *slashp; 858b1b8ab34Slling uint64_t objnum; 859b1b8ab34Slling int error; 860b1b8ab34Slling 861b1b8ab34Slling if (*bpath == 0 || *bpath == '/') 862b1b8ab34Slling return (EINVAL); 863b1b8ab34Slling 86419397407SSherry Moore (void) strcpy(outpath, bpath); 86519397407SSherry Moore 866b1b8ab34Slling slashp = strchr(bpath, '/'); 867b1b8ab34Slling 868b1b8ab34Slling /* if no '/', just return the pool name */ 869b1b8ab34Slling if (slashp == NULL) { 870b1b8ab34Slling return (0); 871b1b8ab34Slling } 872b1b8ab34Slling 87319397407SSherry Moore /* if not a number, just return the root dataset name */ 87419397407SSherry Moore if (str_to_uint64(slashp+1, &objnum)) { 87519397407SSherry Moore return (0); 87619397407SSherry Moore } 877b1b8ab34Slling 878b1b8ab34Slling *slashp = '\0'; 879b1b8ab34Slling error = dsl_dsobj_to_dsname(bpath, objnum, outpath); 880b1b8ab34Slling *slashp = '/'; 881b1b8ab34Slling 882b1b8ab34Slling return (error); 883b1b8ab34Slling } 884b1b8ab34Slling 885ea8dc4b6Seschrock static int 886ea8dc4b6Seschrock zfs_mountroot(vfs_t *vfsp, enum whymountroot why) 887ea8dc4b6Seschrock { 888ea8dc4b6Seschrock int error = 0; 889ea8dc4b6Seschrock static int zfsrootdone = 0; 890ea8dc4b6Seschrock zfsvfs_t *zfsvfs = NULL; 891ea8dc4b6Seschrock znode_t *zp = NULL; 892ea8dc4b6Seschrock vnode_t *vp = NULL; 893e7cbe64fSgw char *zfs_bootfs; 894051aabe6Staylor char *zfs_devid; 895ea8dc4b6Seschrock 896ea8dc4b6Seschrock ASSERT(vfsp); 897ea8dc4b6Seschrock 898ea8dc4b6Seschrock /* 899b1b8ab34Slling * The filesystem that we mount as root is defined in the 900e7cbe64fSgw * boot property "zfs-bootfs" with a format of 901e7cbe64fSgw * "poolname/root-dataset-objnum". 902ea8dc4b6Seschrock */ 903ea8dc4b6Seschrock if (why == ROOT_INIT) { 904ea8dc4b6Seschrock if (zfsrootdone++) 905ea8dc4b6Seschrock return (EBUSY); 906e7cbe64fSgw /* 907e7cbe64fSgw * the process of doing a spa_load will require the 908e7cbe64fSgw * clock to be set before we could (for example) do 909e7cbe64fSgw * something better by looking at the timestamp on 910e7cbe64fSgw * an uberblock, so just set it to -1. 911e7cbe64fSgw */ 912e7cbe64fSgw clkset(-1); 913fa9e4066Sahrens 914051aabe6Staylor if ((zfs_bootfs = spa_get_bootprop("zfs-bootfs")) == NULL) { 915051aabe6Staylor cmn_err(CE_NOTE, "spa_get_bootfs: can not get " 916051aabe6Staylor "bootfs name"); 917e7cbe64fSgw return (EINVAL); 918986fd29aSsetje } 919051aabe6Staylor zfs_devid = spa_get_bootprop("diskdevid"); 920051aabe6Staylor error = spa_import_rootpool(rootfs.bo_name, zfs_devid); 921051aabe6Staylor if (zfs_devid) 922051aabe6Staylor spa_free_bootprop(zfs_devid); 923051aabe6Staylor if (error) { 924051aabe6Staylor spa_free_bootprop(zfs_bootfs); 925051aabe6Staylor cmn_err(CE_NOTE, "spa_import_rootpool: error %d", 926e7cbe64fSgw error); 927e7cbe64fSgw return (error); 928e7cbe64fSgw } 929e7cbe64fSgw if (error = zfs_parse_bootfs(zfs_bootfs, rootfs.bo_name)) { 930051aabe6Staylor spa_free_bootprop(zfs_bootfs); 931051aabe6Staylor cmn_err(CE_NOTE, "zfs_parse_bootfs: error %d", 932e7cbe64fSgw error); 933b1b8ab34Slling return (error); 934e7cbe64fSgw } 935e7cbe64fSgw 936051aabe6Staylor spa_free_bootprop(zfs_bootfs); 937fa9e4066Sahrens 938ea8dc4b6Seschrock if (error = vfs_lock(vfsp)) 939ea8dc4b6Seschrock return (error); 940fa9e4066Sahrens 941088f3894Sahrens if (error = zfs_domount(vfsp, rootfs.bo_name)) { 942051aabe6Staylor cmn_err(CE_NOTE, "zfs_domount: error %d", error); 943ea8dc4b6Seschrock goto out; 944e7cbe64fSgw } 945ea8dc4b6Seschrock 946ea8dc4b6Seschrock zfsvfs = (zfsvfs_t *)vfsp->vfs_data; 947ea8dc4b6Seschrock ASSERT(zfsvfs); 948e7cbe64fSgw if (error = zfs_zget(zfsvfs, zfsvfs->z_root, &zp)) { 949051aabe6Staylor cmn_err(CE_NOTE, "zfs_zget: error %d", error); 950ea8dc4b6Seschrock goto out; 951e7cbe64fSgw } 952ea8dc4b6Seschrock 953ea8dc4b6Seschrock vp = ZTOV(zp); 954ea8dc4b6Seschrock mutex_enter(&vp->v_lock); 955ea8dc4b6Seschrock vp->v_flag |= VROOT; 956ea8dc4b6Seschrock mutex_exit(&vp->v_lock); 957ea8dc4b6Seschrock rootvp = vp; 958ea8dc4b6Seschrock 959ea8dc4b6Seschrock /* 96040d3dfe1Smarks * Leave rootvp held. The root file system is never unmounted. 961ea8dc4b6Seschrock */ 962ea8dc4b6Seschrock 963ea8dc4b6Seschrock vfs_add((struct vnode *)0, vfsp, 964ea8dc4b6Seschrock (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0); 965ea8dc4b6Seschrock out: 966ea8dc4b6Seschrock vfs_unlock(vfsp); 967e7cbe64fSgw return (error); 968ea8dc4b6Seschrock } else if (why == ROOT_REMOUNT) { 969ea8dc4b6Seschrock readonly_changed_cb(vfsp->vfs_data, B_FALSE); 970ea8dc4b6Seschrock vfsp->vfs_flag |= VFS_REMOUNT; 971b510d378Slling 972b510d378Slling /* refresh mount options */ 973b510d378Slling zfs_unregister_callbacks(vfsp->vfs_data); 974b510d378Slling return (zfs_register_callbacks(vfsp)); 975b510d378Slling 976ea8dc4b6Seschrock } else if (why == ROOT_UNMOUNT) { 977ea8dc4b6Seschrock zfs_unregister_callbacks((zfsvfs_t *)vfsp->vfs_data); 978ea8dc4b6Seschrock (void) zfs_sync(vfsp, 0, 0); 979ea8dc4b6Seschrock return (0); 980ea8dc4b6Seschrock } 981ea8dc4b6Seschrock 982ea8dc4b6Seschrock /* 983ea8dc4b6Seschrock * if "why" is equal to anything else other than ROOT_INIT, 984ea8dc4b6Seschrock * ROOT_REMOUNT, or ROOT_UNMOUNT, we do not support it. 985ea8dc4b6Seschrock */ 986ea8dc4b6Seschrock return (ENOTSUP); 987ea8dc4b6Seschrock } 988ea8dc4b6Seschrock 989ea8dc4b6Seschrock /*ARGSUSED*/ 990ea8dc4b6Seschrock static int 991ea8dc4b6Seschrock zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) 992ea8dc4b6Seschrock { 993ea8dc4b6Seschrock char *osname; 994ea8dc4b6Seschrock pathname_t spn; 995ea8dc4b6Seschrock int error = 0; 996ea8dc4b6Seschrock uio_seg_t fromspace = (uap->flags & MS_SYSSPACE) ? 997b1b8ab34Slling UIO_SYSSPACE : UIO_USERSPACE; 998ea8dc4b6Seschrock int canwrite; 999ea8dc4b6Seschrock 1000ea8dc4b6Seschrock if (mvp->v_type != VDIR) 1001ea8dc4b6Seschrock return (ENOTDIR); 1002ea8dc4b6Seschrock 1003ea8dc4b6Seschrock mutex_enter(&mvp->v_lock); 1004ea8dc4b6Seschrock if ((uap->flags & MS_REMOUNT) == 0 && 1005ea8dc4b6Seschrock (uap->flags & MS_OVERLAY) == 0 && 1006ea8dc4b6Seschrock (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { 1007ea8dc4b6Seschrock mutex_exit(&mvp->v_lock); 1008ea8dc4b6Seschrock return (EBUSY); 1009ea8dc4b6Seschrock } 1010ea8dc4b6Seschrock mutex_exit(&mvp->v_lock); 1011ea8dc4b6Seschrock 1012ea8dc4b6Seschrock /* 1013ea8dc4b6Seschrock * ZFS does not support passing unparsed data in via MS_DATA. 1014ea8dc4b6Seschrock * Users should use the MS_OPTIONSTR interface; this means 1015ea8dc4b6Seschrock * that all option parsing is already done and the options struct 1016ea8dc4b6Seschrock * can be interrogated. 1017ea8dc4b6Seschrock */ 1018ea8dc4b6Seschrock if ((uap->flags & MS_DATA) && uap->datalen > 0) 1019ea8dc4b6Seschrock return (EINVAL); 1020ea8dc4b6Seschrock 1021ea8dc4b6Seschrock /* 1022ea8dc4b6Seschrock * Get the objset name (the "special" mount argument). 1023ea8dc4b6Seschrock */ 1024ea8dc4b6Seschrock if (error = pn_get(uap->spec, fromspace, &spn)) 1025ea8dc4b6Seschrock return (error); 1026ea8dc4b6Seschrock 1027ea8dc4b6Seschrock osname = spn.pn_path; 1028ea8dc4b6Seschrock 1029ecd6cf80Smarks /* 1030ecd6cf80Smarks * Check for mount privilege? 1031ecd6cf80Smarks * 1032ecd6cf80Smarks * If we don't have privilege then see if 1033ecd6cf80Smarks * we have local permission to allow it 1034ecd6cf80Smarks */ 1035ecd6cf80Smarks error = secpolicy_fs_mount(cr, mvp, vfsp); 1036ecd6cf80Smarks if (error) { 1037ecd6cf80Smarks error = dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr); 1038ecd6cf80Smarks if (error == 0) { 1039ecd6cf80Smarks vattr_t vattr; 1040ecd6cf80Smarks 1041ecd6cf80Smarks /* 1042ecd6cf80Smarks * Make sure user is the owner of the mount point 1043ecd6cf80Smarks * or has sufficient privileges. 1044ecd6cf80Smarks */ 1045ecd6cf80Smarks 1046ecd6cf80Smarks vattr.va_mask = AT_UID; 1047ecd6cf80Smarks 1048da6c28aaSamw if (error = VOP_GETATTR(mvp, &vattr, 0, cr, NULL)) { 1049ecd6cf80Smarks goto out; 1050ecd6cf80Smarks } 1051ecd6cf80Smarks 10522459a9eaSmarks if (secpolicy_vnode_owner(cr, vattr.va_uid) != 0 && 10532459a9eaSmarks VOP_ACCESS(mvp, VWRITE, 0, cr, NULL) != 0) { 10542459a9eaSmarks error = EPERM; 1055ecd6cf80Smarks goto out; 1056ecd6cf80Smarks } 1057ecd6cf80Smarks 1058ecd6cf80Smarks secpolicy_fs_mount_clearopts(cr, vfsp); 1059ecd6cf80Smarks } else { 1060ecd6cf80Smarks goto out; 1061ecd6cf80Smarks } 1062ecd6cf80Smarks } 1063ea8dc4b6Seschrock 1064ea8dc4b6Seschrock /* 1065ea8dc4b6Seschrock * Refuse to mount a filesystem if we are in a local zone and the 1066ea8dc4b6Seschrock * dataset is not visible. 1067ea8dc4b6Seschrock */ 1068ea8dc4b6Seschrock if (!INGLOBALZONE(curproc) && 1069ea8dc4b6Seschrock (!zone_dataset_visible(osname, &canwrite) || !canwrite)) { 1070ea8dc4b6Seschrock error = EPERM; 1071ea8dc4b6Seschrock goto out; 1072ea8dc4b6Seschrock } 1073ea8dc4b6Seschrock 1074b510d378Slling /* 1075b510d378Slling * When doing a remount, we simply refresh our temporary properties 1076b510d378Slling * according to those options set in the current VFS options. 1077b510d378Slling */ 1078b510d378Slling if (uap->flags & MS_REMOUNT) { 1079b510d378Slling /* refresh mount options */ 1080b510d378Slling zfs_unregister_callbacks(vfsp->vfs_data); 1081b510d378Slling error = zfs_register_callbacks(vfsp); 1082b510d378Slling goto out; 1083b510d378Slling } 1084b510d378Slling 1085088f3894Sahrens error = zfs_domount(vfsp, osname); 1086ea8dc4b6Seschrock 1087142ae85dSChris Kirby /* 1088142ae85dSChris Kirby * Add an extra VFS_HOLD on our parent vfs so that it can't 1089142ae85dSChris Kirby * disappear due to a forced unmount. 1090142ae85dSChris Kirby */ 1091142ae85dSChris Kirby if (((zfsvfs_t *)vfsp->vfs_data)->z_issnap) 1092142ae85dSChris Kirby VFS_HOLD(mvp->v_vfsp); 1093142ae85dSChris Kirby 1094ea8dc4b6Seschrock out: 1095fa9e4066Sahrens pn_free(&spn); 1096fa9e4066Sahrens return (error); 1097fa9e4066Sahrens } 1098fa9e4066Sahrens 1099fa9e4066Sahrens static int 1100fa9e4066Sahrens zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp) 1101fa9e4066Sahrens { 1102fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1103fa9e4066Sahrens dev32_t d32; 1104a2eea2e1Sahrens uint64_t refdbytes, availbytes, usedobjs, availobjs; 1105fa9e4066Sahrens 1106fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1107fa9e4066Sahrens 1108a2eea2e1Sahrens dmu_objset_space(zfsvfs->z_os, 1109a2eea2e1Sahrens &refdbytes, &availbytes, &usedobjs, &availobjs); 1110fa9e4066Sahrens 1111fa9e4066Sahrens /* 1112fa9e4066Sahrens * The underlying storage pool actually uses multiple block sizes. 1113fa9e4066Sahrens * We report the fragsize as the smallest block size we support, 1114fa9e4066Sahrens * and we report our blocksize as the filesystem's maximum blocksize. 1115fa9e4066Sahrens */ 1116fa9e4066Sahrens statp->f_frsize = 1UL << SPA_MINBLOCKSHIFT; 1117fa9e4066Sahrens statp->f_bsize = zfsvfs->z_max_blksz; 1118fa9e4066Sahrens 1119fa9e4066Sahrens /* 1120fa9e4066Sahrens * The following report "total" blocks of various kinds in the 1121fa9e4066Sahrens * file system, but reported in terms of f_frsize - the 1122fa9e4066Sahrens * "fragment" size. 1123fa9e4066Sahrens */ 1124fa9e4066Sahrens 1125a2eea2e1Sahrens statp->f_blocks = (refdbytes + availbytes) >> SPA_MINBLOCKSHIFT; 1126a2eea2e1Sahrens statp->f_bfree = availbytes >> SPA_MINBLOCKSHIFT; 1127fa9e4066Sahrens statp->f_bavail = statp->f_bfree; /* no root reservation */ 1128fa9e4066Sahrens 1129fa9e4066Sahrens /* 1130fa9e4066Sahrens * statvfs() should really be called statufs(), because it assumes 1131fa9e4066Sahrens * static metadata. ZFS doesn't preallocate files, so the best 1132fa9e4066Sahrens * we can do is report the max that could possibly fit in f_files, 1133fa9e4066Sahrens * and that minus the number actually used in f_ffree. 1134fa9e4066Sahrens * For f_ffree, report the smaller of the number of object available 1135fa9e4066Sahrens * and the number of blocks (each object will take at least a block). 1136fa9e4066Sahrens */ 1137a2eea2e1Sahrens statp->f_ffree = MIN(availobjs, statp->f_bfree); 1138fa9e4066Sahrens statp->f_favail = statp->f_ffree; /* no "root reservation" */ 1139a2eea2e1Sahrens statp->f_files = statp->f_ffree + usedobjs; 1140fa9e4066Sahrens 1141fa9e4066Sahrens (void) cmpldev(&d32, vfsp->vfs_dev); 1142fa9e4066Sahrens statp->f_fsid = d32; 1143fa9e4066Sahrens 1144fa9e4066Sahrens /* 1145fa9e4066Sahrens * We're a zfs filesystem. 1146fa9e4066Sahrens */ 1147fa9e4066Sahrens (void) strcpy(statp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 1148fa9e4066Sahrens 1149a5be7ebbSmarks statp->f_flag = vf_to_stf(vfsp->vfs_flag); 1150fa9e4066Sahrens 1151fa9e4066Sahrens statp->f_namemax = ZFS_MAXNAMELEN; 1152fa9e4066Sahrens 1153fa9e4066Sahrens /* 1154fa9e4066Sahrens * We have all of 32 characters to stuff a string here. 1155fa9e4066Sahrens * Is there anything useful we could/should provide? 1156fa9e4066Sahrens */ 1157fa9e4066Sahrens bzero(statp->f_fstr, sizeof (statp->f_fstr)); 1158fa9e4066Sahrens 1159fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1160fa9e4066Sahrens return (0); 1161fa9e4066Sahrens } 1162fa9e4066Sahrens 1163fa9e4066Sahrens static int 1164fa9e4066Sahrens zfs_root(vfs_t *vfsp, vnode_t **vpp) 1165fa9e4066Sahrens { 1166fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1167fa9e4066Sahrens znode_t *rootzp; 1168fa9e4066Sahrens int error; 1169fa9e4066Sahrens 1170fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1171fa9e4066Sahrens 1172fa9e4066Sahrens error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); 1173fa9e4066Sahrens if (error == 0) 1174fa9e4066Sahrens *vpp = ZTOV(rootzp); 1175fa9e4066Sahrens 1176fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1177fa9e4066Sahrens return (error); 1178fa9e4066Sahrens } 1179fa9e4066Sahrens 1180f18faf3fSek /* 1181f18faf3fSek * Teardown the zfsvfs::z_os. 1182f18faf3fSek * 1183f18faf3fSek * Note, if 'unmounting' if FALSE, we return with the 'z_teardown_lock' 1184f18faf3fSek * and 'z_teardown_inactive_lock' held. 1185f18faf3fSek */ 1186f18faf3fSek static int 1187f18faf3fSek zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting) 1188f18faf3fSek { 1189874395d5Smaybee znode_t *zp; 1190f18faf3fSek 1191f18faf3fSek rrw_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); 1192f18faf3fSek 1193f18faf3fSek if (!unmounting) { 1194f18faf3fSek /* 1195f18faf3fSek * We purge the parent filesystem's vfsp as the parent 1196f18faf3fSek * filesystem and all of its snapshots have their vnode's 1197f18faf3fSek * v_vfsp set to the parent's filesystem's vfsp. Note, 1198f18faf3fSek * 'z_parent' is self referential for non-snapshots. 1199f18faf3fSek */ 1200f18faf3fSek (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0); 1201f18faf3fSek } 1202f18faf3fSek 1203f18faf3fSek /* 1204f18faf3fSek * Close the zil. NB: Can't close the zil while zfs_inactive 1205f18faf3fSek * threads are blocked as zil_close can call zfs_inactive. 1206f18faf3fSek */ 1207f18faf3fSek if (zfsvfs->z_log) { 1208f18faf3fSek zil_close(zfsvfs->z_log); 1209f18faf3fSek zfsvfs->z_log = NULL; 1210f18faf3fSek } 1211f18faf3fSek 1212f18faf3fSek rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_WRITER); 1213f18faf3fSek 1214f18faf3fSek /* 1215f18faf3fSek * If we are not unmounting (ie: online recv) and someone already 1216f18faf3fSek * unmounted this file system while we were doing the switcheroo, 1217f18faf3fSek * or a reopen of z_os failed then just bail out now. 1218f18faf3fSek */ 1219f18faf3fSek if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) { 1220f18faf3fSek rw_exit(&zfsvfs->z_teardown_inactive_lock); 1221f18faf3fSek rrw_exit(&zfsvfs->z_teardown_lock, FTAG); 1222f18faf3fSek return (EIO); 1223f18faf3fSek } 1224f18faf3fSek 1225f18faf3fSek /* 1226f18faf3fSek * At this point there are no vops active, and any new vops will 1227f18faf3fSek * fail with EIO since we have z_teardown_lock for writer (only 1228f18faf3fSek * relavent for forced unmount). 1229f18faf3fSek * 1230f18faf3fSek * Release all holds on dbufs. 1231f18faf3fSek */ 1232f18faf3fSek mutex_enter(&zfsvfs->z_znodes_lock); 1233874395d5Smaybee for (zp = list_head(&zfsvfs->z_all_znodes); zp != NULL; 1234874395d5Smaybee zp = list_next(&zfsvfs->z_all_znodes, zp)) 12354ccbb6e7Sahrens if (zp->z_dbuf) { 1236874395d5Smaybee ASSERT(ZTOV(zp)->v_count > 0); 1237874395d5Smaybee zfs_znode_dmu_fini(zp); 1238f18faf3fSek } 1239f18faf3fSek mutex_exit(&zfsvfs->z_znodes_lock); 1240f18faf3fSek 1241f18faf3fSek /* 1242f18faf3fSek * If we are unmounting, set the unmounted flag and let new vops 1243f18faf3fSek * unblock. zfs_inactive will have the unmounted behavior, and all 1244f18faf3fSek * other vops will fail with EIO. 1245f18faf3fSek */ 1246f18faf3fSek if (unmounting) { 1247f18faf3fSek zfsvfs->z_unmounted = B_TRUE; 1248f18faf3fSek rrw_exit(&zfsvfs->z_teardown_lock, FTAG); 1249f18faf3fSek rw_exit(&zfsvfs->z_teardown_inactive_lock); 1250f18faf3fSek } 1251f18faf3fSek 1252f18faf3fSek /* 1253f18faf3fSek * z_os will be NULL if there was an error in attempting to reopen 1254f18faf3fSek * zfsvfs, so just return as the properties had already been 1255f18faf3fSek * unregistered and cached data had been evicted before. 1256f18faf3fSek */ 1257f18faf3fSek if (zfsvfs->z_os == NULL) 1258f18faf3fSek return (0); 1259f18faf3fSek 1260f18faf3fSek /* 1261f18faf3fSek * Unregister properties. 1262f18faf3fSek */ 1263f18faf3fSek zfs_unregister_callbacks(zfsvfs); 1264f18faf3fSek 1265f18faf3fSek /* 1266f18faf3fSek * Evict cached data 1267f18faf3fSek */ 126847f263f4Sek if (dmu_objset_evict_dbufs(zfsvfs->z_os)) { 1269d3248e8bSmaybee txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0); 127047f263f4Sek (void) dmu_objset_evict_dbufs(zfsvfs->z_os); 1271d3248e8bSmaybee } 1272f18faf3fSek 1273f18faf3fSek return (0); 1274f18faf3fSek } 1275f18faf3fSek 1276fa9e4066Sahrens /*ARGSUSED*/ 1277fa9e4066Sahrens static int 1278fa9e4066Sahrens zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr) 1279fa9e4066Sahrens { 1280fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1281f18faf3fSek objset_t *os; 1282fa9e4066Sahrens int ret; 1283fa9e4066Sahrens 1284ecd6cf80Smarks ret = secpolicy_fs_unmount(cr, vfsp); 1285ecd6cf80Smarks if (ret) { 1286ecd6cf80Smarks ret = dsl_deleg_access((char *)refstr_value(vfsp->vfs_resource), 1287ecd6cf80Smarks ZFS_DELEG_PERM_MOUNT, cr); 1288ecd6cf80Smarks if (ret) 1289ecd6cf80Smarks return (ret); 1290ecd6cf80Smarks } 1291033f9833Sek 1292ed097989Sek /* 1293ed097989Sek * We purge the parent filesystem's vfsp as the parent filesystem 1294ed097989Sek * and all of its snapshots have their vnode's v_vfsp set to the 1295ed097989Sek * parent's filesystem's vfsp. Note, 'z_parent' is self 1296ed097989Sek * referential for non-snapshots. 1297ed097989Sek */ 1298ed097989Sek (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0); 1299033f9833Sek 1300fa9e4066Sahrens /* 1301fa9e4066Sahrens * Unmount any snapshots mounted under .zfs before unmounting the 1302fa9e4066Sahrens * dataset itself. 1303fa9e4066Sahrens */ 1304fa9e4066Sahrens if (zfsvfs->z_ctldir != NULL && 1305ecd6cf80Smarks (ret = zfsctl_umount_snapshots(vfsp, fflag, cr)) != 0) { 1306fa9e4066Sahrens return (ret); 1307ecd6cf80Smarks } 1308fa9e4066Sahrens 130991ebeef5Sahrens if (!(fflag & MS_FORCE)) { 1310fa9e4066Sahrens /* 131191ebeef5Sahrens * Check the number of active vnodes in the file system. 131291ebeef5Sahrens * Our count is maintained in the vfs structure, but the 131391ebeef5Sahrens * number is off by 1 to indicate a hold on the vfs 131491ebeef5Sahrens * structure itself. 131591ebeef5Sahrens * 131691ebeef5Sahrens * The '.zfs' directory maintains a reference of its 131791ebeef5Sahrens * own, and any active references underneath are 131891ebeef5Sahrens * reflected in the vnode count. 1319fa9e4066Sahrens */ 132091ebeef5Sahrens if (zfsvfs->z_ctldir == NULL) { 132191ebeef5Sahrens if (vfsp->vfs_count > 1) 132291ebeef5Sahrens return (EBUSY); 132391ebeef5Sahrens } else { 132491ebeef5Sahrens if (vfsp->vfs_count > 2 || 1325f18faf3fSek zfsvfs->z_ctldir->v_count > 1) 132691ebeef5Sahrens return (EBUSY); 1327fa9e4066Sahrens } 132891ebeef5Sahrens } 1329fa9e4066Sahrens 133091ebeef5Sahrens vfsp->vfs_flag |= VFS_UNMOUNTED; 133191ebeef5Sahrens 1332f18faf3fSek VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0); 1333f18faf3fSek os = zfsvfs->z_os; 133491ebeef5Sahrens 133591ebeef5Sahrens /* 1336f18faf3fSek * z_os will be NULL if there was an error in 1337f18faf3fSek * attempting to reopen zfsvfs. 133891ebeef5Sahrens */ 1339f18faf3fSek if (os != NULL) { 1340f18faf3fSek /* 1341f18faf3fSek * Unset the objset user_ptr. 1342f18faf3fSek */ 1343f18faf3fSek mutex_enter(&os->os->os_user_ptr_lock); 1344f18faf3fSek dmu_objset_set_user(os, NULL); 1345f18faf3fSek mutex_exit(&os->os->os_user_ptr_lock); 134691ebeef5Sahrens 1347f18faf3fSek /* 1348745cd3c5Smaybee * Finally release the objset 1349f18faf3fSek */ 1350f18faf3fSek dmu_objset_close(os); 135191ebeef5Sahrens } 135291ebeef5Sahrens 135391ebeef5Sahrens /* 135491ebeef5Sahrens * We can now safely destroy the '.zfs' directory node. 135591ebeef5Sahrens */ 135691ebeef5Sahrens if (zfsvfs->z_ctldir != NULL) 135791ebeef5Sahrens zfsctl_destroy(zfsvfs); 1358fa9e4066Sahrens 1359fa9e4066Sahrens return (0); 1360fa9e4066Sahrens } 1361fa9e4066Sahrens 1362fa9e4066Sahrens static int 1363fa9e4066Sahrens zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp) 1364fa9e4066Sahrens { 1365fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1366fa9e4066Sahrens znode_t *zp; 1367fa9e4066Sahrens uint64_t object = 0; 1368fa9e4066Sahrens uint64_t fid_gen = 0; 1369fa9e4066Sahrens uint64_t gen_mask; 1370fa9e4066Sahrens uint64_t zp_gen; 1371fa9e4066Sahrens int i, err; 1372fa9e4066Sahrens 1373fa9e4066Sahrens *vpp = NULL; 1374fa9e4066Sahrens 1375fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1376fa9e4066Sahrens 1377fa9e4066Sahrens if (fidp->fid_len == LONG_FID_LEN) { 1378fa9e4066Sahrens zfid_long_t *zlfid = (zfid_long_t *)fidp; 1379fa9e4066Sahrens uint64_t objsetid = 0; 1380fa9e4066Sahrens uint64_t setgen = 0; 1381fa9e4066Sahrens 1382fa9e4066Sahrens for (i = 0; i < sizeof (zlfid->zf_setid); i++) 1383fa9e4066Sahrens objsetid |= ((uint64_t)zlfid->zf_setid[i]) << (8 * i); 1384fa9e4066Sahrens 1385fa9e4066Sahrens for (i = 0; i < sizeof (zlfid->zf_setgen); i++) 1386fa9e4066Sahrens setgen |= ((uint64_t)zlfid->zf_setgen[i]) << (8 * i); 1387fa9e4066Sahrens 1388fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1389fa9e4066Sahrens 1390fa9e4066Sahrens err = zfsctl_lookup_objset(vfsp, objsetid, &zfsvfs); 1391fa9e4066Sahrens if (err) 1392fa9e4066Sahrens return (EINVAL); 1393fa9e4066Sahrens ZFS_ENTER(zfsvfs); 1394fa9e4066Sahrens } 1395fa9e4066Sahrens 1396fa9e4066Sahrens if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) { 1397fa9e4066Sahrens zfid_short_t *zfid = (zfid_short_t *)fidp; 1398fa9e4066Sahrens 1399fa9e4066Sahrens for (i = 0; i < sizeof (zfid->zf_object); i++) 1400fa9e4066Sahrens object |= ((uint64_t)zfid->zf_object[i]) << (8 * i); 1401fa9e4066Sahrens 1402fa9e4066Sahrens for (i = 0; i < sizeof (zfid->zf_gen); i++) 1403fa9e4066Sahrens fid_gen |= ((uint64_t)zfid->zf_gen[i]) << (8 * i); 1404fa9e4066Sahrens } else { 1405fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1406fa9e4066Sahrens return (EINVAL); 1407fa9e4066Sahrens } 1408fa9e4066Sahrens 1409fa9e4066Sahrens /* A zero fid_gen means we are in the .zfs control directories */ 1410fa9e4066Sahrens if (fid_gen == 0 && 1411fa9e4066Sahrens (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) { 1412fa9e4066Sahrens *vpp = zfsvfs->z_ctldir; 1413fa9e4066Sahrens ASSERT(*vpp != NULL); 1414fa9e4066Sahrens if (object == ZFSCTL_INO_SNAPDIR) { 1415fa9e4066Sahrens VERIFY(zfsctl_root_lookup(*vpp, "snapshot", vpp, NULL, 1416da6c28aaSamw 0, NULL, NULL, NULL, NULL, NULL) == 0); 1417fa9e4066Sahrens } else { 1418fa9e4066Sahrens VN_HOLD(*vpp); 1419fa9e4066Sahrens } 1420fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1421fa9e4066Sahrens return (0); 1422fa9e4066Sahrens } 1423fa9e4066Sahrens 1424fa9e4066Sahrens gen_mask = -1ULL >> (64 - 8 * i); 1425fa9e4066Sahrens 1426fa9e4066Sahrens dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask); 1427fa9e4066Sahrens if (err = zfs_zget(zfsvfs, object, &zp)) { 1428fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1429fa9e4066Sahrens return (err); 1430fa9e4066Sahrens } 1431fa9e4066Sahrens zp_gen = zp->z_phys->zp_gen & gen_mask; 1432fa9e4066Sahrens if (zp_gen == 0) 1433fa9e4066Sahrens zp_gen = 1; 1434893a6d32Sahrens if (zp->z_unlinked || zp_gen != fid_gen) { 1435fa9e4066Sahrens dprintf("znode gen (%u) != fid gen (%u)\n", zp_gen, fid_gen); 1436fa9e4066Sahrens VN_RELE(ZTOV(zp)); 1437fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1438fa9e4066Sahrens return (EINVAL); 1439fa9e4066Sahrens } 1440fa9e4066Sahrens 1441fa9e4066Sahrens *vpp = ZTOV(zp); 1442fa9e4066Sahrens ZFS_EXIT(zfsvfs); 1443fa9e4066Sahrens return (0); 1444fa9e4066Sahrens } 1445fa9e4066Sahrens 1446f18faf3fSek /* 1447f18faf3fSek * Block out VOPs and close zfsvfs_t::z_os 1448f18faf3fSek * 1449f18faf3fSek * Note, if successful, then we return with the 'z_teardown_lock' and 1450f18faf3fSek * 'z_teardown_inactive_lock' write held. 1451f18faf3fSek */ 1452f18faf3fSek int 1453f18faf3fSek zfs_suspend_fs(zfsvfs_t *zfsvfs, char *name, int *mode) 1454f18faf3fSek { 1455f18faf3fSek int error; 1456f18faf3fSek 1457f18faf3fSek if ((error = zfsvfs_teardown(zfsvfs, B_FALSE)) != 0) 1458f18faf3fSek return (error); 1459f18faf3fSek 1460f18faf3fSek *mode = zfsvfs->z_os->os_mode; 1461f18faf3fSek dmu_objset_name(zfsvfs->z_os, name); 1462f18faf3fSek dmu_objset_close(zfsvfs->z_os); 1463f18faf3fSek 1464f18faf3fSek return (0); 1465f18faf3fSek } 1466f18faf3fSek 1467f18faf3fSek /* 1468f18faf3fSek * Reopen zfsvfs_t::z_os and release VOPs. 1469f18faf3fSek */ 1470f18faf3fSek int 1471f18faf3fSek zfs_resume_fs(zfsvfs_t *zfsvfs, const char *osname, int mode) 1472f18faf3fSek { 1473f18faf3fSek int err; 1474f18faf3fSek 1475f18faf3fSek ASSERT(RRW_WRITE_HELD(&zfsvfs->z_teardown_lock)); 1476f18faf3fSek ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock)); 1477f18faf3fSek 1478f18faf3fSek err = dmu_objset_open(osname, DMU_OST_ZFS, mode, &zfsvfs->z_os); 1479f18faf3fSek if (err) { 1480f18faf3fSek zfsvfs->z_os = NULL; 1481f18faf3fSek } else { 1482f18faf3fSek znode_t *zp; 1483f18faf3fSek 1484f18faf3fSek VERIFY(zfsvfs_setup(zfsvfs, B_FALSE) == 0); 1485f18faf3fSek 1486f18faf3fSek /* 1487f18faf3fSek * Attempt to re-establish all the active znodes with 1488f18faf3fSek * their dbufs. If a zfs_rezget() fails, then we'll let 1489f18faf3fSek * any potential callers discover that via ZFS_ENTER_VERIFY_VP 1490f18faf3fSek * when they try to use their znode. 1491f18faf3fSek */ 1492f18faf3fSek mutex_enter(&zfsvfs->z_znodes_lock); 1493f18faf3fSek for (zp = list_head(&zfsvfs->z_all_znodes); zp; 1494f18faf3fSek zp = list_next(&zfsvfs->z_all_znodes, zp)) { 1495f18faf3fSek (void) zfs_rezget(zp); 1496f18faf3fSek } 1497f18faf3fSek mutex_exit(&zfsvfs->z_znodes_lock); 1498f18faf3fSek 1499f18faf3fSek } 1500f18faf3fSek 1501f18faf3fSek /* release the VOPs */ 1502f18faf3fSek rw_exit(&zfsvfs->z_teardown_inactive_lock); 1503f18faf3fSek rrw_exit(&zfsvfs->z_teardown_lock, FTAG); 1504f18faf3fSek 1505f18faf3fSek if (err) { 1506f18faf3fSek /* 1507f18faf3fSek * Since we couldn't reopen zfsvfs::z_os, force 1508f18faf3fSek * unmount this file system. 1509f18faf3fSek */ 1510f18faf3fSek if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0) 1511f18faf3fSek (void) dounmount(zfsvfs->z_vfs, MS_FORCE, CRED()); 1512f18faf3fSek } 1513f18faf3fSek return (err); 1514f18faf3fSek } 1515f18faf3fSek 1516fa9e4066Sahrens static void 1517fa9e4066Sahrens zfs_freevfs(vfs_t *vfsp) 1518fa9e4066Sahrens { 1519fa9e4066Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1520c25056deSgw int i; 1521c25056deSgw 1522c25056deSgw for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) 1523c25056deSgw mutex_destroy(&zfsvfs->z_hold_mtx[i]); 1524fa9e4066Sahrens 1525da6c28aaSamw zfs_fuid_destroy(zfsvfs); 1526142ae85dSChris Kirby 1527142ae85dSChris Kirby /* 1528142ae85dSChris Kirby * If this is a snapshot, we have an extra VFS_HOLD on our parent 1529142ae85dSChris Kirby * from zfs_mount(). Release it here. 1530142ae85dSChris Kirby */ 1531142ae85dSChris Kirby if (zfsvfs->z_issnap) 1532142ae85dSChris Kirby VFS_RELE(zfsvfs->z_parent->z_vfs); 1533142ae85dSChris Kirby 153447f263f4Sek zfs_freezfsvfs(zfsvfs); 1535fa9e4066Sahrens 1536fa9e4066Sahrens atomic_add_32(&zfs_active_fs_count, -1); 1537fa9e4066Sahrens } 1538fa9e4066Sahrens 1539fa9e4066Sahrens /* 1540fa9e4066Sahrens * VFS_INIT() initialization. Note that there is no VFS_FINI(), 1541fa9e4066Sahrens * so we can't safely do any non-idempotent initialization here. 1542fa9e4066Sahrens * Leave that to zfs_init() and zfs_fini(), which are called 1543fa9e4066Sahrens * from the module's _init() and _fini() entry points. 1544fa9e4066Sahrens */ 1545fa9e4066Sahrens /*ARGSUSED*/ 1546fa9e4066Sahrens static int 1547fa9e4066Sahrens zfs_vfsinit(int fstype, char *name) 1548fa9e4066Sahrens { 1549fa9e4066Sahrens int error; 1550fa9e4066Sahrens 1551fa9e4066Sahrens zfsfstype = fstype; 1552fa9e4066Sahrens 1553fa9e4066Sahrens /* 1554fa9e4066Sahrens * Setup vfsops and vnodeops tables. 1555fa9e4066Sahrens */ 1556fa9e4066Sahrens error = vfs_setfsops(fstype, zfs_vfsops_template, &zfs_vfsops); 1557fa9e4066Sahrens if (error != 0) { 1558fa9e4066Sahrens cmn_err(CE_WARN, "zfs: bad vfs ops template"); 1559fa9e4066Sahrens } 1560fa9e4066Sahrens 1561fa9e4066Sahrens error = zfs_create_op_tables(); 1562fa9e4066Sahrens if (error) { 1563fa9e4066Sahrens zfs_remove_op_tables(); 1564fa9e4066Sahrens cmn_err(CE_WARN, "zfs: bad vnode ops template"); 1565fa9e4066Sahrens (void) vfs_freevfsops_by_type(zfsfstype); 1566fa9e4066Sahrens return (error); 1567fa9e4066Sahrens } 1568fa9e4066Sahrens 1569fa9e4066Sahrens mutex_init(&zfs_dev_mtx, NULL, MUTEX_DEFAULT, NULL); 1570fa9e4066Sahrens 1571fa9e4066Sahrens /* 1572a0965f35Sbonwick * Unique major number for all zfs mounts. 1573a0965f35Sbonwick * If we run out of 32-bit minors, we'll getudev() another major. 1574fa9e4066Sahrens */ 1575a0965f35Sbonwick zfs_major = ddi_name_to_major(ZFS_DRIVER); 1576a0965f35Sbonwick zfs_minor = ZFS_MIN_MINOR; 1577fa9e4066Sahrens 1578fa9e4066Sahrens return (0); 1579fa9e4066Sahrens } 1580fa9e4066Sahrens 1581fa9e4066Sahrens void 1582fa9e4066Sahrens zfs_init(void) 1583fa9e4066Sahrens { 1584fa9e4066Sahrens /* 1585fa9e4066Sahrens * Initialize .zfs directory structures 1586fa9e4066Sahrens */ 1587fa9e4066Sahrens zfsctl_init(); 1588fa9e4066Sahrens 1589fa9e4066Sahrens /* 1590fa9e4066Sahrens * Initialize znode cache, vnode ops, etc... 1591fa9e4066Sahrens */ 1592fa9e4066Sahrens zfs_znode_init(); 1593fa9e4066Sahrens } 1594fa9e4066Sahrens 1595fa9e4066Sahrens void 1596fa9e4066Sahrens zfs_fini(void) 1597fa9e4066Sahrens { 1598fa9e4066Sahrens zfsctl_fini(); 1599fa9e4066Sahrens zfs_znode_fini(); 1600fa9e4066Sahrens } 1601fa9e4066Sahrens 1602fa9e4066Sahrens int 1603fa9e4066Sahrens zfs_busy(void) 1604fa9e4066Sahrens { 1605fa9e4066Sahrens return (zfs_active_fs_count != 0); 1606fa9e4066Sahrens } 1607fa9e4066Sahrens 1608e7437265Sahrens int 1609e7437265Sahrens zfs_set_version(const char *name, uint64_t newvers) 1610e7437265Sahrens { 1611e7437265Sahrens int error; 1612e7437265Sahrens objset_t *os; 1613e7437265Sahrens dmu_tx_t *tx; 1614e7437265Sahrens uint64_t curvers; 1615e7437265Sahrens 1616e7437265Sahrens /* 1617e7437265Sahrens * XXX for now, require that the filesystem be unmounted. Would 1618e7437265Sahrens * be nice to find the zfsvfs_t and just update that if 1619e7437265Sahrens * possible. 1620e7437265Sahrens */ 1621e7437265Sahrens 1622e7437265Sahrens if (newvers < ZPL_VERSION_INITIAL || newvers > ZPL_VERSION) 1623e7437265Sahrens return (EINVAL); 1624e7437265Sahrens 1625745cd3c5Smaybee error = dmu_objset_open(name, DMU_OST_ZFS, DS_MODE_OWNER, &os); 1626e7437265Sahrens if (error) 1627e7437265Sahrens return (error); 1628e7437265Sahrens 1629e7437265Sahrens error = zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 1630e7437265Sahrens 8, 1, &curvers); 1631e7437265Sahrens if (error) 1632e7437265Sahrens goto out; 1633e7437265Sahrens if (newvers < curvers) { 1634e7437265Sahrens error = EINVAL; 1635e7437265Sahrens goto out; 1636e7437265Sahrens } 1637e7437265Sahrens 1638e7437265Sahrens tx = dmu_tx_create(os); 1639e7437265Sahrens dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, 0, ZPL_VERSION_STR); 1640e7437265Sahrens error = dmu_tx_assign(tx, TXG_WAIT); 1641e7437265Sahrens if (error) { 1642e7437265Sahrens dmu_tx_abort(tx); 1643e7437265Sahrens goto out; 1644e7437265Sahrens } 1645e7437265Sahrens error = zap_update(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 8, 1, 1646e7437265Sahrens &newvers, tx); 1647e7437265Sahrens 1648e7437265Sahrens spa_history_internal_log(LOG_DS_UPGRADE, 1649e7437265Sahrens dmu_objset_spa(os), tx, CRED(), 1650e7437265Sahrens "oldver=%llu newver=%llu dataset = %llu", curvers, newvers, 1651e7437265Sahrens dmu_objset_id(os)); 1652e7437265Sahrens dmu_tx_commit(tx); 1653e7437265Sahrens 1654e7437265Sahrens out: 1655e7437265Sahrens dmu_objset_close(os); 1656e7437265Sahrens return (error); 1657e7437265Sahrens } 1658e7437265Sahrens 1659de8267e0Stimh /* 1660de8267e0Stimh * Read a property stored within the master node. 1661de8267e0Stimh */ 1662de8267e0Stimh int 1663de8267e0Stimh zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value) 1664de8267e0Stimh { 1665de8267e0Stimh const char *pname; 16660a48a24eStimh int error = ENOENT; 1667de8267e0Stimh 1668de8267e0Stimh /* 1669de8267e0Stimh * Look up the file system's value for the property. For the 1670de8267e0Stimh * version property, we look up a slightly different string. 1671de8267e0Stimh */ 1672de8267e0Stimh if (prop == ZFS_PROP_VERSION) 1673de8267e0Stimh pname = ZPL_VERSION_STR; 1674de8267e0Stimh else 1675de8267e0Stimh pname = zfs_prop_to_name(prop); 1676de8267e0Stimh 16770a48a24eStimh if (os != NULL) 16780a48a24eStimh error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value); 1679de8267e0Stimh 1680aa60ed0eSmaybee if (error == ENOENT) { 1681de8267e0Stimh /* No value set, use the default value */ 1682de8267e0Stimh switch (prop) { 1683aa60ed0eSmaybee case ZFS_PROP_VERSION: 1684aa60ed0eSmaybee *value = ZPL_VERSION; 1685aa60ed0eSmaybee break; 1686de8267e0Stimh case ZFS_PROP_NORMALIZE: 1687de8267e0Stimh case ZFS_PROP_UTF8ONLY: 1688de8267e0Stimh *value = 0; 1689de8267e0Stimh break; 1690de8267e0Stimh case ZFS_PROP_CASE: 1691de8267e0Stimh *value = ZFS_CASE_SENSITIVE; 1692de8267e0Stimh break; 1693de8267e0Stimh default: 1694aa60ed0eSmaybee return (error); 1695de8267e0Stimh } 1696aa60ed0eSmaybee error = 0; 1697de8267e0Stimh } 1698aa60ed0eSmaybee return (error); 1699de8267e0Stimh } 1700de8267e0Stimh 1701fa9e4066Sahrens static vfsdef_t vfw = { 1702fa9e4066Sahrens VFSDEF_VERSION, 1703fa9e4066Sahrens MNTTYPE_ZFS, 1704fa9e4066Sahrens zfs_vfsinit, 1705da6c28aaSamw VSW_HASPROTO|VSW_CANRWRO|VSW_CANREMOUNT|VSW_VOLATILEDEV|VSW_STATS| 1706da6c28aaSamw VSW_XID, 1707fa9e4066Sahrens &zfs_mntopts 1708fa9e4066Sahrens }; 1709fa9e4066Sahrens 1710fa9e4066Sahrens struct modlfs zfs_modlfs = { 1711e7437265Sahrens &mod_fsops, "ZFS filesystem version " SPA_VERSION_STRING, &vfw 1712fa9e4066Sahrens }; 1713