155344Spendry /*
263233Sbostic  * Copyright (c) 1992, 1993
363233Sbostic  *	The Regents of the University of California.  All rights reserved.
455344Spendry  *
555344Spendry  * This code is derived from software donated to Berkeley by
655344Spendry  * Jan-Simon Pendry.
755344Spendry  *
855344Spendry  * %sccs.include.redist.c%
955344Spendry  *
10*68426Smckusick  *	@(#)kernfs_vfsops.c	8.6 (Berkeley) 02/23/95
1155344Spendry  */
1255344Spendry 
1355344Spendry /*
1455344Spendry  * Kernel params Filesystem
1555344Spendry  */
1655344Spendry 
1755344Spendry #include <sys/param.h>
1855344Spendry #include <sys/systm.h>
1955356Spendry #include <sys/conf.h>
2055344Spendry #include <sys/types.h>
2155344Spendry #include <sys/proc.h>
2255344Spendry #include <sys/vnode.h>
2355344Spendry #include <sys/mount.h>
2455344Spendry #include <sys/namei.h>
2555344Spendry #include <sys/malloc.h>
2655356Spendry 
2755356Spendry #include <miscfs/specfs/specdev.h>
2855344Spendry #include <miscfs/kernfs/kernfs.h>
2955344Spendry 
3067387Spendry dev_t rrootdev = NODEV;
3155356Spendry 
3267387Spendry kernfs_init()
3355356Spendry {
3455356Spendry 
3555356Spendry }
3655356Spendry 
3767387Spendry void
3867387Spendry kernfs_get_rrootdev()
3955344Spendry {
4067387Spendry 	static int tried = 0;
4155356Spendry 	int cmaj;
4255356Spendry 
4367387Spendry 	if (tried) {
4467387Spendry 		/* Already did it once. */
4567387Spendry 		return;
4667387Spendry 	}
4767387Spendry 	tried = 1;
4855356Spendry 
4967387Spendry 	if (rootdev == NODEV)
5067387Spendry 		return;
5155356Spendry 	for (cmaj = 0; cmaj < nchrdev; cmaj++) {
5267387Spendry 		rrootdev = makedev(cmaj, minor(rootdev));
5367387Spendry 		if (chrtoblk(rrootdev) == rootdev)
5467387Spendry 			return;
5555356Spendry 	}
5667387Spendry 	rrootdev = NODEV;
5767387Spendry 	printf("kernfs_get_rrootdev: no raw root device\n");
5855344Spendry }
5955344Spendry 
6055344Spendry /*
6155344Spendry  * Mount the Kernel params filesystem
6255344Spendry  */
6355344Spendry kernfs_mount(mp, path, data, ndp, p)
6455344Spendry 	struct mount *mp;
6555344Spendry 	char *path;
6655344Spendry 	caddr_t data;
6755344Spendry 	struct nameidata *ndp;
6855344Spendry 	struct proc *p;
6955344Spendry {
7055344Spendry 	int error = 0;
7155344Spendry 	u_int size;
7255344Spendry 	struct kernfs_mount *fmp;
7355344Spendry 	struct vnode *rvp;
7455344Spendry 
7555344Spendry #ifdef KERNFS_DIAGNOSTIC
7655344Spendry 	printf("kernfs_mount(mp = %x)\n", mp);
7755344Spendry #endif
7855344Spendry 
7955344Spendry 	/*
8055344Spendry 	 * Update is a no-op
8155344Spendry 	 */
8255344Spendry 	if (mp->mnt_flag & MNT_UPDATE)
8355344Spendry 		return (EOPNOTSUPP);
8455344Spendry 
8565380Spendry 	error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp);	/* XXX */
8655344Spendry 	if (error)
8755344Spendry 		return (error);
8855344Spendry 
8955344Spendry 	MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount),
9055344Spendry 				M_UFSMNT, M_WAITOK);	/* XXX */
9155344Spendry 	rvp->v_type = VDIR;
9255344Spendry 	rvp->v_flag |= VROOT;
9355344Spendry #ifdef KERNFS_DIAGNOSTIC
9455344Spendry 	printf("kernfs_mount: root vp = %x\n", rvp);
9555344Spendry #endif
9655344Spendry 	fmp->kf_root = rvp;
9755344Spendry 	mp->mnt_flag |= MNT_LOCAL;
9855344Spendry 	mp->mnt_data = (qaddr_t) fmp;
9955344Spendry 	getnewfsid(mp, MOUNT_KERNFS);
10055344Spendry 
10155344Spendry 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
10255344Spendry 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
10355344Spendry 	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
10455344Spendry 	bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs"));
10555344Spendry #ifdef KERNFS_DIAGNOSTIC
10655344Spendry 	printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
10755344Spendry #endif
10867387Spendry 
10967387Spendry 	kernfs_get_rrootdev();
11055344Spendry 	return (0);
11155344Spendry }
11255344Spendry 
11355344Spendry kernfs_start(mp, flags, p)
11455344Spendry 	struct mount *mp;
11555344Spendry 	int flags;
11655344Spendry 	struct proc *p;
11755344Spendry {
11855344Spendry 	return (0);
11955344Spendry }
12055344Spendry 
12155344Spendry kernfs_unmount(mp, mntflags, p)
12255344Spendry 	struct mount *mp;
12355344Spendry 	int mntflags;
12455344Spendry 	struct proc *p;
12555344Spendry {
12655344Spendry 	int error;
12755344Spendry 	int flags = 0;
12855344Spendry 	extern int doforce;
12955344Spendry 	struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
13055344Spendry 
13155344Spendry #ifdef KERNFS_DIAGNOSTIC
13255344Spendry 	printf("kernfs_unmount(mp = %x)\n", mp);
13355344Spendry #endif
13455344Spendry 
13555344Spendry 	if (mntflags & MNT_FORCE) {
13655344Spendry 		/* kernfs can never be rootfs so don't check for it */
13755344Spendry 		if (!doforce)
13855344Spendry 			return (EINVAL);
13955344Spendry 		flags |= FORCECLOSE;
14055344Spendry 	}
14155344Spendry 
14255344Spendry 	/*
14355344Spendry 	 * Clear out buffer cache.  I don't think we
14455344Spendry 	 * ever get anything cached at this level at the
14555344Spendry 	 * moment, but who knows...
14655344Spendry 	 */
14755344Spendry 	if (rootvp->v_usecount > 1)
14855344Spendry 		return (EBUSY);
14955344Spendry #ifdef KERNFS_DIAGNOSTIC
15055344Spendry 	printf("kernfs_unmount: calling vflush\n");
15155344Spendry #endif
15255344Spendry 	if (error = vflush(mp, rootvp, flags))
15355344Spendry 		return (error);
15455344Spendry 
15555344Spendry #ifdef KERNFS_DIAGNOSTIC
15655344Spendry 	vprint("kernfs root", rootvp);
15755351Spendry #endif
15855344Spendry 	/*
15955344Spendry 	 * Release reference on underlying root vnode
16055344Spendry 	 */
16155344Spendry 	vrele(rootvp);
16255344Spendry 	/*
16355344Spendry 	 * And blow it away for future re-use
16455344Spendry 	 */
165*68426Smckusick 	VOP_REVOKE(rootvp, 0);
16655344Spendry 	/*
16755344Spendry 	 * Finally, throw away the kernfs_mount structure
16855344Spendry 	 */
16955344Spendry 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
17055344Spendry 	mp->mnt_data = 0;
17155344Spendry 	return 0;
17255344Spendry }
17355344Spendry 
17455344Spendry kernfs_root(mp, vpp)
17555344Spendry 	struct mount *mp;
17655344Spendry 	struct vnode **vpp;
17755344Spendry {
17855344Spendry 	struct vnode *vp;
17955344Spendry 
18055344Spendry #ifdef KERNFS_DIAGNOSTIC
18155344Spendry 	printf("kernfs_root(mp = %x)\n", mp);
18255344Spendry #endif
18355344Spendry 
18455344Spendry 	/*
18555344Spendry 	 * Return locked reference to root.
18655344Spendry 	 */
18755344Spendry 	vp = VFSTOKERNFS(mp)->kf_root;
18855344Spendry 	VREF(vp);
18955344Spendry 	VOP_LOCK(vp);
19055344Spendry 	*vpp = vp;
19155344Spendry 	return (0);
19255344Spendry }
19355344Spendry 
19455344Spendry kernfs_quotactl(mp, cmd, uid, arg, p)
19555344Spendry 	struct mount *mp;
19655344Spendry 	int cmd;
19755344Spendry 	uid_t uid;
19855344Spendry 	caddr_t arg;
19955344Spendry 	struct proc *p;
20055344Spendry {
20155344Spendry 	return (EOPNOTSUPP);
20255344Spendry }
20355344Spendry 
20455344Spendry kernfs_statfs(mp, sbp, p)
20555344Spendry 	struct mount *mp;
20655344Spendry 	struct statfs *sbp;
20755344Spendry 	struct proc *p;
20855344Spendry {
20955344Spendry #ifdef KERNFS_DIAGNOSTIC
21055344Spendry 	printf("kernfs_statfs(mp = %x)\n", mp);
21155344Spendry #endif
21255344Spendry 
21355344Spendry 	sbp->f_type = MOUNT_KERNFS;
21455344Spendry 	sbp->f_flags = 0;
21555344Spendry 	sbp->f_bsize = DEV_BSIZE;
21655344Spendry 	sbp->f_iosize = DEV_BSIZE;
21755344Spendry 	sbp->f_blocks = 2;		/* 1K to keep df happy */
21855344Spendry 	sbp->f_bfree = 0;
21955344Spendry 	sbp->f_bavail = 0;
22055821Spendry 	sbp->f_files = 0;
22155821Spendry 	sbp->f_ffree = 0;
22255344Spendry 	if (sbp != &mp->mnt_stat) {
22355344Spendry 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
22455344Spendry 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
22555344Spendry 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
22655344Spendry 	}
22755344Spendry 	return (0);
22855344Spendry }
22955344Spendry 
23055344Spendry kernfs_sync(mp, waitfor)
23155344Spendry 	struct mount *mp;
23255344Spendry 	int waitfor;
23355344Spendry {
23455344Spendry 	return (0);
23555344Spendry }
23655344Spendry 
23755344Spendry /*
23855351Spendry  * Kernfs flat namespace lookup.
23955344Spendry  * Currently unsupported.
24055344Spendry  */
24155344Spendry kernfs_vget(mp, ino, vpp)
24255344Spendry 	struct mount *mp;
24355344Spendry 	ino_t ino;
24455344Spendry 	struct vnode **vpp;
24555344Spendry {
24655344Spendry 
24755344Spendry 	return (EOPNOTSUPP);
24855344Spendry }
24955344Spendry 
25055344Spendry 
25155344Spendry kernfs_fhtovp(mp, fhp, setgen, vpp)
25255344Spendry 	struct mount *mp;
25355344Spendry 	struct fid *fhp;
25455344Spendry 	int setgen;
25555344Spendry 	struct vnode **vpp;
25655344Spendry {
25755344Spendry 	return (EOPNOTSUPP);
25855344Spendry }
25955344Spendry 
26055344Spendry kernfs_vptofh(vp, fhp)
26155344Spendry 	struct vnode *vp;
26255344Spendry 	struct fid *fhp;
26355344Spendry {
26455344Spendry 	return (EOPNOTSUPP);
26555344Spendry }
26655344Spendry 
26755344Spendry struct vfsops kernfs_vfsops = {
26855344Spendry 	kernfs_mount,
26955344Spendry 	kernfs_start,
27055344Spendry 	kernfs_unmount,
27155344Spendry 	kernfs_root,
27255344Spendry 	kernfs_quotactl,
27355344Spendry 	kernfs_statfs,
27455344Spendry 	kernfs_sync,
27555344Spendry 	kernfs_vget,
27655344Spendry 	kernfs_fhtovp,
27755344Spendry 	kernfs_vptofh,
27855344Spendry 	kernfs_init,
27955344Spendry };
280