155344Spendry /*
2*63233Sbostic  * Copyright (c) 1992, 1993
3*63233Sbostic  *	The Regents of the University of California.  All rights reserved.
455344Spendry  * All rights reserved.
555344Spendry  *
655344Spendry  * This code is derived from software donated to Berkeley by
755344Spendry  * Jan-Simon Pendry.
855344Spendry  *
955344Spendry  * %sccs.include.redist.c%
1055344Spendry  *
11*63233Sbostic  *	@(#)kernfs_vfsops.c	8.1 (Berkeley) 06/10/93
1255344Spendry  */
1355344Spendry 
1455344Spendry /*
1555344Spendry  * Kernel params Filesystem
1655344Spendry  */
1755344Spendry 
1855344Spendry #include <sys/param.h>
1955344Spendry #include <sys/systm.h>
2055356Spendry #include <sys/conf.h>
2155344Spendry #include <sys/types.h>
2255344Spendry #include <sys/proc.h>
2355344Spendry #include <sys/vnode.h>
2455344Spendry #include <sys/mount.h>
2555344Spendry #include <sys/namei.h>
2655344Spendry #include <sys/malloc.h>
2755356Spendry 
2855356Spendry #include <miscfs/specfs/specdev.h>
2955344Spendry #include <miscfs/kernfs/kernfs.h>
3055344Spendry 
3155356Spendry struct vnode *rrootvp;
3255356Spendry 
3355356Spendry /*
3455356Spendry  * Create a vnode for a character device.
3555356Spendry  */
3655356Spendry int
3755356Spendry cdevvp(dev, vpp)
3855356Spendry 	dev_t dev;
3955356Spendry 	struct vnode **vpp;
4055356Spendry {
4155356Spendry 	register struct vnode *vp;
4255356Spendry 	struct vnode *nvp;
4355356Spendry 	int error;
4455356Spendry 
4555356Spendry 	if (dev == NODEV)
4655356Spendry 		return (0);
4755356Spendry 	error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp);
4855356Spendry 	if (error) {
4955356Spendry 		*vpp = 0;
5055356Spendry 		return (error);
5155356Spendry 	}
5255356Spendry 	vp = nvp;
5355356Spendry 	vp->v_type = VCHR;
5455356Spendry 	if (nvp = checkalias(vp, dev, (struct mount *)0)) {
5555356Spendry 		vput(vp);
5655356Spendry 		vp = nvp;
5755356Spendry 	}
5855356Spendry 	*vpp = vp;
5955356Spendry 	return (0);
6055356Spendry }
6155356Spendry 
6255344Spendry kernfs_init()
6355344Spendry {
6455356Spendry 	int cmaj;
6555356Spendry 	int bmaj = major(rootdev);
6655821Spendry 	int error = ENXIO;
6755356Spendry 
6855344Spendry #ifdef KERNFS_DIAGNOSTIC
6955344Spendry 	printf("kernfs_init\n");		/* printed during system boot */
7055344Spendry #endif
7155356Spendry 
7255356Spendry 	for (cmaj = 0; cmaj < nchrdev; cmaj++) {
7355356Spendry 		if (cdevsw[cmaj].d_open == bdevsw[bmaj].d_open) {
7455356Spendry 			dev_t cdev = makedev(cmaj, minor(rootdev));
7555356Spendry 			error = cdevvp(cdev, &rrootvp);
7655356Spendry 			if (error == 0)
7755356Spendry 				break;
7855356Spendry 		}
7955356Spendry 	}
8055356Spendry 
8155356Spendry 	if (error) {
8255356Spendry 		printf("kernfs: no raw boot device\n");
8355356Spendry 		rrootvp = 0;
8455356Spendry 	}
8555344Spendry }
8655344Spendry 
8755344Spendry /*
8855344Spendry  * Mount the Kernel params filesystem
8955344Spendry  */
9055344Spendry kernfs_mount(mp, path, data, ndp, p)
9155344Spendry 	struct mount *mp;
9255344Spendry 	char *path;
9355344Spendry 	caddr_t data;
9455344Spendry 	struct nameidata *ndp;
9555344Spendry 	struct proc *p;
9655344Spendry {
9755344Spendry 	int error = 0;
9855344Spendry 	u_int size;
9955344Spendry 	struct kernfs_mount *fmp;
10055344Spendry 	struct vnode *rvp;
10155344Spendry 
10255344Spendry #ifdef KERNFS_DIAGNOSTIC
10355344Spendry 	printf("kernfs_mount(mp = %x)\n", mp);
10455344Spendry #endif
10555344Spendry 
10655344Spendry 	/*
10755344Spendry 	 * Update is a no-op
10855344Spendry 	 */
10955344Spendry 	if (mp->mnt_flag & MNT_UPDATE)
11055344Spendry 		return (EOPNOTSUPP);
11155344Spendry 
11255344Spendry 	error = getnewvnode(VT_UFS, mp, kernfs_vnodeop_p, &rvp);	/* XXX */
11355344Spendry 	if (error)
11455344Spendry 		return (error);
11555344Spendry 
11655344Spendry 	MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount),
11755344Spendry 				M_UFSMNT, M_WAITOK);	/* XXX */
11855344Spendry 	rvp->v_type = VDIR;
11955344Spendry 	rvp->v_flag |= VROOT;
12055344Spendry #ifdef KERNFS_DIAGNOSTIC
12155344Spendry 	printf("kernfs_mount: root vp = %x\n", rvp);
12255344Spendry #endif
12355344Spendry 	fmp->kf_root = rvp;
12455344Spendry 	mp->mnt_flag |= MNT_LOCAL;
12555344Spendry 	mp->mnt_data = (qaddr_t) fmp;
12655344Spendry 	getnewfsid(mp, MOUNT_KERNFS);
12755344Spendry 
12855344Spendry 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
12955344Spendry 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
13055344Spendry 	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
13155344Spendry 	bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs"));
13255344Spendry #ifdef KERNFS_DIAGNOSTIC
13355344Spendry 	printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
13455344Spendry #endif
13555344Spendry 	return (0);
13655344Spendry }
13755344Spendry 
13855344Spendry kernfs_start(mp, flags, p)
13955344Spendry 	struct mount *mp;
14055344Spendry 	int flags;
14155344Spendry 	struct proc *p;
14255344Spendry {
14355344Spendry 	return (0);
14455344Spendry }
14555344Spendry 
14655344Spendry kernfs_unmount(mp, mntflags, p)
14755344Spendry 	struct mount *mp;
14855344Spendry 	int mntflags;
14955344Spendry 	struct proc *p;
15055344Spendry {
15155344Spendry 	int error;
15255344Spendry 	int flags = 0;
15355344Spendry 	extern int doforce;
15455344Spendry 	struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
15555344Spendry 
15655344Spendry #ifdef KERNFS_DIAGNOSTIC
15755344Spendry 	printf("kernfs_unmount(mp = %x)\n", mp);
15855344Spendry #endif
15955344Spendry 
16055344Spendry 	if (mntflags & MNT_FORCE) {
16155344Spendry 		/* kernfs can never be rootfs so don't check for it */
16255344Spendry 		if (!doforce)
16355344Spendry 			return (EINVAL);
16455344Spendry 		flags |= FORCECLOSE;
16555344Spendry 	}
16655344Spendry 
16755344Spendry 	/*
16855344Spendry 	 * Clear out buffer cache.  I don't think we
16955344Spendry 	 * ever get anything cached at this level at the
17055344Spendry 	 * moment, but who knows...
17155344Spendry 	 */
17255344Spendry 	if (rootvp->v_usecount > 1)
17355344Spendry 		return (EBUSY);
17455344Spendry #ifdef KERNFS_DIAGNOSTIC
17555344Spendry 	printf("kernfs_unmount: calling vflush\n");
17655344Spendry #endif
17755344Spendry 	if (error = vflush(mp, rootvp, flags))
17855344Spendry 		return (error);
17955344Spendry 
18055344Spendry #ifdef KERNFS_DIAGNOSTIC
18155344Spendry 	vprint("kernfs root", rootvp);
18255351Spendry #endif
18355344Spendry 	/*
18455344Spendry 	 * Release reference on underlying root vnode
18555344Spendry 	 */
18655344Spendry 	vrele(rootvp);
18755344Spendry 	/*
18855344Spendry 	 * And blow it away for future re-use
18955344Spendry 	 */
19055344Spendry 	vgone(rootvp);
19155344Spendry 	/*
19255344Spendry 	 * Finally, throw away the kernfs_mount structure
19355344Spendry 	 */
19455344Spendry 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
19555344Spendry 	mp->mnt_data = 0;
19655344Spendry 	return 0;
19755344Spendry }
19855344Spendry 
19955344Spendry kernfs_root(mp, vpp)
20055344Spendry 	struct mount *mp;
20155344Spendry 	struct vnode **vpp;
20255344Spendry {
20355344Spendry 	struct vnode *vp;
20455344Spendry 	int error;
20555344Spendry 
20655344Spendry #ifdef KERNFS_DIAGNOSTIC
20755344Spendry 	printf("kernfs_root(mp = %x)\n", mp);
20855344Spendry #endif
20955344Spendry 
21055344Spendry 	/*
21155344Spendry 	 * Return locked reference to root.
21255344Spendry 	 */
21355344Spendry 	vp = VFSTOKERNFS(mp)->kf_root;
21455344Spendry 	VREF(vp);
21555344Spendry 	VOP_LOCK(vp);
21655344Spendry 	*vpp = vp;
21755344Spendry 	return (0);
21855344Spendry }
21955344Spendry 
22055344Spendry kernfs_quotactl(mp, cmd, uid, arg, p)
22155344Spendry 	struct mount *mp;
22255344Spendry 	int cmd;
22355344Spendry 	uid_t uid;
22455344Spendry 	caddr_t arg;
22555344Spendry 	struct proc *p;
22655344Spendry {
22755344Spendry 	return (EOPNOTSUPP);
22855344Spendry }
22955344Spendry 
23055344Spendry kernfs_statfs(mp, sbp, p)
23155344Spendry 	struct mount *mp;
23255344Spendry 	struct statfs *sbp;
23355344Spendry 	struct proc *p;
23455344Spendry {
23555344Spendry #ifdef KERNFS_DIAGNOSTIC
23655344Spendry 	printf("kernfs_statfs(mp = %x)\n", mp);
23755344Spendry #endif
23855344Spendry 
23955344Spendry 	sbp->f_type = MOUNT_KERNFS;
24055344Spendry 	sbp->f_flags = 0;
24155344Spendry 	sbp->f_bsize = DEV_BSIZE;
24255344Spendry 	sbp->f_iosize = DEV_BSIZE;
24355344Spendry 	sbp->f_blocks = 2;		/* 1K to keep df happy */
24455344Spendry 	sbp->f_bfree = 0;
24555344Spendry 	sbp->f_bavail = 0;
24655821Spendry 	sbp->f_files = 0;
24755821Spendry 	sbp->f_ffree = 0;
24855344Spendry 	if (sbp != &mp->mnt_stat) {
24955344Spendry 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
25055344Spendry 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
25155344Spendry 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
25255344Spendry 	}
25355344Spendry 	return (0);
25455344Spendry }
25555344Spendry 
25655344Spendry kernfs_sync(mp, waitfor)
25755344Spendry 	struct mount *mp;
25855344Spendry 	int waitfor;
25955344Spendry {
26055344Spendry 	return (0);
26155344Spendry }
26255344Spendry 
26355344Spendry /*
26455351Spendry  * Kernfs flat namespace lookup.
26555344Spendry  * Currently unsupported.
26655344Spendry  */
26755344Spendry kernfs_vget(mp, ino, vpp)
26855344Spendry 	struct mount *mp;
26955344Spendry 	ino_t ino;
27055344Spendry 	struct vnode **vpp;
27155344Spendry {
27255344Spendry 
27355344Spendry 	return (EOPNOTSUPP);
27455344Spendry }
27555344Spendry 
27655344Spendry 
27755344Spendry kernfs_fhtovp(mp, fhp, setgen, vpp)
27855344Spendry 	struct mount *mp;
27955344Spendry 	struct fid *fhp;
28055344Spendry 	int setgen;
28155344Spendry 	struct vnode **vpp;
28255344Spendry {
28355344Spendry 	return (EOPNOTSUPP);
28455344Spendry }
28555344Spendry 
28655344Spendry kernfs_vptofh(vp, fhp)
28755344Spendry 	struct vnode *vp;
28855344Spendry 	struct fid *fhp;
28955344Spendry {
29055344Spendry 	return (EOPNOTSUPP);
29155344Spendry }
29255344Spendry 
29355344Spendry struct vfsops kernfs_vfsops = {
29455344Spendry 	kernfs_mount,
29555344Spendry 	kernfs_start,
29655344Spendry 	kernfs_unmount,
29755344Spendry 	kernfs_root,
29855344Spendry 	kernfs_quotactl,
29955344Spendry 	kernfs_statfs,
30055344Spendry 	kernfs_sync,
30155344Spendry 	kernfs_vget,
30255344Spendry 	kernfs_fhtovp,
30355344Spendry 	kernfs_vptofh,
30455344Spendry 	kernfs_init,
30555344Spendry };
306