Exemple #1
0
/*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);
}
Exemple #2
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);
}
Exemple #3
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);
}
Exemple #4
0
/*
 * 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);
}