1*8329232eSGordon Ross /* 2*8329232eSGordon Ross * CDDL HEADER START 3*8329232eSGordon Ross * 4*8329232eSGordon Ross * The contents of this file are subject to the terms of the 5*8329232eSGordon Ross * Common Development and Distribution License (the "License"). 6*8329232eSGordon Ross * You may not use this file except in compliance with the License. 7*8329232eSGordon Ross * 8*8329232eSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*8329232eSGordon Ross * or http://www.opensolaris.org/os/licensing. 10*8329232eSGordon Ross * See the License for the specific language governing permissions 11*8329232eSGordon Ross * and limitations under the License. 12*8329232eSGordon Ross * 13*8329232eSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14*8329232eSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*8329232eSGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16*8329232eSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17*8329232eSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18*8329232eSGordon Ross * 19*8329232eSGordon Ross * CDDL HEADER END 20*8329232eSGordon Ross */ 21*8329232eSGordon Ross 22*8329232eSGordon Ross /* 23*8329232eSGordon Ross * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. 24*8329232eSGordon Ross * Copyright 2016 Joyent, Inc. 25*8329232eSGordon Ross * Copyright 2016 Toomas Soome <tsoome@me.com> 26*8329232eSGordon Ross * Copyright (c) 2016 by Delphix. All rights reserved. 27*8329232eSGordon Ross * Copyright 2017 RackTop Systems. 28*8329232eSGordon Ross * Copyright 2018 Nexenta Systems, Inc. 29*8329232eSGordon Ross */ 30*8329232eSGordon Ross 31*8329232eSGordon Ross /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 32*8329232eSGordon Ross /* All Rights Reserved */ 33*8329232eSGordon Ross 34*8329232eSGordon Ross /* 35*8329232eSGordon Ross * University Copyright- Copyright (c) 1982, 1986, 1988 36*8329232eSGordon Ross * The Regents of the University of California 37*8329232eSGordon Ross * All Rights Reserved 38*8329232eSGordon Ross * 39*8329232eSGordon Ross * University Acknowledgment- Portions of this document are derived from 40*8329232eSGordon Ross * software developed by the University of California, Berkeley, and its 41*8329232eSGordon Ross * contributors. 42*8329232eSGordon Ross */ 43*8329232eSGordon Ross 44*8329232eSGordon Ross /* 45*8329232eSGordon Ross * This file contains those functions from fs/vfs.c that can be 46*8329232eSGordon Ross * used with relatively little change. Functions that differ 47*8329232eSGordon Ross * significantly from that are in other files. 48*8329232eSGordon Ross */ 49*8329232eSGordon Ross 50*8329232eSGordon Ross #include <sys/types.h> 51*8329232eSGordon Ross #include <sys/t_lock.h> 52*8329232eSGordon Ross #include <sys/param.h> 53*8329232eSGordon Ross #include <sys/errno.h> 54*8329232eSGordon Ross #include <sys/user.h> 55*8329232eSGordon Ross #include <sys/fstyp.h> 56*8329232eSGordon Ross #include <sys/kmem.h> 57*8329232eSGordon Ross #include <sys/systm.h> 58*8329232eSGordon Ross #include <sys/proc.h> 59*8329232eSGordon Ross #include <sys/mount.h> 60*8329232eSGordon Ross #include <sys/vfs.h> 61*8329232eSGordon Ross #include <sys/vfs_opreg.h> 62*8329232eSGordon Ross #include <sys/fem.h> 63*8329232eSGordon Ross #include <sys/mntent.h> 64*8329232eSGordon Ross #include <sys/stat.h> 65*8329232eSGordon Ross #include <sys/statvfs.h> 66*8329232eSGordon Ross #include <sys/statfs.h> 67*8329232eSGordon Ross #include <sys/cred.h> 68*8329232eSGordon Ross #include <sys/vnode.h> 69*8329232eSGordon Ross #include <sys/rwstlock.h> 70*8329232eSGordon Ross #include <sys/dnlc.h> 71*8329232eSGordon Ross #include <sys/file.h> 72*8329232eSGordon Ross #include <sys/time.h> 73*8329232eSGordon Ross #include <sys/atomic.h> 74*8329232eSGordon Ross #include <sys/cmn_err.h> 75*8329232eSGordon Ross #include <sys/buf.h> 76*8329232eSGordon Ross #include <sys/debug.h> 77*8329232eSGordon Ross #include <sys/vnode.h> 78*8329232eSGordon Ross #include <sys/ddi.h> 79*8329232eSGordon Ross #include <sys/pathname.h> 80*8329232eSGordon Ross #include <sys/poll.h> 81*8329232eSGordon Ross #include <sys/sunddi.h> 82*8329232eSGordon Ross #include <sys/sysmacros.h> 83*8329232eSGordon Ross #include <sys/zone.h> 84*8329232eSGordon Ross #include <sys/policy.h> 85*8329232eSGordon Ross #include <sys/attr.h> 86*8329232eSGordon Ross #include <fs/fs_subr.h> 87*8329232eSGordon Ross 88*8329232eSGordon Ross #include <libfksmbfs.h> 89*8329232eSGordon Ross 90*8329232eSGordon Ross static void vfs_clearmntopt_nolock(mntopts_t *, const char *, int); 91*8329232eSGordon Ross static void vfs_setmntopt_nolock(mntopts_t *, const char *, 92*8329232eSGordon Ross const char *, int, int); 93*8329232eSGordon Ross static int vfs_optionisset_nolock(const mntopts_t *, const char *, char **); 94*8329232eSGordon Ross // static void vfs_freemnttab(struct vfs *); 95*8329232eSGordon Ross static void vfs_freeopt(mntopt_t *); 96*8329232eSGordon Ross static void vfs_swapopttbl_nolock(mntopts_t *, mntopts_t *); 97*8329232eSGordon Ross static void vfs_swapopttbl(mntopts_t *, mntopts_t *); 98*8329232eSGordon Ross static void vfs_copyopttbl_extend(const mntopts_t *, mntopts_t *, int); 99*8329232eSGordon Ross // static void vfs_createopttbl_extend(mntopts_t *, const char *, 100*8329232eSGordon Ross // const mntopts_t *); 101*8329232eSGordon Ross // static char **vfs_copycancelopt_extend(char **const, int); 102*8329232eSGordon Ross static void vfs_freecancelopt(char **); 103*8329232eSGordon Ross 104*8329232eSGordon Ross /* 105*8329232eSGordon Ross * VFS global data. 106*8329232eSGordon Ross */ 107*8329232eSGordon Ross vnode_t *rootdir; /* pointer to root inode vnode. */ 108*8329232eSGordon Ross struct vfs *rootvfs = NULL; /* pointer to root vfs; head of VFS list. */ 109*8329232eSGordon Ross static krwlock_t vfslist; 110*8329232eSGordon Ross struct vfs *zone_vfslist; /* list of FS's mounted in zone */ 111*8329232eSGordon Ross 112*8329232eSGordon Ross /* from os/vfs_conf.c */ 113*8329232eSGordon Ross const int nfstype = 5; 114*8329232eSGordon Ross struct vfssw vfssw[10] = { 115*8329232eSGordon Ross { "BADVFS" }, /* 0:invalid */ 116*8329232eSGordon Ross { "" }, /* reserved for loadable fs */ 117*8329232eSGordon Ross { "" }, 118*8329232eSGordon Ross { "" }, 119*8329232eSGordon Ross { "" }, 120*8329232eSGordon Ross }; 121*8329232eSGordon Ross 122*8329232eSGordon Ross /* 123*8329232eSGordon Ross * Table for generic options recognized in the VFS layer and acted 124*8329232eSGordon Ross * on at this level before parsing file system specific options. 125*8329232eSGordon Ross * The nosuid option is stronger than any of the devices and setuid 126*8329232eSGordon Ross * options, so those are canceled when nosuid is seen. 127*8329232eSGordon Ross * 128*8329232eSGordon Ross * All options which are added here need to be added to the 129*8329232eSGordon Ross * list of standard options in usr/src/cmd/fs.d/fslib.c as well. 130*8329232eSGordon Ross */ 131*8329232eSGordon Ross /* 132*8329232eSGordon Ross * VFS Mount options table 133*8329232eSGordon Ross */ 134*8329232eSGordon Ross static char *ro_cancel[] = { MNTOPT_RW, NULL }; 135*8329232eSGordon Ross static char *rw_cancel[] = { MNTOPT_RO, NULL }; 136*8329232eSGordon Ross static char *suid_cancel[] = { MNTOPT_NOSUID, NULL }; 137*8329232eSGordon Ross static char *nosuid_cancel[] = { MNTOPT_SUID, MNTOPT_DEVICES, MNTOPT_NODEVICES, 138*8329232eSGordon Ross MNTOPT_NOSETUID, MNTOPT_SETUID, NULL }; 139*8329232eSGordon Ross static char *devices_cancel[] = { MNTOPT_NODEVICES, NULL }; 140*8329232eSGordon Ross static char *nodevices_cancel[] = { MNTOPT_DEVICES, NULL }; 141*8329232eSGordon Ross static char *setuid_cancel[] = { MNTOPT_NOSETUID, NULL }; 142*8329232eSGordon Ross static char *nosetuid_cancel[] = { MNTOPT_SETUID, NULL }; 143*8329232eSGordon Ross static char *nbmand_cancel[] = { MNTOPT_NONBMAND, NULL }; 144*8329232eSGordon Ross static char *nonbmand_cancel[] = { MNTOPT_NBMAND, NULL }; 145*8329232eSGordon Ross static char *exec_cancel[] = { MNTOPT_NOEXEC, NULL }; 146*8329232eSGordon Ross static char *noexec_cancel[] = { MNTOPT_EXEC, NULL }; 147*8329232eSGordon Ross 148*8329232eSGordon Ross static const mntopt_t mntopts[] = { 149*8329232eSGordon Ross /* 150*8329232eSGordon Ross * option name cancel options default arg flags 151*8329232eSGordon Ross */ 152*8329232eSGordon Ross { MNTOPT_REMOUNT, NULL, NULL, 153*8329232eSGordon Ross MO_NODISPLAY, (void *)0 }, 154*8329232eSGordon Ross { MNTOPT_RO, ro_cancel, NULL, 0, 155*8329232eSGordon Ross (void *)0 }, 156*8329232eSGordon Ross { MNTOPT_RW, rw_cancel, NULL, 0, 157*8329232eSGordon Ross (void *)0 }, 158*8329232eSGordon Ross { MNTOPT_SUID, suid_cancel, NULL, 0, 159*8329232eSGordon Ross (void *)0 }, 160*8329232eSGordon Ross { MNTOPT_NOSUID, nosuid_cancel, NULL, 0, 161*8329232eSGordon Ross (void *)0 }, 162*8329232eSGordon Ross { MNTOPT_DEVICES, devices_cancel, NULL, 0, 163*8329232eSGordon Ross (void *)0 }, 164*8329232eSGordon Ross { MNTOPT_NODEVICES, nodevices_cancel, NULL, 0, 165*8329232eSGordon Ross (void *)0 }, 166*8329232eSGordon Ross { MNTOPT_SETUID, setuid_cancel, NULL, 0, 167*8329232eSGordon Ross (void *)0 }, 168*8329232eSGordon Ross { MNTOPT_NOSETUID, nosetuid_cancel, NULL, 0, 169*8329232eSGordon Ross (void *)0 }, 170*8329232eSGordon Ross { MNTOPT_NBMAND, nbmand_cancel, NULL, 0, 171*8329232eSGordon Ross (void *)0 }, 172*8329232eSGordon Ross { MNTOPT_NONBMAND, nonbmand_cancel, NULL, 0, 173*8329232eSGordon Ross (void *)0 }, 174*8329232eSGordon Ross { MNTOPT_EXEC, exec_cancel, NULL, 0, 175*8329232eSGordon Ross (void *)0 }, 176*8329232eSGordon Ross { MNTOPT_NOEXEC, noexec_cancel, NULL, 0, 177*8329232eSGordon Ross (void *)0 }, 178*8329232eSGordon Ross }; 179*8329232eSGordon Ross 180*8329232eSGordon Ross const mntopts_t vfs_mntopts = { 181*8329232eSGordon Ross sizeof (mntopts) / sizeof (mntopt_t), 182*8329232eSGordon Ross (mntopt_t *)&mntopts[0] 183*8329232eSGordon Ross }; 184*8329232eSGordon Ross 185*8329232eSGordon Ross /* 186*8329232eSGordon Ross * File system operation dispatch functions. 187*8329232eSGordon Ross */ 188*8329232eSGordon Ross 189*8329232eSGordon Ross int 190*8329232eSGordon Ross fsop_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) 191*8329232eSGordon Ross { 192*8329232eSGordon Ross return (*(vfsp)->vfs_op->vfs_mount)(vfsp, mvp, uap, cr); 193*8329232eSGordon Ross } 194*8329232eSGordon Ross 195*8329232eSGordon Ross int 196*8329232eSGordon Ross fsop_unmount(vfs_t *vfsp, int flag, cred_t *cr) 197*8329232eSGordon Ross { 198*8329232eSGordon Ross return (*(vfsp)->vfs_op->vfs_unmount)(vfsp, flag, cr); 199*8329232eSGordon Ross } 200*8329232eSGordon Ross 201*8329232eSGordon Ross int 202*8329232eSGordon Ross fsop_root(vfs_t *vfsp, vnode_t **vpp) 203*8329232eSGordon Ross { 204*8329232eSGordon Ross return ((*(vfsp)->vfs_op->vfs_root)(vfsp, vpp)); 205*8329232eSGordon Ross } 206*8329232eSGordon Ross 207*8329232eSGordon Ross int 208*8329232eSGordon Ross fsop_statfs(vfs_t *vfsp, statvfs64_t *sp) 209*8329232eSGordon Ross { 210*8329232eSGordon Ross return (*(vfsp)->vfs_op->vfs_statvfs)(vfsp, sp); 211*8329232eSGordon Ross } 212*8329232eSGordon Ross 213*8329232eSGordon Ross int 214*8329232eSGordon Ross fsop_sync(vfs_t *vfsp, short flag, cred_t *cr) 215*8329232eSGordon Ross { 216*8329232eSGordon Ross return (*(vfsp)->vfs_op->vfs_sync)(vfsp, flag, cr); 217*8329232eSGordon Ross } 218*8329232eSGordon Ross 219*8329232eSGordon Ross int 220*8329232eSGordon Ross fsop_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp) 221*8329232eSGordon Ross { 222*8329232eSGordon Ross return (*(vfsp)->vfs_op->vfs_vget)(vfsp, vpp, fidp); 223*8329232eSGordon Ross } 224*8329232eSGordon Ross 225*8329232eSGordon Ross int 226*8329232eSGordon Ross fsop_mountroot(vfs_t *vfsp, enum whymountroot reason) 227*8329232eSGordon Ross { 228*8329232eSGordon Ross return (*(vfsp)->vfs_op->vfs_mountroot)(vfsp, reason); 229*8329232eSGordon Ross } 230*8329232eSGordon Ross 231*8329232eSGordon Ross void 232*8329232eSGordon Ross fsop_freefs(vfs_t *vfsp) 233*8329232eSGordon Ross { 234*8329232eSGordon Ross (*(vfsp)->vfs_op->vfs_freevfs)(vfsp); 235*8329232eSGordon Ross } 236*8329232eSGordon Ross 237*8329232eSGordon Ross int 238*8329232eSGordon Ross fsop_vnstate(vfs_t *vfsp, vnode_t *vp, vntrans_t nstate) 239*8329232eSGordon Ross { 240*8329232eSGordon Ross return ((*(vfsp)->vfs_op->vfs_vnstate)(vfsp, vp, nstate)); 241*8329232eSGordon Ross } 242*8329232eSGordon Ross 243*8329232eSGordon Ross int 244*8329232eSGordon Ross fsop_sync_by_kind(int fstype, short flag, cred_t *cr) 245*8329232eSGordon Ross { 246*8329232eSGordon Ross ASSERT((fstype >= 0) && (fstype < nfstype)); 247*8329232eSGordon Ross 248*8329232eSGordon Ross if (ALLOCATED_VFSSW(&vfssw[fstype]) && VFS_INSTALLED(&vfssw[fstype])) 249*8329232eSGordon Ross return (*vfssw[fstype].vsw_vfsops.vfs_sync) (NULL, flag, cr); 250*8329232eSGordon Ross else 251*8329232eSGordon Ross return (ENOTSUP); 252*8329232eSGordon Ross } 253*8329232eSGordon Ross 254*8329232eSGordon Ross /* 255*8329232eSGordon Ross * File system initialization. vfs_setfsops() must be called from a file 256*8329232eSGordon Ross * system's init routine. 257*8329232eSGordon Ross */ 258*8329232eSGordon Ross 259*8329232eSGordon Ross static int 260*8329232eSGordon Ross fs_copyfsops(const fs_operation_def_t *template, vfsops_t *actual, 261*8329232eSGordon Ross int *unused_ops) 262*8329232eSGordon Ross { 263*8329232eSGordon Ross static const fs_operation_trans_def_t vfs_ops_table[] = { 264*8329232eSGordon Ross VFSNAME_MOUNT, offsetof(vfsops_t, vfs_mount), 265*8329232eSGordon Ross fs_nosys, fs_nosys, 266*8329232eSGordon Ross 267*8329232eSGordon Ross VFSNAME_UNMOUNT, offsetof(vfsops_t, vfs_unmount), 268*8329232eSGordon Ross fs_nosys, fs_nosys, 269*8329232eSGordon Ross 270*8329232eSGordon Ross VFSNAME_ROOT, offsetof(vfsops_t, vfs_root), 271*8329232eSGordon Ross fs_nosys, fs_nosys, 272*8329232eSGordon Ross 273*8329232eSGordon Ross VFSNAME_STATVFS, offsetof(vfsops_t, vfs_statvfs), 274*8329232eSGordon Ross fs_nosys, fs_nosys, 275*8329232eSGordon Ross 276*8329232eSGordon Ross VFSNAME_SYNC, offsetof(vfsops_t, vfs_sync), 277*8329232eSGordon Ross (fs_generic_func_p) fs_sync, 278*8329232eSGordon Ross (fs_generic_func_p) fs_sync, /* No errors allowed */ 279*8329232eSGordon Ross 280*8329232eSGordon Ross VFSNAME_VGET, offsetof(vfsops_t, vfs_vget), 281*8329232eSGordon Ross fs_nosys, fs_nosys, 282*8329232eSGordon Ross 283*8329232eSGordon Ross VFSNAME_MOUNTROOT, offsetof(vfsops_t, vfs_mountroot), 284*8329232eSGordon Ross fs_nosys, fs_nosys, 285*8329232eSGordon Ross 286*8329232eSGordon Ross VFSNAME_FREEVFS, offsetof(vfsops_t, vfs_freevfs), 287*8329232eSGordon Ross (fs_generic_func_p)fs_freevfs, 288*8329232eSGordon Ross (fs_generic_func_p)fs_freevfs, /* Shouldn't fail */ 289*8329232eSGordon Ross 290*8329232eSGordon Ross VFSNAME_VNSTATE, offsetof(vfsops_t, vfs_vnstate), 291*8329232eSGordon Ross (fs_generic_func_p)fs_nosys, 292*8329232eSGordon Ross (fs_generic_func_p)fs_nosys, 293*8329232eSGordon Ross 294*8329232eSGordon Ross NULL, 0, NULL, NULL 295*8329232eSGordon Ross }; 296*8329232eSGordon Ross 297*8329232eSGordon Ross return (fs_build_vector(actual, unused_ops, vfs_ops_table, template)); 298*8329232eSGordon Ross } 299*8329232eSGordon Ross 300*8329232eSGordon Ross /* zfs_boot_init() */ 301*8329232eSGordon Ross 302*8329232eSGordon Ross int 303*8329232eSGordon Ross vfs_setfsops(int fstype, const fs_operation_def_t *template, vfsops_t **actual) 304*8329232eSGordon Ross { 305*8329232eSGordon Ross int error; 306*8329232eSGordon Ross int unused_ops; 307*8329232eSGordon Ross 308*8329232eSGordon Ross /* 309*8329232eSGordon Ross * Verify that fstype refers to a valid fs. Note that 310*8329232eSGordon Ross * 0 is valid since it's used to set "stray" ops. 311*8329232eSGordon Ross */ 312*8329232eSGordon Ross if ((fstype < 0) || (fstype >= nfstype)) 313*8329232eSGordon Ross return (EINVAL); 314*8329232eSGordon Ross 315*8329232eSGordon Ross if (!ALLOCATED_VFSSW(&vfssw[fstype])) 316*8329232eSGordon Ross return (EINVAL); 317*8329232eSGordon Ross 318*8329232eSGordon Ross /* Set up the operations vector. */ 319*8329232eSGordon Ross 320*8329232eSGordon Ross error = fs_copyfsops(template, &vfssw[fstype].vsw_vfsops, &unused_ops); 321*8329232eSGordon Ross 322*8329232eSGordon Ross if (error != 0) 323*8329232eSGordon Ross return (error); 324*8329232eSGordon Ross 325*8329232eSGordon Ross vfssw[fstype].vsw_flag |= VSW_INSTALLED; 326*8329232eSGordon Ross 327*8329232eSGordon Ross if (actual != NULL) 328*8329232eSGordon Ross *actual = &vfssw[fstype].vsw_vfsops; 329*8329232eSGordon Ross 330*8329232eSGordon Ross #if DEBUG 331*8329232eSGordon Ross if (unused_ops != 0) 332*8329232eSGordon Ross cmn_err(CE_WARN, "vfs_setfsops: %s: %d operations supplied " 333*8329232eSGordon Ross "but not used", vfssw[fstype].vsw_name, unused_ops); 334*8329232eSGordon Ross #endif 335*8329232eSGordon Ross 336*8329232eSGordon Ross return (0); 337*8329232eSGordon Ross } 338*8329232eSGordon Ross 339*8329232eSGordon Ross int 340*8329232eSGordon Ross vfs_makefsops(const fs_operation_def_t *template, vfsops_t **actual) 341*8329232eSGordon Ross { 342*8329232eSGordon Ross int error; 343*8329232eSGordon Ross int unused_ops; 344*8329232eSGordon Ross 345*8329232eSGordon Ross *actual = (vfsops_t *)kmem_alloc(sizeof (vfsops_t), KM_SLEEP); 346*8329232eSGordon Ross 347*8329232eSGordon Ross error = fs_copyfsops(template, *actual, &unused_ops); 348*8329232eSGordon Ross if (error != 0) { 349*8329232eSGordon Ross kmem_free(*actual, sizeof (vfsops_t)); 350*8329232eSGordon Ross *actual = NULL; 351*8329232eSGordon Ross return (error); 352*8329232eSGordon Ross } 353*8329232eSGordon Ross 354*8329232eSGordon Ross return (0); 355*8329232eSGordon Ross } 356*8329232eSGordon Ross 357*8329232eSGordon Ross /* 358*8329232eSGordon Ross * Free a vfsops structure created as a result of vfs_makefsops(). 359*8329232eSGordon Ross * NOTE: For a vfsops structure initialized by vfs_setfsops(), use 360*8329232eSGordon Ross * vfs_freevfsops_by_type(). 361*8329232eSGordon Ross */ 362*8329232eSGordon Ross void 363*8329232eSGordon Ross vfs_freevfsops(vfsops_t *vfsops) 364*8329232eSGordon Ross { 365*8329232eSGordon Ross kmem_free(vfsops, sizeof (vfsops_t)); 366*8329232eSGordon Ross } 367*8329232eSGordon Ross 368*8329232eSGordon Ross /* 369*8329232eSGordon Ross * Since the vfsops structure is part of the vfssw table and wasn't 370*8329232eSGordon Ross * really allocated, we're not really freeing anything. We keep 371*8329232eSGordon Ross * the name for consistency with vfs_freevfsops(). We do, however, 372*8329232eSGordon Ross * need to take care of a little bookkeeping. 373*8329232eSGordon Ross * NOTE: For a vfsops structure created by vfs_setfsops(), use 374*8329232eSGordon Ross * vfs_freevfsops_by_type(). 375*8329232eSGordon Ross */ 376*8329232eSGordon Ross int 377*8329232eSGordon Ross vfs_freevfsops_by_type(int fstype) 378*8329232eSGordon Ross { 379*8329232eSGordon Ross 380*8329232eSGordon Ross /* Verify that fstype refers to a loaded fs (and not fsid 0). */ 381*8329232eSGordon Ross if ((fstype <= 0) || (fstype >= nfstype)) 382*8329232eSGordon Ross return (EINVAL); 383*8329232eSGordon Ross 384*8329232eSGordon Ross WLOCK_VFSSW(); 385*8329232eSGordon Ross if ((vfssw[fstype].vsw_flag & VSW_INSTALLED) == 0) { 386*8329232eSGordon Ross WUNLOCK_VFSSW(); 387*8329232eSGordon Ross return (EINVAL); 388*8329232eSGordon Ross } 389*8329232eSGordon Ross 390*8329232eSGordon Ross vfssw[fstype].vsw_flag &= ~VSW_INSTALLED; 391*8329232eSGordon Ross WUNLOCK_VFSSW(); 392*8329232eSGordon Ross 393*8329232eSGordon Ross return (0); 394*8329232eSGordon Ross } 395*8329232eSGordon Ross 396*8329232eSGordon Ross /* Support routines used to reference vfs_op */ 397*8329232eSGordon Ross 398*8329232eSGordon Ross /* Set the operations vector for a vfs */ 399*8329232eSGordon Ross void 400*8329232eSGordon Ross vfs_setops(vfs_t *vfsp, vfsops_t *vfsops) 401*8329232eSGordon Ross { 402*8329232eSGordon Ross 403*8329232eSGordon Ross ASSERT(vfsp != NULL); 404*8329232eSGordon Ross ASSERT(vfsops != NULL); 405*8329232eSGordon Ross 406*8329232eSGordon Ross vfsp->vfs_op = vfsops; 407*8329232eSGordon Ross } 408*8329232eSGordon Ross 409*8329232eSGordon Ross /* Retrieve the operations vector for a vfs */ 410*8329232eSGordon Ross vfsops_t * 411*8329232eSGordon Ross vfs_getops(vfs_t *vfsp) 412*8329232eSGordon Ross { 413*8329232eSGordon Ross 414*8329232eSGordon Ross ASSERT(vfsp != NULL); 415*8329232eSGordon Ross 416*8329232eSGordon Ross return (vfsp->vfs_op); 417*8329232eSGordon Ross } 418*8329232eSGordon Ross 419*8329232eSGordon Ross /* 420*8329232eSGordon Ross * Returns non-zero (1) if the vfsops matches that of the vfs. 421*8329232eSGordon Ross * Returns zero (0) if not. 422*8329232eSGordon Ross */ 423*8329232eSGordon Ross int 424*8329232eSGordon Ross vfs_matchops(vfs_t *vfsp, vfsops_t *vfsops) 425*8329232eSGordon Ross { 426*8329232eSGordon Ross return (vfs_getops(vfsp) == vfsops); 427*8329232eSGordon Ross } 428*8329232eSGordon Ross 429*8329232eSGordon Ross /* 430*8329232eSGordon Ross * Returns non-zero (1) if the file system has installed a non-default, 431*8329232eSGordon Ross * non-error vfs_sync routine. Returns zero (0) otherwise. 432*8329232eSGordon Ross */ 433*8329232eSGordon Ross int 434*8329232eSGordon Ross vfs_can_sync(vfs_t *vfsp) 435*8329232eSGordon Ross { 436*8329232eSGordon Ross /* vfs_sync() routine is not the default/error function */ 437*8329232eSGordon Ross return (vfs_getops(vfsp)->vfs_sync != fs_sync); 438*8329232eSGordon Ross } 439*8329232eSGordon Ross 440*8329232eSGordon Ross /* 441*8329232eSGordon Ross * Initialize a vfs structure. 442*8329232eSGordon Ross */ 443*8329232eSGordon Ross void 444*8329232eSGordon Ross vfs_init(vfs_t *vfsp, vfsops_t *op, void *data) 445*8329232eSGordon Ross { 446*8329232eSGordon Ross /* Always do full init, like vfs_alloc() */ 447*8329232eSGordon Ross bzero(vfsp, sizeof (vfs_t)); 448*8329232eSGordon Ross vfsp->vfs_count = 0; 449*8329232eSGordon Ross vfsp->vfs_next = vfsp; 450*8329232eSGordon Ross vfsp->vfs_prev = vfsp; 451*8329232eSGordon Ross vfsp->vfs_zone_next = vfsp; 452*8329232eSGordon Ross vfsp->vfs_zone_prev = vfsp; 453*8329232eSGordon Ross vfsp->vfs_lofi_id = 0; 454*8329232eSGordon Ross sema_init(&vfsp->vfs_reflock, 1, NULL, SEMA_DEFAULT, NULL); 455*8329232eSGordon Ross vfsimpl_setup(vfsp); 456*8329232eSGordon Ross vfsp->vfs_data = (data); 457*8329232eSGordon Ross vfs_setops((vfsp), (op)); 458*8329232eSGordon Ross } 459*8329232eSGordon Ross 460*8329232eSGordon Ross /* 461*8329232eSGordon Ross * Allocate and initialize the vfs implementation private data 462*8329232eSGordon Ross * structure, vfs_impl_t. 463*8329232eSGordon Ross */ 464*8329232eSGordon Ross void 465*8329232eSGordon Ross vfsimpl_setup(vfs_t *vfsp) 466*8329232eSGordon Ross { 467*8329232eSGordon Ross int i; 468*8329232eSGordon Ross 469*8329232eSGordon Ross if (vfsp->vfs_implp != NULL) { 470*8329232eSGordon Ross return; 471*8329232eSGordon Ross } 472*8329232eSGordon Ross 473*8329232eSGordon Ross vfsp->vfs_implp = kmem_alloc(sizeof (vfs_impl_t), KM_SLEEP); 474*8329232eSGordon Ross /* Note that these are #define'd in vfs.h */ 475*8329232eSGordon Ross vfsp->vfs_vskap = NULL; 476*8329232eSGordon Ross vfsp->vfs_fstypevsp = NULL; 477*8329232eSGordon Ross 478*8329232eSGordon Ross /* Set size of counted array, then zero the array */ 479*8329232eSGordon Ross vfsp->vfs_featureset[0] = VFS_FEATURE_MAXSZ - 1; 480*8329232eSGordon Ross for (i = 1; i < VFS_FEATURE_MAXSZ; i++) { 481*8329232eSGordon Ross vfsp->vfs_featureset[i] = 0; 482*8329232eSGordon Ross } 483*8329232eSGordon Ross } 484*8329232eSGordon Ross 485*8329232eSGordon Ross /* 486*8329232eSGordon Ross * Release the vfs_impl_t structure, if it exists. Some unbundled 487*8329232eSGordon Ross * filesystems may not use the newer version of vfs and thus 488*8329232eSGordon Ross * would not contain this implementation private data structure. 489*8329232eSGordon Ross */ 490*8329232eSGordon Ross void 491*8329232eSGordon Ross vfsimpl_teardown(vfs_t *vfsp) 492*8329232eSGordon Ross { 493*8329232eSGordon Ross vfs_impl_t *vip = vfsp->vfs_implp; 494*8329232eSGordon Ross 495*8329232eSGordon Ross if (vip == NULL) 496*8329232eSGordon Ross return; 497*8329232eSGordon Ross 498*8329232eSGordon Ross kmem_free(vfsp->vfs_implp, sizeof (vfs_impl_t)); 499*8329232eSGordon Ross vfsp->vfs_implp = NULL; 500*8329232eSGordon Ross } 501*8329232eSGordon Ross 502*8329232eSGordon Ross /* 503*8329232eSGordon Ross * VFS system calls: mount, umount, syssync, statfs, fstatfs, statvfs, 504*8329232eSGordon Ross * fstatvfs, and sysfs moved to common/syscall. 505*8329232eSGordon Ross */ 506*8329232eSGordon Ross 507*8329232eSGordon Ross // vfs_sync, sync 508*8329232eSGordon Ross 509*8329232eSGordon Ross /* 510*8329232eSGordon Ross * External routines. 511*8329232eSGordon Ross */ 512*8329232eSGordon Ross 513*8329232eSGordon Ross krwlock_t vfssw_lock; /* lock accesses to vfssw */ 514*8329232eSGordon Ross 515*8329232eSGordon Ross /* 516*8329232eSGordon Ross * Lock for accessing the vfs linked list. Initialized in vfs_mountroot(), 517*8329232eSGordon Ross * but otherwise should be accessed only via vfs_list_lock() and 518*8329232eSGordon Ross * vfs_list_unlock(). Also used to protect the timestamp for mods to the list. 519*8329232eSGordon Ross */ 520*8329232eSGordon Ross static krwlock_t vfslist; 521*8329232eSGordon Ross 522*8329232eSGordon Ross // vfs_mountdevices(void) 523*8329232eSGordon Ross // vfs_mountdev1(void) 524*8329232eSGordon Ross // vfs_mountfs() 525*8329232eSGordon Ross // vfs_mountroot() 526*8329232eSGordon Ross // lofi_add, lofi_remove 527*8329232eSGordon Ross 528*8329232eSGordon Ross 529*8329232eSGordon Ross /* 530*8329232eSGordon Ross * Mount the FS for the test jig. Based on domount() 531*8329232eSGordon Ross */ 532*8329232eSGordon Ross int 533*8329232eSGordon Ross fake_domount(char *fsname, struct mounta *uap, struct vfs **vfspp) 534*8329232eSGordon Ross { 535*8329232eSGordon Ross vnode_t *vp; 536*8329232eSGordon Ross struct cred *credp; 537*8329232eSGordon Ross struct vfssw *vswp; 538*8329232eSGordon Ross vfsops_t *vfsops; 539*8329232eSGordon Ross struct vfs *vfsp = NULL; 540*8329232eSGordon Ross mntopts_t mnt_mntopts; 541*8329232eSGordon Ross int error = 0; 542*8329232eSGordon Ross int copyout_error = 0; 543*8329232eSGordon Ross char *opts = uap->optptr; 544*8329232eSGordon Ross char *inargs = opts; 545*8329232eSGordon Ross int optlen = uap->optlen; 546*8329232eSGordon Ross 547*8329232eSGordon Ross credp = CRED(); 548*8329232eSGordon Ross 549*8329232eSGordon Ross /* 550*8329232eSGordon Ross * Test jig specific: mount on rootdir 551*8329232eSGordon Ross */ 552*8329232eSGordon Ross if (rootvfs != NULL) 553*8329232eSGordon Ross return (EBUSY); 554*8329232eSGordon Ross vp = rootdir; 555*8329232eSGordon Ross 556*8329232eSGordon Ross /* 557*8329232eSGordon Ross * The v_flag value for the mount point vp is permanently set 558*8329232eSGordon Ross * to VVFSLOCK so that no one bypasses the vn_vfs*locks routine 559*8329232eSGordon Ross * for mount point locking. 560*8329232eSGordon Ross */ 561*8329232eSGordon Ross mutex_enter(&vp->v_lock); 562*8329232eSGordon Ross vp->v_flag |= VVFSLOCK; 563*8329232eSGordon Ross mutex_exit(&vp->v_lock); 564*8329232eSGordon Ross 565*8329232eSGordon Ross mnt_mntopts.mo_count = 0; 566*8329232eSGordon Ross 567*8329232eSGordon Ross /* 568*8329232eSGordon Ross * Find the ops vector to use to invoke the file system-specific mount 569*8329232eSGordon Ross * method. If the fsname argument is non-NULL, use it directly. 570*8329232eSGordon Ross */ 571*8329232eSGordon Ross if ((vswp = vfs_getvfssw(fsname)) == NULL) { 572*8329232eSGordon Ross return (EINVAL); 573*8329232eSGordon Ross } 574*8329232eSGordon Ross if (!VFS_INSTALLED(vswp)) 575*8329232eSGordon Ross return (EINVAL); 576*8329232eSGordon Ross 577*8329232eSGordon Ross // secpolicy_fs_allowed_mount(fsname) 578*8329232eSGordon Ross 579*8329232eSGordon Ross vfsops = &vswp->vsw_vfsops; 580*8329232eSGordon Ross 581*8329232eSGordon Ross vfs_copyopttbl(&vswp->vsw_optproto, &mnt_mntopts); 582*8329232eSGordon Ross 583*8329232eSGordon Ross /* 584*8329232eSGordon Ross * Fetch mount options and parse them for generic vfs options 585*8329232eSGordon Ross */ 586*8329232eSGordon Ross if (uap->flags & MS_OPTIONSTR) { 587*8329232eSGordon Ross /* 588*8329232eSGordon Ross * Limit the buffer size 589*8329232eSGordon Ross */ 590*8329232eSGordon Ross if (optlen < 0 || optlen > MAX_MNTOPT_STR) { 591*8329232eSGordon Ross error = EINVAL; 592*8329232eSGordon Ross goto errout; 593*8329232eSGordon Ross } 594*8329232eSGordon Ross if ((uap->flags & MS_SYSSPACE) == 0) { 595*8329232eSGordon Ross inargs = kmem_alloc(MAX_MNTOPT_STR, KM_SLEEP); 596*8329232eSGordon Ross inargs[0] = '\0'; 597*8329232eSGordon Ross if (optlen) { 598*8329232eSGordon Ross error = copyinstr(opts, inargs, (size_t)optlen, 599*8329232eSGordon Ross NULL); 600*8329232eSGordon Ross if (error) { 601*8329232eSGordon Ross goto errout; 602*8329232eSGordon Ross } 603*8329232eSGordon Ross } 604*8329232eSGordon Ross } 605*8329232eSGordon Ross vfs_parsemntopts(&mnt_mntopts, inargs, 0); 606*8329232eSGordon Ross } 607*8329232eSGordon Ross /* 608*8329232eSGordon Ross * Flag bits override the options string. 609*8329232eSGordon Ross */ 610*8329232eSGordon Ross if (uap->flags & MS_REMOUNT) 611*8329232eSGordon Ross vfs_setmntopt_nolock(&mnt_mntopts, MNTOPT_REMOUNT, NULL, 0, 0); 612*8329232eSGordon Ross if (uap->flags & MS_RDONLY) 613*8329232eSGordon Ross vfs_setmntopt_nolock(&mnt_mntopts, MNTOPT_RO, NULL, 0, 0); 614*8329232eSGordon Ross if (uap->flags & MS_NOSUID) 615*8329232eSGordon Ross vfs_setmntopt_nolock(&mnt_mntopts, MNTOPT_NOSUID, NULL, 0, 0); 616*8329232eSGordon Ross 617*8329232eSGordon Ross /* 618*8329232eSGordon Ross * Check if this is a remount; must be set in the option string and 619*8329232eSGordon Ross * the file system must support a remount option. 620*8329232eSGordon Ross */ 621*8329232eSGordon Ross if (vfs_optionisset_nolock(&mnt_mntopts, 622*8329232eSGordon Ross MNTOPT_REMOUNT, NULL)) { 623*8329232eSGordon Ross /* disallow here */ 624*8329232eSGordon Ross error = ENOTSUP; 625*8329232eSGordon Ross goto errout; 626*8329232eSGordon Ross } 627*8329232eSGordon Ross 628*8329232eSGordon Ross /* 629*8329232eSGordon Ross * uap->flags and vfs_optionisset() should agree. 630*8329232eSGordon Ross */ 631*8329232eSGordon Ross if (vfs_optionisset_nolock(&mnt_mntopts, MNTOPT_RO, NULL)) { 632*8329232eSGordon Ross uap->flags |= MS_RDONLY; 633*8329232eSGordon Ross } 634*8329232eSGordon Ross if (vfs_optionisset_nolock(&mnt_mntopts, MNTOPT_NOSUID, NULL)) { 635*8329232eSGordon Ross uap->flags |= MS_NOSUID; 636*8329232eSGordon Ross } 637*8329232eSGordon Ross // nbmand ... 638*8329232eSGordon Ross 639*8329232eSGordon Ross /* 640*8329232eSGordon Ross * If we are splicing the fs into the namespace, 641*8329232eSGordon Ross * perform mount point checks... 642*8329232eSGordon Ross * (always splice=0 here) 643*8329232eSGordon Ross */ 644*8329232eSGordon Ross 645*8329232eSGordon Ross if ((uap->flags & (MS_DATA | MS_OPTIONSTR)) == 0) { 646*8329232eSGordon Ross uap->dataptr = NULL; 647*8329232eSGordon Ross uap->datalen = 0; 648*8329232eSGordon Ross } 649*8329232eSGordon Ross 650*8329232eSGordon Ross /* 651*8329232eSGordon Ross * If this is a remount, ... (never here) 652*8329232eSGordon Ross */ 653*8329232eSGordon Ross vfsp = vfs_alloc(KM_SLEEP); 654*8329232eSGordon Ross VFS_INIT(vfsp, vfsops, NULL); 655*8329232eSGordon Ross 656*8329232eSGordon Ross VFS_HOLD(vfsp); 657*8329232eSGordon Ross 658*8329232eSGordon Ross // lofi_add(fsname, vfsp, &mnt_mntopts, uap) 659*8329232eSGordon Ross 660*8329232eSGordon Ross /* 661*8329232eSGordon Ross * PRIV_SYS_MOUNT doesn't mean you can become root. 662*8329232eSGordon Ross */ 663*8329232eSGordon Ross uap->flags |= MS_NOSUID; 664*8329232eSGordon Ross vfs_setmntopt_nolock(&mnt_mntopts, MNTOPT_NOSUID, NULL, 0, 0); 665*8329232eSGordon Ross 666*8329232eSGordon Ross /* 667*8329232eSGordon Ross * The vfs_reflock... 668*8329232eSGordon Ross */ 669*8329232eSGordon Ross 670*8329232eSGordon Ross /* 671*8329232eSGordon Ross * Lock the vfs... 672*8329232eSGordon Ross */ 673*8329232eSGordon Ross if ((error = vfs_lock(vfsp)) != 0) { 674*8329232eSGordon Ross vfs_free(vfsp); 675*8329232eSGordon Ross vfsp = NULL; 676*8329232eSGordon Ross goto errout; 677*8329232eSGordon Ross } 678*8329232eSGordon Ross 679*8329232eSGordon Ross /* 680*8329232eSGordon Ross * Add device to mount in progress table... 681*8329232eSGordon Ross */ 682*8329232eSGordon Ross /* 683*8329232eSGordon Ross * Invalidate cached entry for the mount point. 684*8329232eSGordon Ross */ 685*8329232eSGordon Ross 686*8329232eSGordon Ross /* 687*8329232eSGordon Ross * If have an option string but the filesystem doesn't supply a 688*8329232eSGordon Ross * prototype options table, create a table... 689*8329232eSGordon Ross */ 690*8329232eSGordon Ross 691*8329232eSGordon Ross /* 692*8329232eSGordon Ross * Serialize with zone state transitions... 693*8329232eSGordon Ross */ 694*8329232eSGordon Ross 695*8329232eSGordon Ross // mount_in_progress(zone); 696*8329232eSGordon Ross 697*8329232eSGordon Ross /* 698*8329232eSGordon Ross * Instantiate (or reinstantiate) the file system... 699*8329232eSGordon Ross */ 700*8329232eSGordon Ross vfs_swapopttbl(&mnt_mntopts, &vfsp->vfs_mntopts); 701*8329232eSGordon Ross 702*8329232eSGordon Ross vfs_setresource(vfsp, uap->spec, 0); 703*8329232eSGordon Ross vfs_setmntpoint(vfsp, uap->dir, 0); 704*8329232eSGordon Ross 705*8329232eSGordon Ross /* 706*8329232eSGordon Ross * going to mount on this vnode, so notify. 707*8329232eSGordon Ross */ 708*8329232eSGordon Ross // vnevent_mountedover(vp, NULL); 709*8329232eSGordon Ross error = VFS_MOUNT(vfsp, vp, uap, credp); 710*8329232eSGordon Ross 711*8329232eSGordon Ross if (uap->flags & MS_RDONLY) 712*8329232eSGordon Ross vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0); 713*8329232eSGordon Ross if (uap->flags & MS_NOSUID) 714*8329232eSGordon Ross vfs_setmntopt(vfsp, MNTOPT_NOSUID, NULL, 0); 715*8329232eSGordon Ross if (uap->flags & MS_GLOBAL) 716*8329232eSGordon Ross vfs_setmntopt(vfsp, MNTOPT_GLOBAL, NULL, 0); 717*8329232eSGordon Ross 718*8329232eSGordon Ross if (error) { 719*8329232eSGordon Ross // lofi_remove(vfsp); 720*8329232eSGordon Ross 721*8329232eSGordon Ross // (remount == 0) 722*8329232eSGordon Ross vfs_unlock(vfsp); 723*8329232eSGordon Ross // vfs_freemnttab(vfsp); 724*8329232eSGordon Ross vfs_free(vfsp); 725*8329232eSGordon Ross vfsp = NULL; 726*8329232eSGordon Ross } else { 727*8329232eSGordon Ross /* 728*8329232eSGordon Ross * Set the mount time to now 729*8329232eSGordon Ross */ 730*8329232eSGordon Ross // vfsp->vfs_mtime = ddi_get_time(); 731*8329232eSGordon Ross // if (remount) ... 732*8329232eSGordon Ross // else if (splice) vfs_add(vp, vfsp, flags) 733*8329232eSGordon Ross // else VFS_HOLD(vfsp); 734*8329232eSGordon Ross 735*8329232eSGordon Ross /* 736*8329232eSGordon Ross * Test jig specific: 737*8329232eSGordon Ross * Do sort of like vfs_add for vp=rootdir 738*8329232eSGordon Ross * Already have hold on vp. 739*8329232eSGordon Ross */ 740*8329232eSGordon Ross vfsp->vfs_vnodecovered = vp; 741*8329232eSGordon Ross vfsp->vfs_flag |= (VFS_NOSETUID|VFS_NODEVICES); 742*8329232eSGordon Ross VFS_HOLD(vfsp); 743*8329232eSGordon Ross rootvfs = vfsp; 744*8329232eSGordon Ross 745*8329232eSGordon Ross /* 746*8329232eSGordon Ross * Set flags for global options encountered 747*8329232eSGordon Ross */ 748*8329232eSGordon Ross if (vfs_optionisset(vfsp, MNTOPT_RO, NULL)) 749*8329232eSGordon Ross vfsp->vfs_flag |= VFS_RDONLY; 750*8329232eSGordon Ross else 751*8329232eSGordon Ross vfsp->vfs_flag &= ~VFS_RDONLY; 752*8329232eSGordon Ross if (vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL)) { 753*8329232eSGordon Ross vfsp->vfs_flag |= (VFS_NOSETUID|VFS_NODEVICES); 754*8329232eSGordon Ross } else { 755*8329232eSGordon Ross if (vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL)) 756*8329232eSGordon Ross vfsp->vfs_flag |= VFS_NODEVICES; 757*8329232eSGordon Ross else 758*8329232eSGordon Ross vfsp->vfs_flag &= ~VFS_NODEVICES; 759*8329232eSGordon Ross if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) 760*8329232eSGordon Ross vfsp->vfs_flag |= VFS_NOSETUID; 761*8329232eSGordon Ross else 762*8329232eSGordon Ross vfsp->vfs_flag &= ~VFS_NOSETUID; 763*8329232eSGordon Ross } 764*8329232eSGordon Ross if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) 765*8329232eSGordon Ross vfsp->vfs_flag |= VFS_NBMAND; 766*8329232eSGordon Ross else 767*8329232eSGordon Ross vfsp->vfs_flag &= ~VFS_NBMAND; 768*8329232eSGordon Ross 769*8329232eSGordon Ross if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) 770*8329232eSGordon Ross vfsp->vfs_flag |= VFS_XATTR; 771*8329232eSGordon Ross else 772*8329232eSGordon Ross vfsp->vfs_flag &= ~VFS_XATTR; 773*8329232eSGordon Ross 774*8329232eSGordon Ross if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) 775*8329232eSGordon Ross vfsp->vfs_flag |= VFS_NOEXEC; 776*8329232eSGordon Ross else 777*8329232eSGordon Ross vfsp->vfs_flag &= ~VFS_NOEXEC; 778*8329232eSGordon Ross 779*8329232eSGordon Ross /* 780*8329232eSGordon Ross * Now construct the output option string of options 781*8329232eSGordon Ross * we recognized. 782*8329232eSGordon Ross */ 783*8329232eSGordon Ross if (uap->flags & MS_OPTIONSTR) { 784*8329232eSGordon Ross vfs_list_read_lock(); 785*8329232eSGordon Ross copyout_error = vfs_buildoptionstr( 786*8329232eSGordon Ross &vfsp->vfs_mntopts, inargs, optlen); 787*8329232eSGordon Ross vfs_list_unlock(); 788*8329232eSGordon Ross if (copyout_error == 0 && 789*8329232eSGordon Ross (uap->flags & MS_SYSSPACE) == 0) { 790*8329232eSGordon Ross copyout_error = copyout(inargs, opts, optlen); 791*8329232eSGordon Ross } 792*8329232eSGordon Ross } 793*8329232eSGordon Ross 794*8329232eSGordon Ross /* 795*8329232eSGordon Ross * If this isn't a remount, set up the vopstats... 796*8329232eSGordon Ross */ 797*8329232eSGordon Ross if (vswp->vsw_flag & VSW_XID) 798*8329232eSGordon Ross vfsp->vfs_flag |= VFS_XID; 799*8329232eSGordon Ross 800*8329232eSGordon Ross vfs_unlock(vfsp); 801*8329232eSGordon Ross 802*8329232eSGordon Ross /* 803*8329232eSGordon Ross * Test jig specicific: 804*8329232eSGordon Ross * Replace rootdir with the mounted root. 805*8329232eSGordon Ross */ 806*8329232eSGordon Ross error = VFS_ROOT(vfsp, &rootdir); 807*8329232eSGordon Ross if (error != 0) { 808*8329232eSGordon Ross panic("fake_domount, get root %d\n", error); 809*8329232eSGordon Ross } 810*8329232eSGordon Ross } 811*8329232eSGordon Ross // mount_completed(zone); 812*8329232eSGordon Ross // zone_rele(zone); 813*8329232eSGordon Ross 814*8329232eSGordon Ross // if (splice) 815*8329232eSGordon Ross // vn_vfsunlock(vp); 816*8329232eSGordon Ross 817*8329232eSGordon Ross if ((error == 0) && (copyout_error == 0)) { 818*8329232eSGordon Ross /* get_vskstat_anchor() */ 819*8329232eSGordon Ross /* Return vfsp to caller. */ 820*8329232eSGordon Ross *vfspp = vfsp; 821*8329232eSGordon Ross } 822*8329232eSGordon Ross errout: 823*8329232eSGordon Ross vfs_freeopttbl(&mnt_mntopts); 824*8329232eSGordon Ross /* resource, mountpt not allocated */ 825*8329232eSGordon Ross /* no addmip, delmip */ 826*8329232eSGordon Ross ASSERT(vswp != NULL); 827*8329232eSGordon Ross vfs_unrefvfssw(vswp); 828*8329232eSGordon Ross if (inargs != opts) 829*8329232eSGordon Ross kmem_free(inargs, MAX_MNTOPT_STR); 830*8329232eSGordon Ross if (copyout_error) { 831*8329232eSGordon Ross if (vfsp != NULL) { 832*8329232eSGordon Ross // lofi_remove(vfsp); 833*8329232eSGordon Ross VFS_RELE(vfsp); 834*8329232eSGordon Ross } 835*8329232eSGordon Ross error = copyout_error; 836*8329232eSGordon Ross } 837*8329232eSGordon Ross return (error); 838*8329232eSGordon Ross } 839*8329232eSGordon Ross 840*8329232eSGordon Ross 841*8329232eSGordon Ross static void 842*8329232eSGordon Ross vfs_setpath( 843*8329232eSGordon Ross struct vfs *vfsp, /* vfs being updated */ 844*8329232eSGordon Ross refstr_t **refp, /* Ref-count string to contain the new path */ 845*8329232eSGordon Ross const char *newpath, /* Path to add to refp (above) */ 846*8329232eSGordon Ross uint32_t flag) /* flag */ 847*8329232eSGordon Ross { 848*8329232eSGordon Ross // size_t len; 849*8329232eSGordon Ross refstr_t *ref; 850*8329232eSGordon Ross // char *sp; 851*8329232eSGordon Ross int have_list_lock = 0; 852*8329232eSGordon Ross 853*8329232eSGordon Ross ASSERT(!VFS_ON_LIST(vfsp) || vfs_lock_held(vfsp)); 854*8329232eSGordon Ross 855*8329232eSGordon Ross /* 856*8329232eSGordon Ross * New path must be less than MAXPATHLEN because mntfs 857*8329232eSGordon Ross * will only display up to MAXPATHLEN bytes. This is currently 858*8329232eSGordon Ross * safe, because domount() uses pn_get(), and other callers 859*8329232eSGordon Ross * similarly cap the size to fewer than MAXPATHLEN bytes. 860*8329232eSGordon Ross */ 861*8329232eSGordon Ross 862*8329232eSGordon Ross ASSERT(strlen(newpath) < MAXPATHLEN); 863*8329232eSGordon Ross 864*8329232eSGordon Ross /* mntfs requires consistency while vfs list lock is held */ 865*8329232eSGordon Ross 866*8329232eSGordon Ross if (VFS_ON_LIST(vfsp)) { 867*8329232eSGordon Ross have_list_lock = 1; 868*8329232eSGordon Ross vfs_list_lock(); 869*8329232eSGordon Ross } 870*8329232eSGordon Ross 871*8329232eSGordon Ross if (*refp != NULL) 872*8329232eSGordon Ross refstr_rele(*refp); 873*8329232eSGordon Ross 874*8329232eSGordon Ross /* 875*8329232eSGordon Ross * If we are in a non-global zone... (do something else) 876*8329232eSGordon Ross */ 877*8329232eSGordon Ross ref = refstr_alloc(newpath); 878*8329232eSGordon Ross *refp = ref; 879*8329232eSGordon Ross 880*8329232eSGordon Ross if (have_list_lock) { 881*8329232eSGordon Ross vfs_mnttab_modtimeupd(); 882*8329232eSGordon Ross vfs_list_unlock(); 883*8329232eSGordon Ross } 884*8329232eSGordon Ross } 885*8329232eSGordon Ross 886*8329232eSGordon Ross /* 887*8329232eSGordon Ross * Record a mounted resource name in a vfs structure. 888*8329232eSGordon Ross * If vfsp is already mounted, caller must hold the vfs lock. 889*8329232eSGordon Ross */ 890*8329232eSGordon Ross void 891*8329232eSGordon Ross vfs_setresource(struct vfs *vfsp, const char *resource, uint32_t flag) 892*8329232eSGordon Ross { 893*8329232eSGordon Ross if (resource == NULL || resource[0] == '\0') 894*8329232eSGordon Ross resource = VFS_NORESOURCE; 895*8329232eSGordon Ross vfs_setpath(vfsp, &vfsp->vfs_resource, resource, flag); 896*8329232eSGordon Ross } 897*8329232eSGordon Ross 898*8329232eSGordon Ross /* 899*8329232eSGordon Ross * Record a mount point name in a vfs structure. 900*8329232eSGordon Ross * If vfsp is already mounted, caller must hold the vfs lock. 901*8329232eSGordon Ross */ 902*8329232eSGordon Ross void 903*8329232eSGordon Ross vfs_setmntpoint(struct vfs *vfsp, const char *mntpt, uint32_t flag) 904*8329232eSGordon Ross { 905*8329232eSGordon Ross if (mntpt == NULL || mntpt[0] == '\0') 906*8329232eSGordon Ross mntpt = VFS_NOMNTPT; 907*8329232eSGordon Ross vfs_setpath(vfsp, &vfsp->vfs_mntpt, mntpt, flag); 908*8329232eSGordon Ross } 909*8329232eSGordon Ross 910*8329232eSGordon Ross /* Returns the vfs_resource. Caller must call refstr_rele() when finished. */ 911*8329232eSGordon Ross 912*8329232eSGordon Ross refstr_t * 913*8329232eSGordon Ross vfs_getresource(const struct vfs *vfsp) 914*8329232eSGordon Ross { 915*8329232eSGordon Ross refstr_t *resource; 916*8329232eSGordon Ross 917*8329232eSGordon Ross vfs_list_read_lock(); 918*8329232eSGordon Ross resource = vfsp->vfs_resource; 919*8329232eSGordon Ross refstr_hold(resource); 920*8329232eSGordon Ross vfs_list_unlock(); 921*8329232eSGordon Ross 922*8329232eSGordon Ross return (resource); 923*8329232eSGordon Ross } 924*8329232eSGordon Ross 925*8329232eSGordon Ross /* Returns the vfs_mntpt. Caller must call refstr_rele() when finished. */ 926*8329232eSGordon Ross 927*8329232eSGordon Ross refstr_t * 928*8329232eSGordon Ross vfs_getmntpoint(const struct vfs *vfsp) 929*8329232eSGordon Ross { 930*8329232eSGordon Ross refstr_t *mntpt; 931*8329232eSGordon Ross 932*8329232eSGordon Ross vfs_list_read_lock(); 933*8329232eSGordon Ross mntpt = vfsp->vfs_mntpt; 934*8329232eSGordon Ross refstr_hold(mntpt); 935*8329232eSGordon Ross vfs_list_unlock(); 936*8329232eSGordon Ross 937*8329232eSGordon Ross return (mntpt); 938*8329232eSGordon Ross } 939*8329232eSGordon Ross 940*8329232eSGordon Ross // vfs_createopttbl_extend 941*8329232eSGordon Ross // vfs_createopttbl 942*8329232eSGordon Ross 943*8329232eSGordon Ross /* 944*8329232eSGordon Ross * Swap two mount options tables 945*8329232eSGordon Ross */ 946*8329232eSGordon Ross static void 947*8329232eSGordon Ross vfs_swapopttbl_nolock(mntopts_t *optbl1, mntopts_t *optbl2) 948*8329232eSGordon Ross { 949*8329232eSGordon Ross uint_t tmpcnt; 950*8329232eSGordon Ross mntopt_t *tmplist; 951*8329232eSGordon Ross 952*8329232eSGordon Ross tmpcnt = optbl2->mo_count; 953*8329232eSGordon Ross tmplist = optbl2->mo_list; 954*8329232eSGordon Ross optbl2->mo_count = optbl1->mo_count; 955*8329232eSGordon Ross optbl2->mo_list = optbl1->mo_list; 956*8329232eSGordon Ross optbl1->mo_count = tmpcnt; 957*8329232eSGordon Ross optbl1->mo_list = tmplist; 958*8329232eSGordon Ross } 959*8329232eSGordon Ross 960*8329232eSGordon Ross static void 961*8329232eSGordon Ross vfs_swapopttbl(mntopts_t *optbl1, mntopts_t *optbl2) 962*8329232eSGordon Ross { 963*8329232eSGordon Ross vfs_list_lock(); 964*8329232eSGordon Ross vfs_swapopttbl_nolock(optbl1, optbl2); 965*8329232eSGordon Ross vfs_mnttab_modtimeupd(); 966*8329232eSGordon Ross vfs_list_unlock(); 967*8329232eSGordon Ross } 968*8329232eSGordon Ross 969*8329232eSGordon Ross static char ** 970*8329232eSGordon Ross vfs_copycancelopt_extend(char **const moc, int extend) 971*8329232eSGordon Ross { 972*8329232eSGordon Ross int i = 0; 973*8329232eSGordon Ross int j; 974*8329232eSGordon Ross char **result; 975*8329232eSGordon Ross 976*8329232eSGordon Ross if (moc != NULL) { 977*8329232eSGordon Ross for (; moc[i] != NULL; i++) 978*8329232eSGordon Ross /* count number of options to cancel */; 979*8329232eSGordon Ross } 980*8329232eSGordon Ross 981*8329232eSGordon Ross if (i + extend == 0) 982*8329232eSGordon Ross return (NULL); 983*8329232eSGordon Ross 984*8329232eSGordon Ross result = kmem_alloc((i + extend + 1) * sizeof (char *), KM_SLEEP); 985*8329232eSGordon Ross 986*8329232eSGordon Ross for (j = 0; j < i; j++) { 987*8329232eSGordon Ross result[j] = kmem_alloc(strlen(moc[j]) + 1, KM_SLEEP); 988*8329232eSGordon Ross (void) strcpy(result[j], moc[j]); 989*8329232eSGordon Ross } 990*8329232eSGordon Ross for (; j <= i + extend; j++) 991*8329232eSGordon Ross result[j] = NULL; 992*8329232eSGordon Ross 993*8329232eSGordon Ross return (result); 994*8329232eSGordon Ross } 995*8329232eSGordon Ross 996*8329232eSGordon Ross static void 997*8329232eSGordon Ross vfs_copyopt(const mntopt_t *s, mntopt_t *d) 998*8329232eSGordon Ross { 999*8329232eSGordon Ross char *sp, *dp; 1000*8329232eSGordon Ross 1001*8329232eSGordon Ross d->mo_flags = s->mo_flags; 1002*8329232eSGordon Ross d->mo_data = s->mo_data; 1003*8329232eSGordon Ross sp = s->mo_name; 1004*8329232eSGordon Ross if (sp != NULL) { 1005*8329232eSGordon Ross dp = kmem_alloc(strlen(sp) + 1, KM_SLEEP); 1006*8329232eSGordon Ross (void) strcpy(dp, sp); 1007*8329232eSGordon Ross d->mo_name = dp; 1008*8329232eSGordon Ross } else { 1009*8329232eSGordon Ross d->mo_name = NULL; /* should never happen */ 1010*8329232eSGordon Ross } 1011*8329232eSGordon Ross 1012*8329232eSGordon Ross d->mo_cancel = vfs_copycancelopt_extend(s->mo_cancel, 0); 1013*8329232eSGordon Ross 1014*8329232eSGordon Ross sp = s->mo_arg; 1015*8329232eSGordon Ross if (sp != NULL) { 1016*8329232eSGordon Ross dp = kmem_alloc(strlen(sp) + 1, KM_SLEEP); 1017*8329232eSGordon Ross (void) strcpy(dp, sp); 1018*8329232eSGordon Ross d->mo_arg = dp; 1019*8329232eSGordon Ross } else { 1020*8329232eSGordon Ross d->mo_arg = NULL; 1021*8329232eSGordon Ross } 1022*8329232eSGordon Ross } 1023*8329232eSGordon Ross 1024*8329232eSGordon Ross // vfs_copyopttbl_extend 1025*8329232eSGordon Ross // vfs_copyopttbl 1026*8329232eSGordon Ross 1027*8329232eSGordon Ross /* 1028*8329232eSGordon Ross * Copy a mount options table, possibly allocating some spare 1029*8329232eSGordon Ross * slots at the end. It is permissible to copy_extend the NULL table. 1030*8329232eSGordon Ross */ 1031*8329232eSGordon Ross static void 1032*8329232eSGordon Ross vfs_copyopttbl_extend(const mntopts_t *smo, mntopts_t *dmo, int extra) 1033*8329232eSGordon Ross { 1034*8329232eSGordon Ross uint_t i, count; 1035*8329232eSGordon Ross mntopt_t *motbl; 1036*8329232eSGordon Ross 1037*8329232eSGordon Ross /* 1038*8329232eSGordon Ross * Clear out any existing stuff in the options table being initialized 1039*8329232eSGordon Ross */ 1040*8329232eSGordon Ross vfs_freeopttbl(dmo); 1041*8329232eSGordon Ross count = (smo == NULL) ? 0 : smo->mo_count; 1042*8329232eSGordon Ross if ((count + extra) == 0) /* nothing to do */ 1043*8329232eSGordon Ross return; 1044*8329232eSGordon Ross dmo->mo_count = count + extra; 1045*8329232eSGordon Ross motbl = kmem_zalloc((count + extra) * sizeof (mntopt_t), KM_SLEEP); 1046*8329232eSGordon Ross dmo->mo_list = motbl; 1047*8329232eSGordon Ross for (i = 0; i < count; i++) { 1048*8329232eSGordon Ross vfs_copyopt(&smo->mo_list[i], &motbl[i]); 1049*8329232eSGordon Ross } 1050*8329232eSGordon Ross for (i = count; i < count + extra; i++) { 1051*8329232eSGordon Ross motbl[i].mo_flags = MO_EMPTY; 1052*8329232eSGordon Ross } 1053*8329232eSGordon Ross } 1054*8329232eSGordon Ross 1055*8329232eSGordon Ross /* 1056*8329232eSGordon Ross * Copy a mount options table. 1057*8329232eSGordon Ross * 1058*8329232eSGordon Ross * This function is *not* for general use by filesystems. 1059*8329232eSGordon Ross * 1060*8329232eSGordon Ross * Note: caller is responsible for locking the vfs list, if needed, 1061*8329232eSGordon Ross * to protect smo and dmo. 1062*8329232eSGordon Ross */ 1063*8329232eSGordon Ross void 1064*8329232eSGordon Ross vfs_copyopttbl(const mntopts_t *smo, mntopts_t *dmo) 1065*8329232eSGordon Ross { 1066*8329232eSGordon Ross vfs_copyopttbl_extend(smo, dmo, 0); 1067*8329232eSGordon Ross } 1068*8329232eSGordon Ross 1069*8329232eSGordon Ross static char ** 1070*8329232eSGordon Ross vfs_mergecancelopts(const mntopt_t *mop1, const mntopt_t *mop2) 1071*8329232eSGordon Ross { 1072*8329232eSGordon Ross int c1 = 0; 1073*8329232eSGordon Ross int c2 = 0; 1074*8329232eSGordon Ross char **result; 1075*8329232eSGordon Ross char **sp1, **sp2, **dp; 1076*8329232eSGordon Ross 1077*8329232eSGordon Ross /* 1078*8329232eSGordon Ross * First we count both lists of cancel options. 1079*8329232eSGordon Ross * If either is NULL or has no elements, we return a copy of 1080*8329232eSGordon Ross * the other. 1081*8329232eSGordon Ross */ 1082*8329232eSGordon Ross if (mop1->mo_cancel != NULL) { 1083*8329232eSGordon Ross for (; mop1->mo_cancel[c1] != NULL; c1++) 1084*8329232eSGordon Ross /* count cancel options in mop1 */; 1085*8329232eSGordon Ross } 1086*8329232eSGordon Ross 1087*8329232eSGordon Ross if (c1 == 0) 1088*8329232eSGordon Ross return (vfs_copycancelopt_extend(mop2->mo_cancel, 0)); 1089*8329232eSGordon Ross 1090*8329232eSGordon Ross if (mop2->mo_cancel != NULL) { 1091*8329232eSGordon Ross for (; mop2->mo_cancel[c2] != NULL; c2++) 1092*8329232eSGordon Ross /* count cancel options in mop2 */; 1093*8329232eSGordon Ross } 1094*8329232eSGordon Ross 1095*8329232eSGordon Ross result = vfs_copycancelopt_extend(mop1->mo_cancel, c2); 1096*8329232eSGordon Ross 1097*8329232eSGordon Ross if (c2 == 0) 1098*8329232eSGordon Ross return (result); 1099*8329232eSGordon Ross 1100*8329232eSGordon Ross /* 1101*8329232eSGordon Ross * When we get here, we've got two sets of cancel options; 1102*8329232eSGordon Ross * we need to merge the two sets. We know that the result 1103*8329232eSGordon Ross * array has "c1+c2+1" entries and in the end we might shrink 1104*8329232eSGordon Ross * it. 1105*8329232eSGordon Ross * Result now has a copy of the c1 entries from mop1; we'll 1106*8329232eSGordon Ross * now lookup all the entries of mop2 in mop1 and copy it if 1107*8329232eSGordon Ross * it is unique. 1108*8329232eSGordon Ross * This operation is O(n^2) but it's only called once per 1109*8329232eSGordon Ross * filesystem per duplicate option. This is a situation 1110*8329232eSGordon Ross * which doesn't arise with the filesystems in ON and 1111*8329232eSGordon Ross * n is generally 1. 1112*8329232eSGordon Ross */ 1113*8329232eSGordon Ross 1114*8329232eSGordon Ross dp = &result[c1]; 1115*8329232eSGordon Ross for (sp2 = mop2->mo_cancel; *sp2 != NULL; sp2++) { 1116*8329232eSGordon Ross for (sp1 = mop1->mo_cancel; *sp1 != NULL; sp1++) { 1117*8329232eSGordon Ross if (strcmp(*sp1, *sp2) == 0) 1118*8329232eSGordon Ross break; 1119*8329232eSGordon Ross } 1120*8329232eSGordon Ross if (*sp1 == NULL) { 1121*8329232eSGordon Ross /* 1122*8329232eSGordon Ross * Option *sp2 not found in mop1, so copy it. 1123*8329232eSGordon Ross * The calls to vfs_copycancelopt_extend() 1124*8329232eSGordon Ross * guarantee that there's enough room. 1125*8329232eSGordon Ross */ 1126*8329232eSGordon Ross *dp = kmem_alloc(strlen(*sp2) + 1, KM_SLEEP); 1127*8329232eSGordon Ross (void) strcpy(*dp++, *sp2); 1128*8329232eSGordon Ross } 1129*8329232eSGordon Ross } 1130*8329232eSGordon Ross if (dp != &result[c1+c2]) { 1131*8329232eSGordon Ross size_t bytes = (dp - result + 1) * sizeof (char *); 1132*8329232eSGordon Ross char **nres = kmem_alloc(bytes, KM_SLEEP); 1133*8329232eSGordon Ross 1134*8329232eSGordon Ross bcopy(result, nres, bytes); 1135*8329232eSGordon Ross kmem_free(result, (c1 + c2 + 1) * sizeof (char *)); 1136*8329232eSGordon Ross result = nres; 1137*8329232eSGordon Ross } 1138*8329232eSGordon Ross return (result); 1139*8329232eSGordon Ross } 1140*8329232eSGordon Ross 1141*8329232eSGordon Ross /* 1142*8329232eSGordon Ross * Merge two mount option tables (outer and inner) into one. This is very 1143*8329232eSGordon Ross * similar to "merging" global variables and automatic variables in C. 1144*8329232eSGordon Ross * 1145*8329232eSGordon Ross * This isn't (and doesn't have to be) fast. 1146*8329232eSGordon Ross * 1147*8329232eSGordon Ross * This function is *not* for general use by filesystems. 1148*8329232eSGordon Ross * 1149*8329232eSGordon Ross * Note: caller is responsible for locking the vfs list, if needed, 1150*8329232eSGordon Ross * to protect omo, imo & dmo. 1151*8329232eSGordon Ross */ 1152*8329232eSGordon Ross void 1153*8329232eSGordon Ross vfs_mergeopttbl(const mntopts_t *omo, const mntopts_t *imo, mntopts_t *dmo) 1154*8329232eSGordon Ross { 1155*8329232eSGordon Ross uint_t i, count; 1156*8329232eSGordon Ross mntopt_t *mop, *motbl; 1157*8329232eSGordon Ross uint_t freeidx; 1158*8329232eSGordon Ross 1159*8329232eSGordon Ross /* 1160*8329232eSGordon Ross * First determine how much space we need to allocate. 1161*8329232eSGordon Ross */ 1162*8329232eSGordon Ross count = omo->mo_count; 1163*8329232eSGordon Ross for (i = 0; i < imo->mo_count; i++) { 1164*8329232eSGordon Ross if (imo->mo_list[i].mo_flags & MO_EMPTY) 1165*8329232eSGordon Ross continue; 1166*8329232eSGordon Ross if (vfs_hasopt(omo, imo->mo_list[i].mo_name) == NULL) 1167*8329232eSGordon Ross count++; 1168*8329232eSGordon Ross } 1169*8329232eSGordon Ross ASSERT(count >= omo->mo_count && 1170*8329232eSGordon Ross count <= omo->mo_count + imo->mo_count); 1171*8329232eSGordon Ross motbl = kmem_alloc(count * sizeof (mntopt_t), KM_SLEEP); 1172*8329232eSGordon Ross for (i = 0; i < omo->mo_count; i++) 1173*8329232eSGordon Ross vfs_copyopt(&omo->mo_list[i], &motbl[i]); 1174*8329232eSGordon Ross freeidx = omo->mo_count; 1175*8329232eSGordon Ross for (i = 0; i < imo->mo_count; i++) { 1176*8329232eSGordon Ross if (imo->mo_list[i].mo_flags & MO_EMPTY) 1177*8329232eSGordon Ross continue; 1178*8329232eSGordon Ross if ((mop = vfs_hasopt(omo, imo->mo_list[i].mo_name)) != NULL) { 1179*8329232eSGordon Ross char **newcanp; 1180*8329232eSGordon Ross uint_t index = mop - omo->mo_list; 1181*8329232eSGordon Ross 1182*8329232eSGordon Ross newcanp = vfs_mergecancelopts(mop, &motbl[index]); 1183*8329232eSGordon Ross 1184*8329232eSGordon Ross vfs_freeopt(&motbl[index]); 1185*8329232eSGordon Ross vfs_copyopt(&imo->mo_list[i], &motbl[index]); 1186*8329232eSGordon Ross 1187*8329232eSGordon Ross vfs_freecancelopt(motbl[index].mo_cancel); 1188*8329232eSGordon Ross motbl[index].mo_cancel = newcanp; 1189*8329232eSGordon Ross } else { 1190*8329232eSGordon Ross /* 1191*8329232eSGordon Ross * If it's a new option, just copy it over to the first 1192*8329232eSGordon Ross * free location. 1193*8329232eSGordon Ross */ 1194*8329232eSGordon Ross vfs_copyopt(&imo->mo_list[i], &motbl[freeidx++]); 1195*8329232eSGordon Ross } 1196*8329232eSGordon Ross } 1197*8329232eSGordon Ross dmo->mo_count = count; 1198*8329232eSGordon Ross dmo->mo_list = motbl; 1199*8329232eSGordon Ross } 1200*8329232eSGordon Ross 1201*8329232eSGordon Ross /* 1202*8329232eSGordon Ross * Functions to set and clear mount options in a mount options table. 1203*8329232eSGordon Ross */ 1204*8329232eSGordon Ross 1205*8329232eSGordon Ross /* 1206*8329232eSGordon Ross * Clear a mount option, if it exists. 1207*8329232eSGordon Ross * 1208*8329232eSGordon Ross * The update_mnttab arg indicates whether mops is part of a vfs that is on 1209*8329232eSGordon Ross * the vfs list. 1210*8329232eSGordon Ross */ 1211*8329232eSGordon Ross static void 1212*8329232eSGordon Ross vfs_clearmntopt_nolock(mntopts_t *mops, const char *opt, int update_mnttab) 1213*8329232eSGordon Ross { 1214*8329232eSGordon Ross struct mntopt *mop; 1215*8329232eSGordon Ross uint_t i, count; 1216*8329232eSGordon Ross 1217*8329232eSGordon Ross ASSERT(!update_mnttab || RW_WRITE_HELD(&vfslist)); 1218*8329232eSGordon Ross 1219*8329232eSGordon Ross count = mops->mo_count; 1220*8329232eSGordon Ross for (i = 0; i < count; i++) { 1221*8329232eSGordon Ross mop = &mops->mo_list[i]; 1222*8329232eSGordon Ross 1223*8329232eSGordon Ross if (mop->mo_flags & MO_EMPTY) 1224*8329232eSGordon Ross continue; 1225*8329232eSGordon Ross if (strcmp(opt, mop->mo_name)) 1226*8329232eSGordon Ross continue; 1227*8329232eSGordon Ross mop->mo_flags &= ~MO_SET; 1228*8329232eSGordon Ross if (mop->mo_arg != NULL) { 1229*8329232eSGordon Ross kmem_free(mop->mo_arg, strlen(mop->mo_arg) + 1); 1230*8329232eSGordon Ross } 1231*8329232eSGordon Ross mop->mo_arg = NULL; 1232*8329232eSGordon Ross if (update_mnttab) 1233*8329232eSGordon Ross vfs_mnttab_modtimeupd(); 1234*8329232eSGordon Ross break; 1235*8329232eSGordon Ross } 1236*8329232eSGordon Ross } 1237*8329232eSGordon Ross 1238*8329232eSGordon Ross void 1239*8329232eSGordon Ross vfs_clearmntopt(struct vfs *vfsp, const char *opt) 1240*8329232eSGordon Ross { 1241*8329232eSGordon Ross int gotlock = 0; 1242*8329232eSGordon Ross 1243*8329232eSGordon Ross if (VFS_ON_LIST(vfsp)) { 1244*8329232eSGordon Ross gotlock = 1; 1245*8329232eSGordon Ross vfs_list_lock(); 1246*8329232eSGordon Ross } 1247*8329232eSGordon Ross vfs_clearmntopt_nolock(&vfsp->vfs_mntopts, opt, gotlock); 1248*8329232eSGordon Ross if (gotlock) 1249*8329232eSGordon Ross vfs_list_unlock(); 1250*8329232eSGordon Ross } 1251*8329232eSGordon Ross 1252*8329232eSGordon Ross 1253*8329232eSGordon Ross /* 1254*8329232eSGordon Ross * Set a mount option on... 1255*8329232eSGordon Ross */ 1256*8329232eSGordon Ross static void 1257*8329232eSGordon Ross vfs_setmntopt_nolock(mntopts_t *mops, const char *opt, 1258*8329232eSGordon Ross const char *arg, int flags, int update_mnttab) 1259*8329232eSGordon Ross { 1260*8329232eSGordon Ross mntopt_t *mop; 1261*8329232eSGordon Ross uint_t i, count; 1262*8329232eSGordon Ross char *sp; 1263*8329232eSGordon Ross 1264*8329232eSGordon Ross ASSERT(!update_mnttab || RW_WRITE_HELD(&vfslist)); 1265*8329232eSGordon Ross 1266*8329232eSGordon Ross if (flags & VFS_CREATEOPT) { 1267*8329232eSGordon Ross if (vfs_hasopt(mops, opt) != NULL) { 1268*8329232eSGordon Ross flags &= ~VFS_CREATEOPT; 1269*8329232eSGordon Ross } 1270*8329232eSGordon Ross } 1271*8329232eSGordon Ross count = mops->mo_count; 1272*8329232eSGordon Ross for (i = 0; i < count; i++) { 1273*8329232eSGordon Ross mop = &mops->mo_list[i]; 1274*8329232eSGordon Ross 1275*8329232eSGordon Ross if (mop->mo_flags & MO_EMPTY) { 1276*8329232eSGordon Ross if ((flags & VFS_CREATEOPT) == 0) 1277*8329232eSGordon Ross continue; 1278*8329232eSGordon Ross sp = kmem_alloc(strlen(opt) + 1, KM_SLEEP); 1279*8329232eSGordon Ross (void) strcpy(sp, opt); 1280*8329232eSGordon Ross mop->mo_name = sp; 1281*8329232eSGordon Ross if (arg != NULL) 1282*8329232eSGordon Ross mop->mo_flags = MO_HASVALUE; 1283*8329232eSGordon Ross else 1284*8329232eSGordon Ross mop->mo_flags = 0; 1285*8329232eSGordon Ross } else if (strcmp(opt, mop->mo_name)) { 1286*8329232eSGordon Ross continue; 1287*8329232eSGordon Ross } 1288*8329232eSGordon Ross if ((mop->mo_flags & MO_IGNORE) && (flags & VFS_NOFORCEOPT)) 1289*8329232eSGordon Ross break; 1290*8329232eSGordon Ross if (arg != NULL && (mop->mo_flags & MO_HASVALUE) != 0) { 1291*8329232eSGordon Ross sp = kmem_alloc(strlen(arg) + 1, KM_SLEEP); 1292*8329232eSGordon Ross (void) strcpy(sp, arg); 1293*8329232eSGordon Ross } else { 1294*8329232eSGordon Ross sp = NULL; 1295*8329232eSGordon Ross } 1296*8329232eSGordon Ross if (mop->mo_arg != NULL) 1297*8329232eSGordon Ross kmem_free(mop->mo_arg, strlen(mop->mo_arg) + 1); 1298*8329232eSGordon Ross mop->mo_arg = sp; 1299*8329232eSGordon Ross if (flags & VFS_DISPLAY) 1300*8329232eSGordon Ross mop->mo_flags &= ~MO_NODISPLAY; 1301*8329232eSGordon Ross if (flags & VFS_NODISPLAY) 1302*8329232eSGordon Ross mop->mo_flags |= MO_NODISPLAY; 1303*8329232eSGordon Ross mop->mo_flags |= MO_SET; 1304*8329232eSGordon Ross if (mop->mo_cancel != NULL) { 1305*8329232eSGordon Ross char **cp; 1306*8329232eSGordon Ross 1307*8329232eSGordon Ross for (cp = mop->mo_cancel; *cp != NULL; cp++) 1308*8329232eSGordon Ross vfs_clearmntopt_nolock(mops, *cp, 0); 1309*8329232eSGordon Ross } 1310*8329232eSGordon Ross if (update_mnttab) 1311*8329232eSGordon Ross vfs_mnttab_modtimeupd(); 1312*8329232eSGordon Ross break; 1313*8329232eSGordon Ross } 1314*8329232eSGordon Ross } 1315*8329232eSGordon Ross 1316*8329232eSGordon Ross void 1317*8329232eSGordon Ross vfs_setmntopt(struct vfs *vfsp, const char *opt, const char *arg, int flags) 1318*8329232eSGordon Ross { 1319*8329232eSGordon Ross int gotlock = 0; 1320*8329232eSGordon Ross 1321*8329232eSGordon Ross if (VFS_ON_LIST(vfsp)) { 1322*8329232eSGordon Ross gotlock = 1; 1323*8329232eSGordon Ross vfs_list_lock(); 1324*8329232eSGordon Ross } 1325*8329232eSGordon Ross vfs_setmntopt_nolock(&vfsp->vfs_mntopts, opt, arg, flags, gotlock); 1326*8329232eSGordon Ross if (gotlock) 1327*8329232eSGordon Ross vfs_list_unlock(); 1328*8329232eSGordon Ross } 1329*8329232eSGordon Ross 1330*8329232eSGordon Ross // vfs_addtag 1331*8329232eSGordon Ross // vfs_settag 1332*8329232eSGordon Ross // vfs_clrtag 1333*8329232eSGordon Ross 1334*8329232eSGordon Ross /* 1335*8329232eSGordon Ross * Function to parse an option string and fill in a mount options table. 1336*8329232eSGordon Ross * Unknown options are silently ignored. The input option string is modified 1337*8329232eSGordon Ross * by replacing separators with nulls. If the create flag is set, options 1338*8329232eSGordon Ross * not found in the table are just added on the fly. The table must have 1339*8329232eSGordon Ross * an option slot marked MO_EMPTY to add an option on the fly. 1340*8329232eSGordon Ross * 1341*8329232eSGordon Ross * This function is *not* for general use by filesystems. 1342*8329232eSGordon Ross * 1343*8329232eSGordon Ross * Note: caller is responsible for locking the vfs list, if needed, 1344*8329232eSGordon Ross * to protect mops.. 1345*8329232eSGordon Ross */ 1346*8329232eSGordon Ross void 1347*8329232eSGordon Ross vfs_parsemntopts(mntopts_t *mops, char *osp, int create) 1348*8329232eSGordon Ross { 1349*8329232eSGordon Ross char *s = osp, *p, *nextop, *valp, *cp, *ep = NULL; 1350*8329232eSGordon Ross int setflg = VFS_NOFORCEOPT; 1351*8329232eSGordon Ross 1352*8329232eSGordon Ross if (osp == NULL) 1353*8329232eSGordon Ross return; 1354*8329232eSGordon Ross while (*s != '\0') { 1355*8329232eSGordon Ross p = strchr(s, ','); /* find next option */ 1356*8329232eSGordon Ross if (p == NULL) { 1357*8329232eSGordon Ross cp = NULL; 1358*8329232eSGordon Ross p = s + strlen(s); 1359*8329232eSGordon Ross } else { 1360*8329232eSGordon Ross cp = p; /* save location of comma */ 1361*8329232eSGordon Ross *p++ = '\0'; /* mark end and point to next option */ 1362*8329232eSGordon Ross } 1363*8329232eSGordon Ross nextop = p; 1364*8329232eSGordon Ross p = strchr(s, '='); /* look for value */ 1365*8329232eSGordon Ross if (p == NULL) { 1366*8329232eSGordon Ross valp = NULL; /* no value supplied */ 1367*8329232eSGordon Ross ep = NULL; 1368*8329232eSGordon Ross } else { 1369*8329232eSGordon Ross ep = p; /* save location of equals */ 1370*8329232eSGordon Ross *p++ = '\0'; /* end option and point to value */ 1371*8329232eSGordon Ross valp = p; 1372*8329232eSGordon Ross } 1373*8329232eSGordon Ross /* 1374*8329232eSGordon Ross * set option into options table 1375*8329232eSGordon Ross */ 1376*8329232eSGordon Ross if (create) 1377*8329232eSGordon Ross setflg |= VFS_CREATEOPT; 1378*8329232eSGordon Ross vfs_setmntopt_nolock(mops, s, valp, setflg, 0); 1379*8329232eSGordon Ross if (cp != NULL) 1380*8329232eSGordon Ross *cp = ','; /* restore the comma */ 1381*8329232eSGordon Ross if (valp != NULL) 1382*8329232eSGordon Ross *ep = '='; /* restore the equals */ 1383*8329232eSGordon Ross s = nextop; 1384*8329232eSGordon Ross } 1385*8329232eSGordon Ross } 1386*8329232eSGordon Ross 1387*8329232eSGordon Ross /* 1388*8329232eSGordon Ross * Function to inquire if an option exists in a mount options table. 1389*8329232eSGordon Ross * Returns a pointer to the option if it exists, else NULL. 1390*8329232eSGordon Ross */ 1391*8329232eSGordon Ross struct mntopt * 1392*8329232eSGordon Ross vfs_hasopt(const mntopts_t *mops, const char *opt) 1393*8329232eSGordon Ross { 1394*8329232eSGordon Ross struct mntopt *mop; 1395*8329232eSGordon Ross uint_t i, count; 1396*8329232eSGordon Ross 1397*8329232eSGordon Ross count = mops->mo_count; 1398*8329232eSGordon Ross for (i = 0; i < count; i++) { 1399*8329232eSGordon Ross mop = &mops->mo_list[i]; 1400*8329232eSGordon Ross 1401*8329232eSGordon Ross if (mop->mo_flags & MO_EMPTY) 1402*8329232eSGordon Ross continue; 1403*8329232eSGordon Ross if (strcmp(opt, mop->mo_name) == 0) 1404*8329232eSGordon Ross return (mop); 1405*8329232eSGordon Ross } 1406*8329232eSGordon Ross return (NULL); 1407*8329232eSGordon Ross } 1408*8329232eSGordon Ross 1409*8329232eSGordon Ross /* 1410*8329232eSGordon Ross * Function to inquire if an option is set in a mount options table. 1411*8329232eSGordon Ross * Returns non-zero if set and fills in the arg pointer with a pointer to 1412*8329232eSGordon Ross * the argument string or NULL if there is no argument string. 1413*8329232eSGordon Ross */ 1414*8329232eSGordon Ross static int 1415*8329232eSGordon Ross vfs_optionisset_nolock(const mntopts_t *mops, const char *opt, char **argp) 1416*8329232eSGordon Ross { 1417*8329232eSGordon Ross struct mntopt *mop; 1418*8329232eSGordon Ross uint_t i, count; 1419*8329232eSGordon Ross 1420*8329232eSGordon Ross count = mops->mo_count; 1421*8329232eSGordon Ross for (i = 0; i < count; i++) { 1422*8329232eSGordon Ross mop = &mops->mo_list[i]; 1423*8329232eSGordon Ross 1424*8329232eSGordon Ross if (mop->mo_flags & MO_EMPTY) 1425*8329232eSGordon Ross continue; 1426*8329232eSGordon Ross if (strcmp(opt, mop->mo_name)) 1427*8329232eSGordon Ross continue; 1428*8329232eSGordon Ross if ((mop->mo_flags & MO_SET) == 0) 1429*8329232eSGordon Ross return (0); 1430*8329232eSGordon Ross if (argp != NULL && (mop->mo_flags & MO_HASVALUE) != 0) 1431*8329232eSGordon Ross *argp = mop->mo_arg; 1432*8329232eSGordon Ross return (1); 1433*8329232eSGordon Ross } 1434*8329232eSGordon Ross return (0); 1435*8329232eSGordon Ross } 1436*8329232eSGordon Ross 1437*8329232eSGordon Ross 1438*8329232eSGordon Ross int 1439*8329232eSGordon Ross vfs_optionisset(const struct vfs *vfsp, const char *opt, char **argp) 1440*8329232eSGordon Ross { 1441*8329232eSGordon Ross int ret; 1442*8329232eSGordon Ross 1443*8329232eSGordon Ross vfs_list_read_lock(); 1444*8329232eSGordon Ross ret = vfs_optionisset_nolock(&vfsp->vfs_mntopts, opt, argp); 1445*8329232eSGordon Ross vfs_list_unlock(); 1446*8329232eSGordon Ross return (ret); 1447*8329232eSGordon Ross } 1448*8329232eSGordon Ross 1449*8329232eSGordon Ross 1450*8329232eSGordon Ross /* 1451*8329232eSGordon Ross * Construct a comma separated string of the options set in the given 1452*8329232eSGordon Ross * mount table, return the string in the given buffer. Return non-zero if 1453*8329232eSGordon Ross * the buffer would overflow. 1454*8329232eSGordon Ross * 1455*8329232eSGordon Ross * This function is *not* for general use by filesystems. 1456*8329232eSGordon Ross * 1457*8329232eSGordon Ross * Note: caller is responsible for locking the vfs list, if needed, 1458*8329232eSGordon Ross * to protect mp. 1459*8329232eSGordon Ross */ 1460*8329232eSGordon Ross int 1461*8329232eSGordon Ross vfs_buildoptionstr(const mntopts_t *mp, char *buf, int len) 1462*8329232eSGordon Ross { 1463*8329232eSGordon Ross char *cp; 1464*8329232eSGordon Ross uint_t i; 1465*8329232eSGordon Ross 1466*8329232eSGordon Ross buf[0] = '\0'; 1467*8329232eSGordon Ross cp = buf; 1468*8329232eSGordon Ross for (i = 0; i < mp->mo_count; i++) { 1469*8329232eSGordon Ross struct mntopt *mop; 1470*8329232eSGordon Ross 1471*8329232eSGordon Ross mop = &mp->mo_list[i]; 1472*8329232eSGordon Ross if (mop->mo_flags & MO_SET) { 1473*8329232eSGordon Ross int optlen, comma = 0; 1474*8329232eSGordon Ross 1475*8329232eSGordon Ross if (buf[0] != '\0') 1476*8329232eSGordon Ross comma = 1; 1477*8329232eSGordon Ross optlen = strlen(mop->mo_name); 1478*8329232eSGordon Ross if (strlen(buf) + comma + optlen + 1 > len) 1479*8329232eSGordon Ross goto err; 1480*8329232eSGordon Ross if (comma) 1481*8329232eSGordon Ross *cp++ = ','; 1482*8329232eSGordon Ross (void) strcpy(cp, mop->mo_name); 1483*8329232eSGordon Ross cp += optlen; 1484*8329232eSGordon Ross /* 1485*8329232eSGordon Ross * Append option value if there is one 1486*8329232eSGordon Ross */ 1487*8329232eSGordon Ross if (mop->mo_arg != NULL) { 1488*8329232eSGordon Ross int arglen; 1489*8329232eSGordon Ross 1490*8329232eSGordon Ross arglen = strlen(mop->mo_arg); 1491*8329232eSGordon Ross if (strlen(buf) + arglen + 2 > len) 1492*8329232eSGordon Ross goto err; 1493*8329232eSGordon Ross *cp++ = '='; 1494*8329232eSGordon Ross (void) strcpy(cp, mop->mo_arg); 1495*8329232eSGordon Ross cp += arglen; 1496*8329232eSGordon Ross } 1497*8329232eSGordon Ross } 1498*8329232eSGordon Ross } 1499*8329232eSGordon Ross return (0); 1500*8329232eSGordon Ross err: 1501*8329232eSGordon Ross return (EOVERFLOW); 1502*8329232eSGordon Ross } 1503*8329232eSGordon Ross 1504*8329232eSGordon Ross static void 1505*8329232eSGordon Ross vfs_freecancelopt(char **moc) 1506*8329232eSGordon Ross { 1507*8329232eSGordon Ross if (moc != NULL) { 1508*8329232eSGordon Ross int ccnt = 0; 1509*8329232eSGordon Ross char **cp; 1510*8329232eSGordon Ross 1511*8329232eSGordon Ross for (cp = moc; *cp != NULL; cp++) { 1512*8329232eSGordon Ross kmem_free(*cp, strlen(*cp) + 1); 1513*8329232eSGordon Ross ccnt++; 1514*8329232eSGordon Ross } 1515*8329232eSGordon Ross kmem_free(moc, (ccnt + 1) * sizeof (char *)); 1516*8329232eSGordon Ross } 1517*8329232eSGordon Ross } 1518*8329232eSGordon Ross 1519*8329232eSGordon Ross static void 1520*8329232eSGordon Ross vfs_freeopt(mntopt_t *mop) 1521*8329232eSGordon Ross { 1522*8329232eSGordon Ross if (mop->mo_name != NULL) 1523*8329232eSGordon Ross kmem_free(mop->mo_name, strlen(mop->mo_name) + 1); 1524*8329232eSGordon Ross 1525*8329232eSGordon Ross vfs_freecancelopt(mop->mo_cancel); 1526*8329232eSGordon Ross 1527*8329232eSGordon Ross if (mop->mo_arg != NULL) 1528*8329232eSGordon Ross kmem_free(mop->mo_arg, strlen(mop->mo_arg) + 1); 1529*8329232eSGordon Ross } 1530*8329232eSGordon Ross 1531*8329232eSGordon Ross /* 1532*8329232eSGordon Ross * Free a mount options table 1533*8329232eSGordon Ross * 1534*8329232eSGordon Ross * This function is *not* for general use by filesystems. 1535*8329232eSGordon Ross * 1536*8329232eSGordon Ross * Note: caller is responsible for locking the vfs list, if needed, 1537*8329232eSGordon Ross * to protect mp. 1538*8329232eSGordon Ross */ 1539*8329232eSGordon Ross void 1540*8329232eSGordon Ross vfs_freeopttbl(mntopts_t *mp) 1541*8329232eSGordon Ross { 1542*8329232eSGordon Ross uint_t i, count; 1543*8329232eSGordon Ross 1544*8329232eSGordon Ross count = mp->mo_count; 1545*8329232eSGordon Ross for (i = 0; i < count; i++) { 1546*8329232eSGordon Ross vfs_freeopt(&mp->mo_list[i]); 1547*8329232eSGordon Ross } 1548*8329232eSGordon Ross if (count) { 1549*8329232eSGordon Ross kmem_free(mp->mo_list, sizeof (mntopt_t) * count); 1550*8329232eSGordon Ross mp->mo_count = 0; 1551*8329232eSGordon Ross mp->mo_list = NULL; 1552*8329232eSGordon Ross } 1553*8329232eSGordon Ross } 1554*8329232eSGordon Ross 1555*8329232eSGordon Ross // vfs_mntdummyread 1556*8329232eSGordon Ross // vfs_mntdummywrite 1557*8329232eSGordon Ross // vfs_mntdummygetattr 1558*8329232eSGordon Ross // vfs_mnttabvp_setup 1559*8329232eSGordon Ross // vfs_mnttab_rwop 1560*8329232eSGordon Ross // vfs_mnttab_writeop 1561*8329232eSGordon Ross // vfs_mnttab_readop 1562*8329232eSGordon Ross // vfs_freemnttab 1563*8329232eSGordon Ross // vfs_mnttab_modtime 1564*8329232eSGordon Ross // vfs_mnttab_poll 1565*8329232eSGordon Ross // vfs_mono_time 1566*8329232eSGordon Ross 1567*8329232eSGordon Ross /* 1568*8329232eSGordon Ross * Update the mnttab modification time... 1569*8329232eSGordon Ross */ 1570*8329232eSGordon Ross void 1571*8329232eSGordon Ross vfs_mnttab_modtimeupd() 1572*8329232eSGordon Ross { 1573*8329232eSGordon Ross } 1574*8329232eSGordon Ross 1575*8329232eSGordon Ross /* 1576*8329232eSGordon Ross * Unlike the real dounmount, we don't have 1577*8329232eSGordon Ross * vn_vfswlock_held(coveredvp) 1578*8329232eSGordon Ross */ 1579*8329232eSGordon Ross int 1580*8329232eSGordon Ross fake_dounmount(struct vfs *vfsp, int flag) 1581*8329232eSGordon Ross { 1582*8329232eSGordon Ross cred_t *cr = CRED(); 1583*8329232eSGordon Ross vnode_t *coveredvp; 1584*8329232eSGordon Ross int error; 1585*8329232eSGordon Ross 1586*8329232eSGordon Ross /* 1587*8329232eSGordon Ross * Get covered vnode. This will be NULL if the vfs is not linked 1588*8329232eSGordon Ross * into the file system name space (i.e., domount() with MNT_NOSPICE). 1589*8329232eSGordon Ross */ 1590*8329232eSGordon Ross coveredvp = vfsp->vfs_vnodecovered; 1591*8329232eSGordon Ross 1592*8329232eSGordon Ross /* For forcible umount, skip VFS_SYNC() since it may hang */ 1593*8329232eSGordon Ross if ((flag & MS_FORCE) == 0) 1594*8329232eSGordon Ross (void) VFS_SYNC(vfsp, 0, cr); 1595*8329232eSGordon Ross 1596*8329232eSGordon Ross /* 1597*8329232eSGordon Ross * Test-jig specific: 1598*8329232eSGordon Ross * Need to release rootdir before unmount or VFS_UNMOUNT 1599*8329232eSGordon Ross * may fail due to that node being active. 1600*8329232eSGordon Ross */ 1601*8329232eSGordon Ross if (rootdir != NULL) { 1602*8329232eSGordon Ross ASSERT(rootdir != coveredvp); 1603*8329232eSGordon Ross VN_RELE(rootdir); 1604*8329232eSGordon Ross rootdir = NULL; 1605*8329232eSGordon Ross } 1606*8329232eSGordon Ross 1607*8329232eSGordon Ross /* 1608*8329232eSGordon Ross * Lock the vfs to maintain fs status quo during unmount. This 1609*8329232eSGordon Ross * has to be done after the sync because ufs_update tries to acquire 1610*8329232eSGordon Ross * the vfs_reflock. 1611*8329232eSGordon Ross */ 1612*8329232eSGordon Ross vfs_lock_wait(vfsp); 1613*8329232eSGordon Ross 1614*8329232eSGordon Ross if ((error = VFS_UNMOUNT(vfsp, flag, cr)) != 0) { 1615*8329232eSGordon Ross int err2; 1616*8329232eSGordon Ross vfs_unlock(vfsp); 1617*8329232eSGordon Ross /* Get rootdir back */ 1618*8329232eSGordon Ross err2 = VFS_ROOT(vfsp, &rootdir); 1619*8329232eSGordon Ross if (err2 != 0) { 1620*8329232eSGordon Ross panic("fake_dounmount, get root %d\n", err2); 1621*8329232eSGordon Ross } 1622*8329232eSGordon Ross } else { 1623*8329232eSGordon Ross /* 1624*8329232eSGordon Ross * Real dounmount does vfs_remove. 1625*8329232eSGordon Ross * 1626*8329232eSGordon Ross * Test-jig specific: 1627*8329232eSGordon Ross * Restore the covered rootdir, 1628*8329232eSGordon Ross * release the rootvfs hold and clear. 1629*8329232eSGordon Ross */ 1630*8329232eSGordon Ross if (coveredvp != NULL) { 1631*8329232eSGordon Ross // vfs_list_remove(vfsp); 1632*8329232eSGordon Ross vfsp->vfs_vnodecovered = NULL; 1633*8329232eSGordon Ross rootdir = coveredvp; 1634*8329232eSGordon Ross } 1635*8329232eSGordon Ross if (rootvfs == vfsp) { 1636*8329232eSGordon Ross VFS_RELE(vfsp); 1637*8329232eSGordon Ross rootvfs = NULL; 1638*8329232eSGordon Ross } 1639*8329232eSGordon Ross 1640*8329232eSGordon Ross /* 1641*8329232eSGordon Ross * Release the (final) reference to vfs 1642*8329232eSGordon Ross */ 1643*8329232eSGordon Ross vfs_unlock(vfsp); 1644*8329232eSGordon Ross VFS_RELE(vfsp); 1645*8329232eSGordon Ross } 1646*8329232eSGordon Ross return (error); 1647*8329232eSGordon Ross } 1648*8329232eSGordon Ross 1649*8329232eSGordon Ross // vfs_unmountall(void) 1650*8329232eSGordon Ross // vfs_addmip 1651*8329232eSGordon Ross // vfs_delmip 1652*8329232eSGordon Ross // vfs_add 1653*8329232eSGordon Ross // vfs_remove 1654*8329232eSGordon Ross 1655*8329232eSGordon Ross static krwlock_t vpvfsentry_ve_lock; 1656*8329232eSGordon Ross 1657*8329232eSGordon Ross /* 1658*8329232eSGordon Ross * Lock a filesystem to prevent access to it while mounting, 1659*8329232eSGordon Ross * unmounting and syncing. Return EBUSY immediately if lock 1660*8329232eSGordon Ross * can't be acquired. 1661*8329232eSGordon Ross */ 1662*8329232eSGordon Ross int 1663*8329232eSGordon Ross vfs_lock(vfs_t *vfsp) 1664*8329232eSGordon Ross { 1665*8329232eSGordon Ross 1666*8329232eSGordon Ross if (rw_tryenter(&vpvfsentry_ve_lock, RW_WRITER)) 1667*8329232eSGordon Ross return (0); 1668*8329232eSGordon Ross 1669*8329232eSGordon Ross return (EBUSY); 1670*8329232eSGordon Ross } 1671*8329232eSGordon Ross 1672*8329232eSGordon Ross int 1673*8329232eSGordon Ross vfs_rlock(vfs_t *vfsp) 1674*8329232eSGordon Ross { 1675*8329232eSGordon Ross 1676*8329232eSGordon Ross if (rw_tryenter(&vpvfsentry_ve_lock, RW_READER)) 1677*8329232eSGordon Ross return (0); 1678*8329232eSGordon Ross 1679*8329232eSGordon Ross return (EBUSY); 1680*8329232eSGordon Ross } 1681*8329232eSGordon Ross 1682*8329232eSGordon Ross void 1683*8329232eSGordon Ross vfs_lock_wait(vfs_t *vfsp) 1684*8329232eSGordon Ross { 1685*8329232eSGordon Ross 1686*8329232eSGordon Ross rw_enter(&vpvfsentry_ve_lock, RW_WRITER); 1687*8329232eSGordon Ross } 1688*8329232eSGordon Ross 1689*8329232eSGordon Ross void 1690*8329232eSGordon Ross vfs_rlock_wait(vfs_t *vfsp) 1691*8329232eSGordon Ross { 1692*8329232eSGordon Ross rw_enter(&vpvfsentry_ve_lock, RW_READER); 1693*8329232eSGordon Ross } 1694*8329232eSGordon Ross 1695*8329232eSGordon Ross /* 1696*8329232eSGordon Ross * Unlock a locked filesystem. 1697*8329232eSGordon Ross */ 1698*8329232eSGordon Ross void 1699*8329232eSGordon Ross vfs_unlock(vfs_t *vfsp) 1700*8329232eSGordon Ross { 1701*8329232eSGordon Ross 1702*8329232eSGordon Ross rw_exit(&vpvfsentry_ve_lock); 1703*8329232eSGordon Ross } 1704*8329232eSGordon Ross 1705*8329232eSGordon Ross /* 1706*8329232eSGordon Ross * Utility routine that allows a filesystem to construct its 1707*8329232eSGordon Ross * fsid in "the usual way" - by munging some underlying dev_t and 1708*8329232eSGordon Ross * the filesystem type number into the 64-bit fsid. ... 1709*8329232eSGordon Ross */ 1710*8329232eSGordon Ross void 1711*8329232eSGordon Ross vfs_make_fsid(fsid_t *fsi, dev_t dev, int val) 1712*8329232eSGordon Ross { 1713*8329232eSGordon Ross if (!cmpldev((dev32_t *)&fsi->val[0], dev)) 1714*8329232eSGordon Ross panic("device number too big for fsid!"); 1715*8329232eSGordon Ross fsi->val[1] = val; 1716*8329232eSGordon Ross } 1717*8329232eSGordon Ross 1718*8329232eSGordon Ross int 1719*8329232eSGordon Ross vfs_lock_held(vfs_t *vfsp) 1720*8329232eSGordon Ross { 1721*8329232eSGordon Ross int held; 1722*8329232eSGordon Ross 1723*8329232eSGordon Ross held = rw_write_held(&vpvfsentry_ve_lock); 1724*8329232eSGordon Ross 1725*8329232eSGordon Ross return (held); 1726*8329232eSGordon Ross } 1727*8329232eSGordon Ross 1728*8329232eSGordon Ross // vfs_lock_owner 1729*8329232eSGordon Ross 1730*8329232eSGordon Ross /* 1731*8329232eSGordon Ross * vfs list locking. 1732*8329232eSGordon Ross */ 1733*8329232eSGordon Ross 1734*8329232eSGordon Ross void 1735*8329232eSGordon Ross vfs_list_lock() 1736*8329232eSGordon Ross { 1737*8329232eSGordon Ross rw_enter(&vfslist, RW_WRITER); 1738*8329232eSGordon Ross } 1739*8329232eSGordon Ross 1740*8329232eSGordon Ross void 1741*8329232eSGordon Ross vfs_list_read_lock() 1742*8329232eSGordon Ross { 1743*8329232eSGordon Ross rw_enter(&vfslist, RW_READER); 1744*8329232eSGordon Ross } 1745*8329232eSGordon Ross 1746*8329232eSGordon Ross void 1747*8329232eSGordon Ross vfs_list_unlock() 1748*8329232eSGordon Ross { 1749*8329232eSGordon Ross rw_exit(&vfslist); 1750*8329232eSGordon Ross } 1751*8329232eSGordon Ross 1752*8329232eSGordon Ross /* 1753*8329232eSGordon Ross * Low level worker routines for adding entries to and removing entries from 1754*8329232eSGordon Ross * the vfs list. 1755*8329232eSGordon Ross */ 1756*8329232eSGordon Ross 1757*8329232eSGordon Ross // vfs_hash_add 1758*8329232eSGordon Ross // vfs_hash_remove 1759*8329232eSGordon Ross // vfs_list_add 1760*8329232eSGordon Ross // vfs_list_remove 1761*8329232eSGordon Ross // getvfs 1762*8329232eSGordon Ross // vfs_devmounting 1763*8329232eSGordon Ross 1764*8329232eSGordon Ross /* 1765*8329232eSGordon Ross * Search the vfs list for a specified device. Returns 1, if entry is found 1766*8329232eSGordon Ross * or 0 if no suitable entry is found. 1767*8329232eSGordon Ross */ 1768*8329232eSGordon Ross 1769*8329232eSGordon Ross int 1770*8329232eSGordon Ross vfs_devismounted(dev_t dev) 1771*8329232eSGordon Ross { 1772*8329232eSGordon Ross return (0); 1773*8329232eSGordon Ross } 1774*8329232eSGordon Ross 1775*8329232eSGordon Ross // vfs_dev2vfsp 1776*8329232eSGordon Ross // vfs_mntpoint2vfsp 1777*8329232eSGordon Ross 1778*8329232eSGordon Ross /* 1779*8329232eSGordon Ross * Search the vfs list for a specified vfsops. 1780*8329232eSGordon Ross * if vfs entry is found then return 1, else 0. 1781*8329232eSGordon Ross */ 1782*8329232eSGordon Ross int 1783*8329232eSGordon Ross vfs_opsinuse(vfsops_t *ops) 1784*8329232eSGordon Ross { 1785*8329232eSGordon Ross return (0); 1786*8329232eSGordon Ross } 1787*8329232eSGordon Ross 1788*8329232eSGordon Ross /* 1789*8329232eSGordon Ross * Allocate an entry in vfssw for a file system type 1790*8329232eSGordon Ross */ 1791*8329232eSGordon Ross struct vfssw * 1792*8329232eSGordon Ross allocate_vfssw(const char *type) 1793*8329232eSGordon Ross { 1794*8329232eSGordon Ross struct vfssw *vswp; 1795*8329232eSGordon Ross 1796*8329232eSGordon Ross if (type[0] == '\0' || strlen(type) + 1 > _ST_FSTYPSZ) { 1797*8329232eSGordon Ross /* 1798*8329232eSGordon Ross * The vfssw table uses the empty string to identify an 1799*8329232eSGordon Ross * available entry; we cannot add any type which has 1800*8329232eSGordon Ross * a leading NUL. The string length is limited to 1801*8329232eSGordon Ross * the size of the st_fstype array in struct stat. 1802*8329232eSGordon Ross */ 1803*8329232eSGordon Ross return (NULL); 1804*8329232eSGordon Ross } 1805*8329232eSGordon Ross 1806*8329232eSGordon Ross ASSERT(VFSSW_WRITE_LOCKED()); 1807*8329232eSGordon Ross for (vswp = &vfssw[1]; vswp < &vfssw[nfstype]; vswp++) 1808*8329232eSGordon Ross if (!ALLOCATED_VFSSW(vswp)) { 1809*8329232eSGordon Ross vswp->vsw_name = kmem_alloc(strlen(type) + 1, KM_SLEEP); 1810*8329232eSGordon Ross (void) strcpy(vswp->vsw_name, type); 1811*8329232eSGordon Ross ASSERT(vswp->vsw_count == 0); 1812*8329232eSGordon Ross vswp->vsw_count = 1; 1813*8329232eSGordon Ross mutex_init(&vswp->vsw_lock, NULL, MUTEX_DEFAULT, NULL); 1814*8329232eSGordon Ross return (vswp); 1815*8329232eSGordon Ross } 1816*8329232eSGordon Ross return (NULL); 1817*8329232eSGordon Ross } 1818*8329232eSGordon Ross 1819*8329232eSGordon Ross // vfs_to_modname 1820*8329232eSGordon Ross // vfs_getvfssw 1821*8329232eSGordon Ross 1822*8329232eSGordon Ross /* 1823*8329232eSGordon Ross * Find a vfssw entry given a file system type name. 1824*8329232eSGordon Ross */ 1825*8329232eSGordon Ross struct vfssw * 1826*8329232eSGordon Ross vfs_getvfssw(const char *type) 1827*8329232eSGordon Ross { 1828*8329232eSGordon Ross struct vfssw *vswp; 1829*8329232eSGordon Ross 1830*8329232eSGordon Ross if (type == NULL || *type == '\0') 1831*8329232eSGordon Ross return (NULL); 1832*8329232eSGordon Ross 1833*8329232eSGordon Ross for (vswp = &vfssw[1]; vswp < &vfssw[nfstype]; vswp++) { 1834*8329232eSGordon Ross if (strcmp(type, vswp->vsw_name) == 0) { 1835*8329232eSGordon Ross return (vswp); 1836*8329232eSGordon Ross } 1837*8329232eSGordon Ross } 1838*8329232eSGordon Ross 1839*8329232eSGordon Ross return (NULL); 1840*8329232eSGordon Ross 1841*8329232eSGordon Ross } 1842*8329232eSGordon Ross 1843*8329232eSGordon Ross /* 1844*8329232eSGordon Ross * Find a vfssw entry given a file system type name. 1845*8329232eSGordon Ross */ 1846*8329232eSGordon Ross struct vfssw * 1847*8329232eSGordon Ross vfs_getvfsswbyname(const char *type) 1848*8329232eSGordon Ross { 1849*8329232eSGordon Ross struct vfssw *vswp; 1850*8329232eSGordon Ross 1851*8329232eSGordon Ross ASSERT(VFSSW_LOCKED()); 1852*8329232eSGordon Ross if (type == NULL || *type == '\0') 1853*8329232eSGordon Ross return (NULL); 1854*8329232eSGordon Ross 1855*8329232eSGordon Ross for (vswp = &vfssw[1]; vswp < &vfssw[nfstype]; vswp++) { 1856*8329232eSGordon Ross if (strcmp(type, vswp->vsw_name) == 0) { 1857*8329232eSGordon Ross vfs_refvfssw(vswp); 1858*8329232eSGordon Ross return (vswp); 1859*8329232eSGordon Ross } 1860*8329232eSGordon Ross } 1861*8329232eSGordon Ross 1862*8329232eSGordon Ross return (NULL); 1863*8329232eSGordon Ross } 1864*8329232eSGordon Ross 1865*8329232eSGordon Ross // vfs_getvfsswbyvfsops 1866*8329232eSGordon Ross 1867*8329232eSGordon Ross /* 1868*8329232eSGordon Ross * Reference a vfssw entry. 1869*8329232eSGordon Ross */ 1870*8329232eSGordon Ross void 1871*8329232eSGordon Ross vfs_refvfssw(struct vfssw *vswp) 1872*8329232eSGordon Ross { 1873*8329232eSGordon Ross 1874*8329232eSGordon Ross mutex_enter(&vswp->vsw_lock); 1875*8329232eSGordon Ross vswp->vsw_count++; 1876*8329232eSGordon Ross mutex_exit(&vswp->vsw_lock); 1877*8329232eSGordon Ross } 1878*8329232eSGordon Ross 1879*8329232eSGordon Ross /* 1880*8329232eSGordon Ross * Unreference a vfssw entry. 1881*8329232eSGordon Ross */ 1882*8329232eSGordon Ross void 1883*8329232eSGordon Ross vfs_unrefvfssw(struct vfssw *vswp) 1884*8329232eSGordon Ross { 1885*8329232eSGordon Ross 1886*8329232eSGordon Ross mutex_enter(&vswp->vsw_lock); 1887*8329232eSGordon Ross vswp->vsw_count--; 1888*8329232eSGordon Ross mutex_exit(&vswp->vsw_lock); 1889*8329232eSGordon Ross } 1890*8329232eSGordon Ross 1891*8329232eSGordon Ross // vfs_syncall 1892*8329232eSGordon Ross 1893*8329232eSGordon Ross /* 1894*8329232eSGordon Ross * Map VFS flags to statvfs flags. These shouldn't really be separate 1895*8329232eSGordon Ross * flags at all. 1896*8329232eSGordon Ross */ 1897*8329232eSGordon Ross uint_t 1898*8329232eSGordon Ross vf_to_stf(uint_t vf) 1899*8329232eSGordon Ross { 1900*8329232eSGordon Ross uint_t stf = 0; 1901*8329232eSGordon Ross 1902*8329232eSGordon Ross if (vf & VFS_RDONLY) 1903*8329232eSGordon Ross stf |= ST_RDONLY; 1904*8329232eSGordon Ross if (vf & VFS_NOSETUID) 1905*8329232eSGordon Ross stf |= ST_NOSUID; 1906*8329232eSGordon Ross if (vf & VFS_NOTRUNC) 1907*8329232eSGordon Ross stf |= ST_NOTRUNC; 1908*8329232eSGordon Ross 1909*8329232eSGordon Ross return (stf); 1910*8329232eSGordon Ross } 1911*8329232eSGordon Ross 1912*8329232eSGordon Ross // vfsstray_sync 1913*8329232eSGordon Ross // vfsstray 1914*8329232eSGordon Ross // vfs_EIO 1915*8329232eSGordon Ross // vfs_EIO_sync 1916*8329232eSGordon Ross // EIO_vfs 1917*8329232eSGordon Ross // EIO_vfsops 1918*8329232eSGordon Ross 1919*8329232eSGordon Ross #pragma init(vfsinit) 1920*8329232eSGordon Ross 1921*8329232eSGordon Ross /* 1922*8329232eSGordon Ross * Called from startup() to initialize all loaded vfs's 1923*8329232eSGordon Ross */ 1924*8329232eSGordon Ross void 1925*8329232eSGordon Ross vfsinit(void) 1926*8329232eSGordon Ross { 1927*8329232eSGordon Ross vn_create_cache(); 1928*8329232eSGordon Ross 1929*8329232eSGordon Ross /* Temporary, until we mount root */ 1930*8329232eSGordon Ross rootdir = vn_alloc(KM_SLEEP); 1931*8329232eSGordon Ross rootdir->v_type = VDIR; 1932*8329232eSGordon Ross } 1933*8329232eSGordon Ross 1934*8329232eSGordon Ross vfs_t * 1935*8329232eSGordon Ross vfs_alloc(int kmflag) 1936*8329232eSGordon Ross { 1937*8329232eSGordon Ross vfs_t *vfsp; 1938*8329232eSGordon Ross 1939*8329232eSGordon Ross vfsp = kmem_alloc(sizeof (struct vfs), kmflag); 1940*8329232eSGordon Ross 1941*8329232eSGordon Ross /* 1942*8329232eSGordon Ross * Do the simplest initialization here. 1943*8329232eSGordon Ross * Everything else gets done in vfs_init() 1944*8329232eSGordon Ross */ 1945*8329232eSGordon Ross bzero(vfsp, sizeof (vfs_t)); 1946*8329232eSGordon Ross return (vfsp); 1947*8329232eSGordon Ross } 1948*8329232eSGordon Ross 1949*8329232eSGordon Ross void 1950*8329232eSGordon Ross vfs_free(vfs_t *vfsp) 1951*8329232eSGordon Ross { 1952*8329232eSGordon Ross /* 1953*8329232eSGordon Ross * One would be tempted to assert that "vfsp->vfs_count == 0". 1954*8329232eSGordon Ross * Don't. See fs/vfs.c 1955*8329232eSGordon Ross */ 1956*8329232eSGordon Ross 1957*8329232eSGordon Ross /* If FEM was in use, make sure everything gets cleaned up */ 1958*8329232eSGordon Ross 1959*8329232eSGordon Ross if (vfsp->vfs_implp) 1960*8329232eSGordon Ross vfsimpl_teardown(vfsp); 1961*8329232eSGordon Ross sema_destroy(&vfsp->vfs_reflock); 1962*8329232eSGordon Ross kmem_free(vfsp, sizeof (struct vfs)); 1963*8329232eSGordon Ross } 1964*8329232eSGordon Ross 1965*8329232eSGordon Ross /* 1966*8329232eSGordon Ross * Increments the vfs reference count by one atomically. 1967*8329232eSGordon Ross */ 1968*8329232eSGordon Ross void 1969*8329232eSGordon Ross vfs_hold(vfs_t *vfsp) 1970*8329232eSGordon Ross { 1971*8329232eSGordon Ross atomic_inc_32(&vfsp->vfs_count); 1972*8329232eSGordon Ross ASSERT(vfsp->vfs_count != 0); 1973*8329232eSGordon Ross } 1974*8329232eSGordon Ross 1975*8329232eSGordon Ross /* 1976*8329232eSGordon Ross * Decrements the vfs reference count by one atomically. When 1977*8329232eSGordon Ross * vfs reference count becomes zero, it calls the file system 1978*8329232eSGordon Ross * specific vfs_freevfs() to free up the resources. 1979*8329232eSGordon Ross */ 1980*8329232eSGordon Ross void 1981*8329232eSGordon Ross vfs_rele(vfs_t *vfsp) 1982*8329232eSGordon Ross { 1983*8329232eSGordon Ross ASSERT(vfsp->vfs_count != 0); 1984*8329232eSGordon Ross if (atomic_dec_32_nv(&vfsp->vfs_count) == 0) { 1985*8329232eSGordon Ross VFS_FREEVFS(vfsp); 1986*8329232eSGordon Ross // lofi_remove(vfsp); 1987*8329232eSGordon Ross // zone_rele_ref... 1988*8329232eSGordon Ross // vfs_freemnttab(vfsp); 1989*8329232eSGordon Ross vfs_free(vfsp); 1990*8329232eSGordon Ross } 1991*8329232eSGordon Ross } 1992*8329232eSGordon Ross 1993*8329232eSGordon Ross /* 1994*8329232eSGordon Ross * Generic operations vector support. 1995*8329232eSGordon Ross */ 1996*8329232eSGordon Ross 1997*8329232eSGordon Ross int 1998*8329232eSGordon Ross fs_build_vector(void *vector, int *unused_ops, 1999*8329232eSGordon Ross const fs_operation_trans_def_t *translation, 2000*8329232eSGordon Ross const fs_operation_def_t *operations) 2001*8329232eSGordon Ross { 2002*8329232eSGordon Ross int i, num_trans, num_ops, used; 2003*8329232eSGordon Ross 2004*8329232eSGordon Ross /* 2005*8329232eSGordon Ross * Count the number of translations and the number of supplied 2006*8329232eSGordon Ross * operations. 2007*8329232eSGordon Ross */ 2008*8329232eSGordon Ross 2009*8329232eSGordon Ross { 2010*8329232eSGordon Ross const fs_operation_trans_def_t *p; 2011*8329232eSGordon Ross 2012*8329232eSGordon Ross for (num_trans = 0, p = translation; 2013*8329232eSGordon Ross p->name != NULL; 2014*8329232eSGordon Ross num_trans++, p++) 2015*8329232eSGordon Ross ; 2016*8329232eSGordon Ross } 2017*8329232eSGordon Ross 2018*8329232eSGordon Ross { 2019*8329232eSGordon Ross const fs_operation_def_t *p; 2020*8329232eSGordon Ross 2021*8329232eSGordon Ross for (num_ops = 0, p = operations; 2022*8329232eSGordon Ross p->name != NULL; 2023*8329232eSGordon Ross num_ops++, p++) 2024*8329232eSGordon Ross ; 2025*8329232eSGordon Ross } 2026*8329232eSGordon Ross 2027*8329232eSGordon Ross /* Walk through each operation known to our caller. There will be */ 2028*8329232eSGordon Ross /* one entry in the supplied "translation table" for each. */ 2029*8329232eSGordon Ross 2030*8329232eSGordon Ross used = 0; 2031*8329232eSGordon Ross 2032*8329232eSGordon Ross for (i = 0; i < num_trans; i++) { 2033*8329232eSGordon Ross int j, found; 2034*8329232eSGordon Ross char *curname; 2035*8329232eSGordon Ross fs_generic_func_p result; 2036*8329232eSGordon Ross fs_generic_func_p *location; 2037*8329232eSGordon Ross 2038*8329232eSGordon Ross curname = translation[i].name; 2039*8329232eSGordon Ross 2040*8329232eSGordon Ross /* Look for a matching operation in the list supplied by the */ 2041*8329232eSGordon Ross /* file system. */ 2042*8329232eSGordon Ross 2043*8329232eSGordon Ross found = 0; 2044*8329232eSGordon Ross 2045*8329232eSGordon Ross for (j = 0; j < num_ops; j++) { 2046*8329232eSGordon Ross if (strcmp(operations[j].name, curname) == 0) { 2047*8329232eSGordon Ross used++; 2048*8329232eSGordon Ross found = 1; 2049*8329232eSGordon Ross break; 2050*8329232eSGordon Ross } 2051*8329232eSGordon Ross } 2052*8329232eSGordon Ross 2053*8329232eSGordon Ross /* 2054*8329232eSGordon Ross * If the file system is using a "placeholder" for default 2055*8329232eSGordon Ross * or error functions, grab the appropriate function out of 2056*8329232eSGordon Ross * the translation table. If the file system didn't supply 2057*8329232eSGordon Ross * this operation at all, use the default function. 2058*8329232eSGordon Ross */ 2059*8329232eSGordon Ross 2060*8329232eSGordon Ross if (found) { 2061*8329232eSGordon Ross result = operations[j].func.fs_generic; 2062*8329232eSGordon Ross if (result == fs_default) { 2063*8329232eSGordon Ross result = translation[i].defaultFunc; 2064*8329232eSGordon Ross } else if (result == fs_error) { 2065*8329232eSGordon Ross result = translation[i].errorFunc; 2066*8329232eSGordon Ross } else if (result == NULL) { 2067*8329232eSGordon Ross /* Null values are PROHIBITED */ 2068*8329232eSGordon Ross return (EINVAL); 2069*8329232eSGordon Ross } 2070*8329232eSGordon Ross } else { 2071*8329232eSGordon Ross result = translation[i].defaultFunc; 2072*8329232eSGordon Ross } 2073*8329232eSGordon Ross 2074*8329232eSGordon Ross /* Now store the function into the operations vector. */ 2075*8329232eSGordon Ross 2076*8329232eSGordon Ross /* LINTED E_BAD_PTR_CAST_ALIGN */ 2077*8329232eSGordon Ross location = (fs_generic_func_p *) 2078*8329232eSGordon Ross (((char *)vector) + translation[i].offset); 2079*8329232eSGordon Ross 2080*8329232eSGordon Ross *location = result; 2081*8329232eSGordon Ross } 2082*8329232eSGordon Ross 2083*8329232eSGordon Ross *unused_ops = num_ops - used; 2084*8329232eSGordon Ross 2085*8329232eSGordon Ross return (0); 2086*8329232eSGordon Ross } 2087*8329232eSGordon Ross 2088*8329232eSGordon Ross /* Placeholder functions, should never be called. */ 2089*8329232eSGordon Ross 2090*8329232eSGordon Ross int 2091*8329232eSGordon Ross fs_error(void) 2092*8329232eSGordon Ross { 2093*8329232eSGordon Ross cmn_err(CE_PANIC, "fs_error called"); 2094*8329232eSGordon Ross return (0); 2095*8329232eSGordon Ross } 2096*8329232eSGordon Ross 2097*8329232eSGordon Ross int 2098*8329232eSGordon Ross fs_default(void) 2099*8329232eSGordon Ross { 2100*8329232eSGordon Ross cmn_err(CE_PANIC, "fs_default called"); 2101*8329232eSGordon Ross return (0); 2102*8329232eSGordon Ross } 2103*8329232eSGordon Ross 2104*8329232eSGordon Ross // rootconf 2105*8329232eSGordon Ross // getfsname 2106*8329232eSGordon Ross // getrootfs 2107*8329232eSGordon Ross 2108*8329232eSGordon Ross /* 2109*8329232eSGordon Ross * VFS feature routines 2110*8329232eSGordon Ross */ 2111*8329232eSGordon Ross 2112*8329232eSGordon Ross #define VFTINDEX(feature) (((feature) >> 32) & 0xFFFFFFFF) 2113*8329232eSGordon Ross #define VFTBITS(feature) ((feature) & 0xFFFFFFFFLL) 2114*8329232eSGordon Ross 2115*8329232eSGordon Ross /* Register a feature in the vfs */ 2116*8329232eSGordon Ross void 2117*8329232eSGordon Ross vfs_set_feature(vfs_t *vfsp, vfs_feature_t feature) 2118*8329232eSGordon Ross { 2119*8329232eSGordon Ross /* Note that vfs_featureset[] is found in *vfsp->vfs_implp */ 2120*8329232eSGordon Ross if (vfsp->vfs_implp == NULL) 2121*8329232eSGordon Ross return; 2122*8329232eSGordon Ross 2123*8329232eSGordon Ross vfsp->vfs_featureset[VFTINDEX(feature)] |= VFTBITS(feature); 2124*8329232eSGordon Ross } 2125*8329232eSGordon Ross 2126*8329232eSGordon Ross void 2127*8329232eSGordon Ross vfs_clear_feature(vfs_t *vfsp, vfs_feature_t feature) 2128*8329232eSGordon Ross { 2129*8329232eSGordon Ross /* Note that vfs_featureset[] is found in *vfsp->vfs_implp */ 2130*8329232eSGordon Ross if (vfsp->vfs_implp == NULL) 2131*8329232eSGordon Ross return; 2132*8329232eSGordon Ross vfsp->vfs_featureset[VFTINDEX(feature)] &= VFTBITS(~feature); 2133*8329232eSGordon Ross } 2134*8329232eSGordon Ross 2135*8329232eSGordon Ross /* 2136*8329232eSGordon Ross * Query a vfs for a feature. 2137*8329232eSGordon Ross * Returns 1 if feature is present, 0 if not 2138*8329232eSGordon Ross */ 2139*8329232eSGordon Ross int 2140*8329232eSGordon Ross vfs_has_feature(vfs_t *vfsp, vfs_feature_t feature) 2141*8329232eSGordon Ross { 2142*8329232eSGordon Ross int ret = 0; 2143*8329232eSGordon Ross 2144*8329232eSGordon Ross /* Note that vfs_featureset[] is found in *vfsp->vfs_implp */ 2145*8329232eSGordon Ross if (vfsp->vfs_implp == NULL) 2146*8329232eSGordon Ross return (ret); 2147*8329232eSGordon Ross 2148*8329232eSGordon Ross if (vfsp->vfs_featureset[VFTINDEX(feature)] & VFTBITS(feature)) 2149*8329232eSGordon Ross ret = 1; 2150*8329232eSGordon Ross 2151*8329232eSGordon Ross return (ret); 2152*8329232eSGordon Ross } 2153*8329232eSGordon Ross 2154*8329232eSGordon Ross // vfs_propagate_features 2155*8329232eSGordon Ross // vfs_get_lofi 2156