1*2621Sllai1 /* 2*2621Sllai1 * CDDL HEADER START 3*2621Sllai1 * 4*2621Sllai1 * The contents of this file are subject to the terms of the 5*2621Sllai1 * Common Development and Distribution License (the "License"). 6*2621Sllai1 * You may not use this file except in compliance with the License. 7*2621Sllai1 * 8*2621Sllai1 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*2621Sllai1 * or http://www.opensolaris.org/os/licensing. 10*2621Sllai1 * See the License for the specific language governing permissions 11*2621Sllai1 * and limitations under the License. 12*2621Sllai1 * 13*2621Sllai1 * When distributing Covered Code, include this CDDL HEADER in each 14*2621Sllai1 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*2621Sllai1 * If applicable, add the following below this CDDL HEADER, with the 16*2621Sllai1 * fields enclosed by brackets "[]" replaced with your own identifying 17*2621Sllai1 * information: Portions Copyright [yyyy] [name of copyright owner] 18*2621Sllai1 * 19*2621Sllai1 * CDDL HEADER END 20*2621Sllai1 */ 21*2621Sllai1 /* 22*2621Sllai1 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*2621Sllai1 * Use is subject to license terms. 24*2621Sllai1 */ 25*2621Sllai1 26*2621Sllai1 #pragma ident "%Z%%M% %I% %E% SMI" 27*2621Sllai1 28*2621Sllai1 /* 29*2621Sllai1 * This is the /dev (hence, the sdev_ prefix) filesystem. 30*2621Sllai1 */ 31*2621Sllai1 32*2621Sllai1 #include <sys/types.h> 33*2621Sllai1 #include <sys/param.h> 34*2621Sllai1 #include <sys/sysmacros.h> 35*2621Sllai1 #include <sys/systm.h> 36*2621Sllai1 #include <sys/kmem.h> 37*2621Sllai1 #include <sys/time.h> 38*2621Sllai1 #include <sys/pathname.h> 39*2621Sllai1 #include <sys/vfs.h> 40*2621Sllai1 #include <sys/vnode.h> 41*2621Sllai1 #include <sys/file.h> 42*2621Sllai1 #include <sys/stat.h> 43*2621Sllai1 #include <sys/uio.h> 44*2621Sllai1 #include <sys/stat.h> 45*2621Sllai1 #include <sys/errno.h> 46*2621Sllai1 #include <sys/cmn_err.h> 47*2621Sllai1 #include <sys/cred.h> 48*2621Sllai1 #include <sys/statvfs.h> 49*2621Sllai1 #include <sys/policy.h> 50*2621Sllai1 #include <sys/mount.h> 51*2621Sllai1 #include <sys/debug.h> 52*2621Sllai1 #include <sys/modctl.h> 53*2621Sllai1 #include <sys/mkdev.h> 54*2621Sllai1 #include <fs/fs_subr.h> 55*2621Sllai1 #include <sys/fs/sdev_impl.h> 56*2621Sllai1 #include <sys/fs/sdev_node.h> 57*2621Sllai1 #include <sys/fs/snode.h> 58*2621Sllai1 #include <sys/fs/dv_node.h> 59*2621Sllai1 #include <sys/sunndi.h> 60*2621Sllai1 #include <sys/mntent.h> 61*2621Sllai1 62*2621Sllai1 /* 63*2621Sllai1 * /dev vfs operations. 64*2621Sllai1 */ 65*2621Sllai1 66*2621Sllai1 /* 67*2621Sllai1 * globals 68*2621Sllai1 */ 69*2621Sllai1 struct sdev_data *sdev_origins; /* mount info for origins under /dev */ 70*2621Sllai1 71*2621Sllai1 /* 72*2621Sllai1 * static 73*2621Sllai1 */ 74*2621Sllai1 static kmutex_t sdev_lock; /* protects global data */ 75*2621Sllai1 static major_t devmajor; /* the fictitious major we live on */ 76*2621Sllai1 static major_t devminor; /* the fictitious minor of this instance */ 77*2621Sllai1 static struct sdev_data *sdev_mntinfo = NULL; /* linked list of instances */ 78*2621Sllai1 static struct vnode *sdev_stale_attrvp; /* stale root attrvp after remount */ 79*2621Sllai1 static int sdev_mntinfo_cnt; /* mntinfo reference count */ 80*2621Sllai1 81*2621Sllai1 static int sdev_mount(struct vfs *, struct vnode *, struct mounta *, 82*2621Sllai1 struct cred *); 83*2621Sllai1 static int sdev_unmount(struct vfs *, int, struct cred *); 84*2621Sllai1 static int sdev_root(struct vfs *, struct vnode **); 85*2621Sllai1 static int sdev_statvfs(struct vfs *, struct statvfs64 *); 86*2621Sllai1 static void sdev_insert_mntinfo(struct sdev_data *); 87*2621Sllai1 static int devinit(int, char *); 88*2621Sllai1 89*2621Sllai1 static vfsdef_t sdev_vfssw = { 90*2621Sllai1 VFSDEF_VERSION, 91*2621Sllai1 "dev", /* type name string */ 92*2621Sllai1 devinit, /* init routine */ 93*2621Sllai1 VSW_CANREMOUNT, /* flags */ 94*2621Sllai1 NULL /* mount options table prototype */ 95*2621Sllai1 }; 96*2621Sllai1 97*2621Sllai1 98*2621Sllai1 /* 99*2621Sllai1 * Module linkage information 100*2621Sllai1 */ 101*2621Sllai1 static struct modlfs modlfs = { 102*2621Sllai1 &mod_fsops, "/dev filesystem %I%", &sdev_vfssw 103*2621Sllai1 }; 104*2621Sllai1 105*2621Sllai1 static struct modlinkage modlinkage = { 106*2621Sllai1 MODREV_1, (void *)&modlfs, NULL 107*2621Sllai1 }; 108*2621Sllai1 109*2621Sllai1 int 110*2621Sllai1 _init(void) 111*2621Sllai1 { 112*2621Sllai1 int e; 113*2621Sllai1 114*2621Sllai1 mutex_init(&sdev_lock, NULL, MUTEX_DEFAULT, NULL); 115*2621Sllai1 sdev_node_cache_init(); 116*2621Sllai1 sdev_devfsadm_lockinit(); 117*2621Sllai1 if ((e = mod_install(&modlinkage)) != 0) { 118*2621Sllai1 sdev_devfsadm_lockdestroy(); 119*2621Sllai1 sdev_node_cache_fini(); 120*2621Sllai1 mutex_destroy(&sdev_lock); 121*2621Sllai1 return (e); 122*2621Sllai1 } 123*2621Sllai1 return (0); 124*2621Sllai1 } 125*2621Sllai1 126*2621Sllai1 /* 127*2621Sllai1 * dev module remained loaded for the global /dev instance 128*2621Sllai1 */ 129*2621Sllai1 int 130*2621Sllai1 _fini(void) 131*2621Sllai1 { 132*2621Sllai1 return (EBUSY); 133*2621Sllai1 } 134*2621Sllai1 135*2621Sllai1 int 136*2621Sllai1 _info(struct modinfo *modinfop) 137*2621Sllai1 { 138*2621Sllai1 return (mod_info(&modlinkage, modinfop)); 139*2621Sllai1 } 140*2621Sllai1 141*2621Sllai1 /*ARGSUSED*/ 142*2621Sllai1 static int 143*2621Sllai1 devinit(int fstype, char *name) 144*2621Sllai1 { 145*2621Sllai1 static const fs_operation_def_t dev_vfsops_tbl[] = { 146*2621Sllai1 VFSNAME_MOUNT, sdev_mount, /* mount file system */ 147*2621Sllai1 VFSNAME_UNMOUNT, sdev_unmount, /* unmount file system */ 148*2621Sllai1 VFSNAME_ROOT, sdev_root, /* get root vnode */ 149*2621Sllai1 VFSNAME_STATVFS, sdev_statvfs, /* get file system statistics */ 150*2621Sllai1 NULL, NULL 151*2621Sllai1 }; 152*2621Sllai1 153*2621Sllai1 int error; 154*2621Sllai1 extern major_t getudev(void); 155*2621Sllai1 156*2621Sllai1 devtype = fstype; 157*2621Sllai1 158*2621Sllai1 error = vfs_setfsops(fstype, dev_vfsops_tbl, NULL); 159*2621Sllai1 if (error != 0) { 160*2621Sllai1 cmn_err(CE_WARN, "devinit: bad vfs ops tbl"); 161*2621Sllai1 return (error); 162*2621Sllai1 } 163*2621Sllai1 164*2621Sllai1 error = vn_make_ops("dev", sdev_vnodeops_tbl, &sdev_vnodeops); 165*2621Sllai1 if (error != 0) { 166*2621Sllai1 (void) vfs_freevfsops_by_type(fstype); 167*2621Sllai1 cmn_err(CE_WARN, "devinit: bad vnode ops tbl"); 168*2621Sllai1 return (error); 169*2621Sllai1 } 170*2621Sllai1 171*2621Sllai1 if ((devmajor = getudev()) == (major_t)-1) { 172*2621Sllai1 cmn_err(CE_WARN, "%s: can't get unique dev", sdev_vfssw.name); 173*2621Sllai1 return (1); 174*2621Sllai1 } 175*2621Sllai1 176*2621Sllai1 /* initialize negative cache */ 177*2621Sllai1 sdev_ncache_init(); 178*2621Sllai1 179*2621Sllai1 return (0); 180*2621Sllai1 } 181*2621Sllai1 182*2621Sllai1 /* 183*2621Sllai1 * Both mount point and backing store directory name are 184*2621Sllai1 * passed in from userland 185*2621Sllai1 */ 186*2621Sllai1 static int 187*2621Sllai1 sdev_mount(struct vfs *vfsp, struct vnode *mvp, struct mounta *uap, 188*2621Sllai1 struct cred *cr) 189*2621Sllai1 { 190*2621Sllai1 struct sdev_data *sdev_data; 191*2621Sllai1 struct vnode *avp; 192*2621Sllai1 struct sdev_node *dv; 193*2621Sllai1 struct sdev_mountargs *args = NULL; 194*2621Sllai1 int error = 0; 195*2621Sllai1 dev_t devdev; 196*2621Sllai1 197*2621Sllai1 /* 198*2621Sllai1 * security check 199*2621Sllai1 */ 200*2621Sllai1 if ((secpolicy_fs_mount(cr, mvp, vfsp) != 0) || 201*2621Sllai1 (secpolicy_sys_devices(cr) != 0)) 202*2621Sllai1 return (EPERM); 203*2621Sllai1 204*2621Sllai1 /* 205*2621Sllai1 * Sanity check the mount point 206*2621Sllai1 */ 207*2621Sllai1 if (mvp->v_type != VDIR) 208*2621Sllai1 return (ENOTDIR); 209*2621Sllai1 210*2621Sllai1 /* 211*2621Sllai1 * Sanity Check for overlay mount. 212*2621Sllai1 */ 213*2621Sllai1 mutex_enter(&mvp->v_lock); 214*2621Sllai1 if ((uap->flags & MS_OVERLAY) == 0 && 215*2621Sllai1 (uap->flags & MS_REMOUNT) == 0 && 216*2621Sllai1 (mvp->v_count > 1 || (mvp->v_flag & VROOT))) { 217*2621Sllai1 mutex_exit(&mvp->v_lock); 218*2621Sllai1 return (EBUSY); 219*2621Sllai1 } 220*2621Sllai1 mutex_exit(&mvp->v_lock); 221*2621Sllai1 222*2621Sllai1 args = kmem_zalloc(sizeof (*args), KM_SLEEP); 223*2621Sllai1 224*2621Sllai1 if ((uap->flags & MS_DATA) && 225*2621Sllai1 (uap->datalen != 0 && uap->dataptr != NULL)) { 226*2621Sllai1 /* copy in the arguments */ 227*2621Sllai1 if (error = sdev_copyin_mountargs(uap, args)) 228*2621Sllai1 goto cleanup; 229*2621Sllai1 } 230*2621Sllai1 231*2621Sllai1 /* 232*2621Sllai1 * Sanity check the backing store 233*2621Sllai1 */ 234*2621Sllai1 if (args->sdev_attrdir) { 235*2621Sllai1 /* user supplied an attribute store */ 236*2621Sllai1 if (error = lookupname((char *)(uintptr_t)args->sdev_attrdir, 237*2621Sllai1 UIO_USERSPACE, FOLLOW, NULLVPP, &avp)) { 238*2621Sllai1 cmn_err(CE_NOTE, "/dev fs: lookup on attribute " 239*2621Sllai1 "directory %s failed", 240*2621Sllai1 (char *)(uintptr_t)args->sdev_attrdir); 241*2621Sllai1 goto cleanup; 242*2621Sllai1 } 243*2621Sllai1 244*2621Sllai1 if (avp->v_type != VDIR) { 245*2621Sllai1 VN_RELE(avp); 246*2621Sllai1 error = ENOTDIR; 247*2621Sllai1 goto cleanup; 248*2621Sllai1 } 249*2621Sllai1 } else { 250*2621Sllai1 /* use mountp as the attribute store */ 251*2621Sllai1 avp = mvp; 252*2621Sllai1 VN_HOLD(avp); 253*2621Sllai1 } 254*2621Sllai1 255*2621Sllai1 mutex_enter(&sdev_lock); 256*2621Sllai1 257*2621Sllai1 /* 258*2621Sllai1 * handling installation 259*2621Sllai1 */ 260*2621Sllai1 if (uap->flags & MS_REMOUNT) { 261*2621Sllai1 sdev_data = (struct sdev_data *)vfsp->vfs_data; 262*2621Sllai1 ASSERT(sdev_data); 263*2621Sllai1 264*2621Sllai1 dv = sdev_data->sdev_root; 265*2621Sllai1 ASSERT(dv == dv->sdev_dotdot); 266*2621Sllai1 267*2621Sllai1 /* 268*2621Sllai1 * mark all existing sdev_nodes (except root node) stale 269*2621Sllai1 */ 270*2621Sllai1 sdev_stale(dv); 271*2621Sllai1 272*2621Sllai1 /* Reset previous mountargs */ 273*2621Sllai1 if (sdev_data->sdev_mountargs) { 274*2621Sllai1 kmem_free(sdev_data->sdev_mountargs, 275*2621Sllai1 sizeof (struct sdev_mountargs)); 276*2621Sllai1 } 277*2621Sllai1 sdev_data->sdev_mountargs = args; 278*2621Sllai1 args = NULL; /* so it won't be freed below */ 279*2621Sllai1 280*2621Sllai1 sdev_stale_attrvp = dv->sdev_attrvp; 281*2621Sllai1 dv->sdev_attrvp = avp; 282*2621Sllai1 vfsp->vfs_mtime = ddi_get_time(); 283*2621Sllai1 284*2621Sllai1 mutex_exit(&sdev_lock); 285*2621Sllai1 goto cleanup; /* we're done */ 286*2621Sllai1 } 287*2621Sllai1 288*2621Sllai1 /* 289*2621Sllai1 * Create and initialize the vfs-private data. 290*2621Sllai1 */ 291*2621Sllai1 devdev = makedevice(devmajor, devminor); 292*2621Sllai1 while (vfs_devismounted(devdev)) { 293*2621Sllai1 devminor = (devminor + 1) & MAXMIN32; 294*2621Sllai1 295*2621Sllai1 /* 296*2621Sllai1 * All the minor numbers are used up. 297*2621Sllai1 */ 298*2621Sllai1 if (devminor == 0) { 299*2621Sllai1 mutex_exit(&sdev_lock); 300*2621Sllai1 VN_RELE(avp); 301*2621Sllai1 error = ENODEV; 302*2621Sllai1 goto cleanup; 303*2621Sllai1 } 304*2621Sllai1 305*2621Sllai1 devdev = makedevice(devmajor, devminor); 306*2621Sllai1 } 307*2621Sllai1 308*2621Sllai1 dv = sdev_mkroot(vfsp, devdev, mvp, avp, cr); 309*2621Sllai1 sdev_data = kmem_zalloc(sizeof (struct sdev_data), KM_SLEEP); 310*2621Sllai1 vfsp->vfs_dev = devdev; 311*2621Sllai1 vfsp->vfs_data = (caddr_t)sdev_data; 312*2621Sllai1 vfsp->vfs_fstype = devtype; 313*2621Sllai1 vfsp->vfs_bsize = DEV_BSIZE; 314*2621Sllai1 vfsp->vfs_mtime = ddi_get_time(); 315*2621Sllai1 vfs_make_fsid(&vfsp->vfs_fsid, vfsp->vfs_dev, devtype); 316*2621Sllai1 317*2621Sllai1 ASSERT(dv == dv->sdev_dotdot); 318*2621Sllai1 319*2621Sllai1 sdev_data->sdev_vfsp = vfsp; 320*2621Sllai1 sdev_data->sdev_root = dv; 321*2621Sllai1 sdev_data->sdev_mountargs = args; 322*2621Sllai1 323*2621Sllai1 /* get acl flavor from attribute dir */ 324*2621Sllai1 if (VOP_PATHCONF(avp, _PC_ACL_ENABLED, &sdev_data->sdev_acl_flavor, 325*2621Sllai1 kcred) != 0 || sdev_data->sdev_acl_flavor == 0) 326*2621Sllai1 sdev_data->sdev_acl_flavor = _ACL_ACLENT_ENABLED; 327*2621Sllai1 328*2621Sllai1 args = NULL; /* so it won't be freed below */ 329*2621Sllai1 sdev_insert_mntinfo(sdev_data); 330*2621Sllai1 mutex_exit(&sdev_lock); 331*2621Sllai1 332*2621Sllai1 if (!SDEV_IS_GLOBAL(dv)) { 333*2621Sllai1 ASSERT(sdev_origins); 334*2621Sllai1 dv->sdev_flags &= ~SDEV_GLOBAL; 335*2621Sllai1 dv->sdev_origin = sdev_origins->sdev_root; 336*2621Sllai1 } else { 337*2621Sllai1 sdev_ncache_setup(); 338*2621Sllai1 } 339*2621Sllai1 340*2621Sllai1 sdev_update_timestamps(dv->sdev_attrvp, 341*2621Sllai1 cr, AT_CTIME|AT_MTIME|AT_ATIME); 342*2621Sllai1 343*2621Sllai1 cleanup: 344*2621Sllai1 if (args) 345*2621Sllai1 kmem_free(args, sizeof (*args)); 346*2621Sllai1 return (error); 347*2621Sllai1 } 348*2621Sllai1 349*2621Sllai1 /* 350*2621Sllai1 * unmounting the non-global /dev instances, e.g. when deleting a Kevlar zone. 351*2621Sllai1 */ 352*2621Sllai1 static int 353*2621Sllai1 sdev_unmount(struct vfs *vfsp, int flag, struct cred *cr) 354*2621Sllai1 { 355*2621Sllai1 struct sdev_node *dv; 356*2621Sllai1 int error; 357*2621Sllai1 struct sdev_data *sdev_data, *prev, *next; 358*2621Sllai1 359*2621Sllai1 /* 360*2621Sllai1 * enforce the security policies 361*2621Sllai1 */ 362*2621Sllai1 if ((secpolicy_fs_unmount(cr, vfsp) != 0) || 363*2621Sllai1 (secpolicy_sys_devices(cr) != 0)) 364*2621Sllai1 return (EPERM); 365*2621Sllai1 366*2621Sllai1 if (flag & MS_FORCE) 367*2621Sllai1 return (ENOTSUP); 368*2621Sllai1 369*2621Sllai1 mutex_enter(&sdev_lock); 370*2621Sllai1 dv = VFSTOSDEVFS(vfsp)->sdev_root; 371*2621Sllai1 ASSERT(dv == dv->sdev_dotdot); 372*2621Sllai1 if (SDEVTOV(dv)->v_count > 1) { 373*2621Sllai1 mutex_exit(&sdev_lock); 374*2621Sllai1 return (EBUSY); 375*2621Sllai1 } 376*2621Sllai1 377*2621Sllai1 /* 378*2621Sllai1 * global instance remains mounted 379*2621Sllai1 */ 380*2621Sllai1 if (SDEV_IS_GLOBAL(dv)) { 381*2621Sllai1 mutex_exit(&sdev_lock); 382*2621Sllai1 return (EBUSY); 383*2621Sllai1 } 384*2621Sllai1 mutex_exit(&sdev_lock); 385*2621Sllai1 386*2621Sllai1 /* verify the v_count */ 387*2621Sllai1 if ((error = sdev_cleandir(dv, NULL, 0)) != 0) { 388*2621Sllai1 return (error); 389*2621Sllai1 } 390*2621Sllai1 ASSERT(SDEVTOV(dv)->v_count == 1); 391*2621Sllai1 392*2621Sllai1 /* release hold on root node and destroy it */ 393*2621Sllai1 SDEV_RELE(dv); 394*2621Sllai1 dv->sdev_nlink -= 2; 395*2621Sllai1 sdev_nodedestroy(dv, 0); 396*2621Sllai1 397*2621Sllai1 sdev_data = (struct sdev_data *)vfsp->vfs_data; 398*2621Sllai1 vfsp->vfs_data = (caddr_t)0; 399*2621Sllai1 400*2621Sllai1 /* 401*2621Sllai1 * XXX separate it into sdev_delete_mntinfo() if useful 402*2621Sllai1 */ 403*2621Sllai1 mutex_enter(&sdev_lock); 404*2621Sllai1 prev = sdev_data->sdev_prev; 405*2621Sllai1 next = sdev_data->sdev_next; 406*2621Sllai1 if (prev) 407*2621Sllai1 prev->sdev_next = next; 408*2621Sllai1 else 409*2621Sllai1 sdev_mntinfo = next; 410*2621Sllai1 if (next) 411*2621Sllai1 next->sdev_prev = prev; 412*2621Sllai1 mutex_exit(&sdev_lock); 413*2621Sllai1 414*2621Sllai1 if (sdev_data->sdev_mountargs) { 415*2621Sllai1 kmem_free(sdev_data->sdev_mountargs, 416*2621Sllai1 sizeof (struct sdev_mountargs)); 417*2621Sllai1 } 418*2621Sllai1 kmem_free(sdev_data, sizeof (struct sdev_data)); 419*2621Sllai1 return (0); 420*2621Sllai1 } 421*2621Sllai1 422*2621Sllai1 /* 423*2621Sllai1 * return root vnode for given vfs 424*2621Sllai1 */ 425*2621Sllai1 static int 426*2621Sllai1 sdev_root(struct vfs *vfsp, struct vnode **vpp) 427*2621Sllai1 { 428*2621Sllai1 *vpp = SDEVTOV(VFSTOSDEVFS(vfsp)->sdev_root); 429*2621Sllai1 VN_HOLD(*vpp); 430*2621Sllai1 return (0); 431*2621Sllai1 } 432*2621Sllai1 433*2621Sllai1 /* 434*2621Sllai1 * return 'generic superblock' information to userland. 435*2621Sllai1 * 436*2621Sllai1 * not much that we can usefully admit to here 437*2621Sllai1 */ 438*2621Sllai1 static int 439*2621Sllai1 sdev_statvfs(struct vfs *vfsp, struct statvfs64 *sbp) 440*2621Sllai1 { 441*2621Sllai1 dev32_t d32; 442*2621Sllai1 443*2621Sllai1 bzero(sbp, sizeof (*sbp)); 444*2621Sllai1 sbp->f_frsize = sbp->f_bsize = vfsp->vfs_bsize; 445*2621Sllai1 sbp->f_files = kmem_cache_stat(sdev_node_cache, "alloc"); 446*2621Sllai1 447*2621Sllai1 /* no illusions that free/avail files is relevant to dev */ 448*2621Sllai1 sbp->f_ffree = 0; 449*2621Sllai1 sbp->f_favail = 0; 450*2621Sllai1 451*2621Sllai1 /* no illusions that blocks are relevant to devfs */ 452*2621Sllai1 sbp->f_bfree = 0; 453*2621Sllai1 sbp->f_bavail = 0; 454*2621Sllai1 sbp->f_blocks = 0; 455*2621Sllai1 456*2621Sllai1 (void) cmpldev(&d32, vfsp->vfs_dev); 457*2621Sllai1 sbp->f_fsid = d32; 458*2621Sllai1 (void) strcpy(sbp->f_basetype, vfssw[devtype].vsw_name); 459*2621Sllai1 sbp->f_flag = vf_to_stf(vfsp->vfs_flag); 460*2621Sllai1 sbp->f_namemax = MAXNAMELEN - 1; 461*2621Sllai1 (void) strcpy(sbp->f_fstr, "dev"); 462*2621Sllai1 463*2621Sllai1 return (0); 464*2621Sllai1 } 465*2621Sllai1 466*2621Sllai1 int 467*2621Sllai1 sdev_module_register(char *mod_name, struct devname_ops *dev_ops) 468*2621Sllai1 { 469*2621Sllai1 struct devname_nsmap *map = NULL; 470*2621Sllai1 471*2621Sllai1 if (strcmp(mod_name, DEVNAME_NSCONFIG) == 0) { 472*2621Sllai1 devname_ns_ops = dev_ops; 473*2621Sllai1 return (0); 474*2621Sllai1 } 475*2621Sllai1 476*2621Sllai1 map = sdev_get_nsmap_by_module(mod_name); 477*2621Sllai1 if (map == NULL) 478*2621Sllai1 return (EFAULT); 479*2621Sllai1 480*2621Sllai1 rw_enter(&map->dir_lock, RW_WRITER); 481*2621Sllai1 map->dir_ops = dev_ops; 482*2621Sllai1 rw_exit(&map->dir_lock); 483*2621Sllai1 return (0); 484*2621Sllai1 } 485*2621Sllai1 486*2621Sllai1 static void 487*2621Sllai1 sdev_insert_mntinfo(struct sdev_data *data) 488*2621Sllai1 { 489*2621Sllai1 ASSERT(mutex_owned(&sdev_lock)); 490*2621Sllai1 data->sdev_next = sdev_mntinfo; 491*2621Sllai1 data->sdev_prev = NULL; 492*2621Sllai1 if (sdev_mntinfo) { 493*2621Sllai1 sdev_mntinfo->sdev_prev = data; 494*2621Sllai1 } else { 495*2621Sllai1 sdev_origins = data; 496*2621Sllai1 } 497*2621Sllai1 sdev_mntinfo = data; 498*2621Sllai1 } 499*2621Sllai1 500*2621Sllai1 struct sdev_data * 501*2621Sllai1 sdev_find_mntinfo(char *mntpt) 502*2621Sllai1 { 503*2621Sllai1 struct sdev_data *mntinfo; 504*2621Sllai1 505*2621Sllai1 mutex_enter(&sdev_lock); 506*2621Sllai1 mntinfo = sdev_mntinfo; 507*2621Sllai1 while (mntinfo) { 508*2621Sllai1 if (strcmp(mntpt, mntinfo->sdev_root->sdev_name) == 0) { 509*2621Sllai1 SDEVTOV(mntinfo->sdev_root)->v_count++; 510*2621Sllai1 break; 511*2621Sllai1 } 512*2621Sllai1 mntinfo = mntinfo->sdev_next; 513*2621Sllai1 } 514*2621Sllai1 mutex_exit(&sdev_lock); 515*2621Sllai1 return (mntinfo); 516*2621Sllai1 } 517*2621Sllai1 518*2621Sllai1 void 519*2621Sllai1 sdev_mntinfo_rele(struct sdev_data *mntinfo) 520*2621Sllai1 { 521*2621Sllai1 mutex_enter(&sdev_lock); 522*2621Sllai1 SDEVTOV(mntinfo->sdev_root)->v_count--; 523*2621Sllai1 mutex_exit(&sdev_lock); 524*2621Sllai1 } 525