/*ARGSUSED*/ static int mod_infofs(struct modlfs *modl, struct modlinkage *modlp, int *p0) { struct vfssw *vswp; RLOCK_VFSSW(); if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL) *p0 = -1; else { *p0 = vswp - vfssw; vfs_unrefvfssw(vswp); } RUNLOCK_VFSSW(); return (0); }
/* * Remove a filesystem */ static int mod_removefs(struct modlfs *modl, struct modlinkage *modlp) { struct vfssw *vswp; struct modctl *mcp; char *modname; if (moddebug & MODDEBUG_NOAUL_FS) return (EBUSY); WLOCK_VFSSW(); if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL) { mcp = mod_getctl(modlp); ASSERT(mcp != NULL); modname = mcp->mod_modname; WUNLOCK_VFSSW(); cmn_err(CE_WARN, uninstall_err, modname); return (EINVAL); } if (vswp->vsw_count != 1) { vfs_unrefvfssw(vswp); WUNLOCK_VFSSW(); return (EBUSY); } /* XXX - Shouldn't the refcount be sufficient? */ if (vfs_opsinuse(&vswp->vsw_vfsops)) { vfs_unrefvfssw(vswp); WUNLOCK_VFSSW(); return (EBUSY); } vfs_freeopttbl(&vswp->vsw_optproto); vswp->vsw_optproto.mo_count = 0; vswp->vsw_flag = 0; vswp->vsw_init = NULL; vfs_unrefvfssw(vswp); WUNLOCK_VFSSW(); return (0); }
/*ARGSUSED1*/ static int mod_installfs(struct modlfs *modl, struct modlinkage *modlp) { struct vfssw *vswp; struct modctl *mcp; char *fsname; char ksname[KSTAT_STRLEN + 1]; int fstype; /* index into vfssw[] and vsanchor_fstype[] */ int allocated; int err; int vsw_stats_enabled; /* Not for public consumption so these aren't in a header file */ extern int vopstats_enabled; extern vopstats_t **vopstats_fstype; extern kstat_t *new_vskstat(char *, vopstats_t *); extern void initialize_vopstats(vopstats_t *); if (modl->fs_vfsdef->def_version == VFSDEF_VERSION) { /* Version matched */ fsname = modl->fs_vfsdef->name; } else { if ((modl->fs_vfsdef->def_version > 0) && (modl->fs_vfsdef->def_version < VFSDEF_VERSION)) { /* Older VFSDEF_VERSION */ fsname = modl->fs_vfsdef->name; } else if ((mcp = mod_getctl(modlp)) != NULL) { /* Pre-VFSDEF_VERSION */ fsname = mcp->mod_modname; } else { /* If all else fails... */ fsname = "<unknown file system type>"; } cmn_err(CE_WARN, "file system '%s' version mismatch", fsname); return (ENXIO); } allocated = 0; WLOCK_VFSSW(); if ((vswp = vfs_getvfsswbyname(fsname)) == NULL) { if ((vswp = allocate_vfssw(fsname)) == NULL) { WUNLOCK_VFSSW(); /* * See 1095689. If this message appears, then * we either need to make the vfssw table bigger * statically, or make it grow dynamically. */ cmn_err(CE_WARN, "no room for '%s' in vfssw!", fsname); return (ENXIO); } allocated = 1; } ASSERT(vswp != NULL); fstype = vswp - vfssw; /* Pointer arithmetic to get the fstype */ /* Turn on everything by default *except* VSW_STATS */ vswp->vsw_flag = modl->fs_vfsdef->flags & ~(VSW_STATS); if (modl->fs_vfsdef->flags & VSW_HASPROTO) { vfs_mergeopttbl(&vfs_mntopts, modl->fs_vfsdef->optproto, &vswp->vsw_optproto); } else { vfs_copyopttbl(&vfs_mntopts, &vswp->vsw_optproto); } if (modl->fs_vfsdef->flags & VSW_CANRWRO) { /* * This obviously implies VSW_CANREMOUNT. */ vswp->vsw_flag |= VSW_CANREMOUNT; } /* * If stats are enabled system wide and for this fstype, then * set the VSW_STATS flag in the proper vfssw[] table entry. */ if (vopstats_enabled && modl->fs_vfsdef->flags & VSW_STATS) { vswp->vsw_flag |= VSW_STATS; } if (modl->fs_vfsdef->init == NULL) err = EFAULT; else err = (*(modl->fs_vfsdef->init))(fstype, fsname); if (err != 0) { if (allocated) { kmem_free(vswp->vsw_name, strlen(vswp->vsw_name)+1); vswp->vsw_name = ""; } vswp->vsw_flag = 0; vswp->vsw_init = NULL; } /* We don't want to hold the vfssw[] write lock over a kmem_alloc() */ vsw_stats_enabled = vswp->vsw_flag & VSW_STATS; vfs_unrefvfssw(vswp); WUNLOCK_VFSSW(); /* If everything is on, set up the per-fstype vopstats */ if (vsw_stats_enabled && vopstats_enabled && vopstats_fstype && vopstats_fstype[fstype] == NULL) { (void) strlcpy(ksname, VOPSTATS_STR, sizeof (ksname)); (void) strlcat(ksname, vfssw[fstype].vsw_name, sizeof (ksname)); vopstats_fstype[fstype] = kmem_alloc(sizeof (vopstats_t), KM_SLEEP); initialize_vopstats(vopstats_fstype[fstype]); (void) new_vskstat(ksname, vopstats_fstype[fstype]); } return (err); }
/* * Configure root file system. */ int rootconf(void) { int error; struct vfssw *vsw; extern void pm_init(void); BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype)); BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name)); BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags)); BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath)); /* * Install cluster modules that were only loaded during * loadrootmodules(). */ if (error = clboot_rootconf()) return (error); if (root_is_svm) { (void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME); BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name)); BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath)); } /* * Run _init on the root filesystem (we already loaded it * but we've been waiting until now to _init it) which will * have the side-effect of running vsw_init() on this vfs. * Because all the nfs filesystems are lumped into one * module we need to special case it. */ if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { if (modload("fs", "nfs") == -1) { cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", rootfs.bo_fstype); return (ENXIO); } } else { if (modload("fs", rootfs.bo_fstype) == -1) { cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", rootfs.bo_fstype); return (ENXIO); } } RLOCK_VFSSW(); vsw = vfs_getvfsswbyname(rootfs.bo_fstype); RUNLOCK_VFSSW(); VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0); VFS_HOLD(rootvfs); if (root_is_svm) { rootvfs->vfs_flag |= VFS_RDONLY; } /* * This pm-releated call has to occur before root is mounted since we * need to power up all devices. It is placed after VFS_INIT() such * that opening a device via ddi_lyr_ interface just before root has * been mounted would work. */ pm_init(); if (netboot) { if ((error = strplumb()) != 0) { cmn_err(CE_CONT, "Cannot plumb network device\n"); return (error); } } /* * ufs_mountroot() ends up calling getrootdev() * (below) which actually triggers the _init, identify, * probe and attach of the drivers that make up root device * bush; these are also quietly waiting in memory. */ BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype)); error = VFS_MOUNTROOT(rootvfs, ROOT_INIT); vfs_unrefvfssw(vsw); rootdev = rootvfs->vfs_dev; if (error) cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n", rootfs.bo_name, rootfs.bo_fstype); else cmn_err(CE_CONT, "?root on %s fstype %s\n", rootfs.bo_name, rootfs.bo_fstype); return (error); }