155344Spendry /*
255344Spendry  * Copyright (c) 1992 The Regents of the University of California
355344Spendry  * Copyright (c) 1990, 1992 Jan-Simon Pendry
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*55356Spendry  *	@(#)kernfs_vfsops.c	7.3 (Berkeley) 07/19/92
1255344Spendry  */
1355344Spendry 
1455344Spendry /*
1555344Spendry  * Kernel params Filesystem
1655344Spendry  */
1755344Spendry 
1855344Spendry #include <sys/param.h>
1955344Spendry #include <sys/systm.h>
20*55356Spendry #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>
27*55356Spendry 
28*55356Spendry #include <miscfs/specfs/specdev.h>
29*55356Spendry extern int (**spec_vnodeop_p)();
3055344Spendry #include <miscfs/kernfs/kernfs.h>
3155344Spendry 
32*55356Spendry struct vnode *rrootvp;
33*55356Spendry 
34*55356Spendry /*
35*55356Spendry  * Create a vnode for a character device.
36*55356Spendry  */
37*55356Spendry int
38*55356Spendry cdevvp(dev, vpp)
39*55356Spendry 	dev_t dev;
40*55356Spendry 	struct vnode **vpp;
41*55356Spendry {
42*55356Spendry 	register struct vnode *vp;
43*55356Spendry 	struct vnode *nvp;
44*55356Spendry 	int error;
45*55356Spendry 
46*55356Spendry 	if (dev == NODEV)
47*55356Spendry 		return (0);
48*55356Spendry 	error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp);
49*55356Spendry 	if (error) {
50*55356Spendry 		*vpp = 0;
51*55356Spendry 		return (error);
52*55356Spendry 	}
53*55356Spendry 	vp = nvp;
54*55356Spendry 	vp->v_type = VCHR;
55*55356Spendry 	if (nvp = checkalias(vp, dev, (struct mount *)0)) {
56*55356Spendry 		vput(vp);
57*55356Spendry 		vp = nvp;
58*55356Spendry 	}
59*55356Spendry 	*vpp = vp;
60*55356Spendry 	return (0);
61*55356Spendry }
62*55356Spendry 
6355344Spendry kernfs_init()
6455344Spendry {
65*55356Spendry 	int cmaj;
66*55356Spendry 	int bmaj = major(rootdev);
67*55356Spendry 	int error = ENOENT;
68*55356Spendry 
6955344Spendry #ifdef KERNFS_DIAGNOSTIC
7055344Spendry 	printf("kernfs_init\n");		/* printed during system boot */
7155344Spendry #endif
72*55356Spendry 
73*55356Spendry 	for (cmaj = 0; cmaj < nchrdev; cmaj++) {
74*55356Spendry 		if (cdevsw[cmaj].d_open == bdevsw[bmaj].d_open) {
75*55356Spendry 			dev_t cdev = makedev(cmaj, minor(rootdev));
76*55356Spendry 			error = cdevvp(cdev, &rrootvp);
77*55356Spendry 			if (error == 0)
78*55356Spendry 				break;
79*55356Spendry 		}
80*55356Spendry 	}
81*55356Spendry 
82*55356Spendry 	if (error) {
83*55356Spendry 		printf("kernfs: no raw boot device\n");
84*55356Spendry 		rrootvp = 0;
85*55356Spendry 	}
8655344Spendry }
8755344Spendry 
8855344Spendry /*
8955344Spendry  * Mount the Kernel params filesystem
9055344Spendry  */
9155344Spendry kernfs_mount(mp, path, data, ndp, p)
9255344Spendry 	struct mount *mp;
9355344Spendry 	char *path;
9455344Spendry 	caddr_t data;
9555344Spendry 	struct nameidata *ndp;
9655344Spendry 	struct proc *p;
9755344Spendry {
9855344Spendry 	int error = 0;
9955344Spendry 	u_int size;
10055344Spendry 	struct kernfs_mount *fmp;
10155344Spendry 	struct vnode *rvp;
10255344Spendry 
10355344Spendry #ifdef KERNFS_DIAGNOSTIC
10455344Spendry 	printf("kernfs_mount(mp = %x)\n", mp);
10555344Spendry #endif
10655344Spendry 
10755344Spendry 	/*
10855344Spendry 	 * Update is a no-op
10955344Spendry 	 */
11055344Spendry 	if (mp->mnt_flag & MNT_UPDATE)
11155344Spendry 		return (EOPNOTSUPP);
11255344Spendry 
11355344Spendry 	error = getnewvnode(VT_UFS, mp, kernfs_vnodeop_p, &rvp);	/* XXX */
11455344Spendry 	if (error)
11555344Spendry 		return (error);
11655344Spendry 
11755344Spendry 	MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount),
11855344Spendry 				M_UFSMNT, M_WAITOK);	/* XXX */
11955344Spendry 	rvp->v_type = VDIR;
12055344Spendry 	rvp->v_flag |= VROOT;
12155344Spendry #ifdef KERNFS_DIAGNOSTIC
12255344Spendry 	printf("kernfs_mount: root vp = %x\n", rvp);
12355344Spendry #endif
12455344Spendry 	fmp->kf_root = rvp;
12555344Spendry 	mp->mnt_flag |= MNT_LOCAL;
12655344Spendry 	mp->mnt_data = (qaddr_t) fmp;
12755344Spendry 	getnewfsid(mp, MOUNT_KERNFS);
12855344Spendry 
12955344Spendry 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
13055344Spendry 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
13155344Spendry 	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
13255344Spendry 	bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs"));
13355344Spendry #ifdef KERNFS_DIAGNOSTIC
13455344Spendry 	printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
13555344Spendry #endif
13655344Spendry 	return (0);
13755344Spendry }
13855344Spendry 
13955344Spendry kernfs_start(mp, flags, p)
14055344Spendry 	struct mount *mp;
14155344Spendry 	int flags;
14255344Spendry 	struct proc *p;
14355344Spendry {
14455344Spendry 	return (0);
14555344Spendry }
14655344Spendry 
14755344Spendry kernfs_unmount(mp, mntflags, p)
14855344Spendry 	struct mount *mp;
14955344Spendry 	int mntflags;
15055344Spendry 	struct proc *p;
15155344Spendry {
15255344Spendry 	int error;
15355344Spendry 	int flags = 0;
15455344Spendry 	extern int doforce;
15555344Spendry 	struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
15655344Spendry 
15755344Spendry #ifdef KERNFS_DIAGNOSTIC
15855344Spendry 	printf("kernfs_unmount(mp = %x)\n", mp);
15955344Spendry #endif
16055344Spendry 
16155344Spendry 	if (mntflags & MNT_FORCE) {
16255344Spendry 		/* kernfs can never be rootfs so don't check for it */
16355344Spendry 		if (!doforce)
16455344Spendry 			return (EINVAL);
16555344Spendry 		flags |= FORCECLOSE;
16655344Spendry 	}
16755344Spendry 
16855344Spendry 	/*
16955344Spendry 	 * Clear out buffer cache.  I don't think we
17055344Spendry 	 * ever get anything cached at this level at the
17155344Spendry 	 * moment, but who knows...
17255344Spendry 	 */
17355344Spendry #if 0
17455344Spendry #ifdef KERNFS_DIAGNOSTIC
17555344Spendry 	printf("kernfs_unmount: calling mntflushbuf\n");
17655344Spendry #endif
17755351Spendry 	mntflushbuf(mp, 0);
17855344Spendry #ifdef KERNFS_DIAGNOSTIC
17955344Spendry 	printf("kernfs_unmount: calling mntinvalbuf\n");
18055344Spendry #endif
18155344Spendry 	if (mntinvalbuf(mp, 1))
18255344Spendry 		return (EBUSY);
18355344Spendry #endif
18455344Spendry 	if (rootvp->v_usecount > 1)
18555344Spendry 		return (EBUSY);
18655344Spendry #ifdef KERNFS_DIAGNOSTIC
18755344Spendry 	printf("kernfs_unmount: calling vflush\n");
18855344Spendry #endif
18955344Spendry 	if (error = vflush(mp, rootvp, flags))
19055344Spendry 		return (error);
19155344Spendry 
19255344Spendry #ifdef KERNFS_DIAGNOSTIC
19355344Spendry 	vprint("kernfs root", rootvp);
19455351Spendry #endif
19555344Spendry 	/*
19655344Spendry 	 * Release reference on underlying root vnode
19755344Spendry 	 */
19855344Spendry 	vrele(rootvp);
19955344Spendry 	/*
20055344Spendry 	 * And blow it away for future re-use
20155344Spendry 	 */
20255344Spendry 	vgone(rootvp);
20355344Spendry 	/*
20455344Spendry 	 * Finally, throw away the kernfs_mount structure
20555344Spendry 	 */
20655344Spendry 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
20755344Spendry 	mp->mnt_data = 0;
20855344Spendry 	return 0;
20955344Spendry }
21055344Spendry 
21155344Spendry kernfs_root(mp, vpp)
21255344Spendry 	struct mount *mp;
21355344Spendry 	struct vnode **vpp;
21455344Spendry {
21555344Spendry 	struct vnode *vp;
21655344Spendry 	int error;
21755344Spendry 
21855344Spendry #ifdef KERNFS_DIAGNOSTIC
21955344Spendry 	printf("kernfs_root(mp = %x)\n", mp);
22055344Spendry #endif
22155344Spendry 
22255344Spendry 	/*
22355344Spendry 	 * Return locked reference to root.
22455344Spendry 	 */
22555344Spendry 	vp = VFSTOKERNFS(mp)->kf_root;
22655344Spendry 	VREF(vp);
22755344Spendry 	VOP_LOCK(vp);
22855344Spendry 	*vpp = vp;
22955344Spendry 	return (0);
23055344Spendry }
23155344Spendry 
23255344Spendry kernfs_quotactl(mp, cmd, uid, arg, p)
23355344Spendry 	struct mount *mp;
23455344Spendry 	int cmd;
23555344Spendry 	uid_t uid;
23655344Spendry 	caddr_t arg;
23755344Spendry 	struct proc *p;
23855344Spendry {
23955344Spendry 	return (EOPNOTSUPP);
24055344Spendry }
24155344Spendry 
24255344Spendry kernfs_statfs(mp, sbp, p)
24355344Spendry 	struct mount *mp;
24455344Spendry 	struct statfs *sbp;
24555344Spendry 	struct proc *p;
24655344Spendry {
24755344Spendry #ifdef KERNFS_DIAGNOSTIC
24855344Spendry 	printf("kernfs_statfs(mp = %x)\n", mp);
24955344Spendry #endif
25055344Spendry 
25155344Spendry 	sbp->f_type = MOUNT_KERNFS;
25255344Spendry 	sbp->f_flags = 0;
25355344Spendry 	sbp->f_bsize = DEV_BSIZE;
25455344Spendry 	sbp->f_iosize = DEV_BSIZE;
25555344Spendry 	sbp->f_blocks = 2;		/* 1K to keep df happy */
25655344Spendry 	sbp->f_bfree = 0;
25755344Spendry 	sbp->f_bavail = 0;
25855344Spendry 	sbp->f_files = 0;		/* Allow for "." */
25955344Spendry 	sbp->f_ffree = 0;		/* See comments above */
26055344Spendry 	if (sbp != &mp->mnt_stat) {
26155344Spendry 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
26255344Spendry 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
26355344Spendry 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
26455344Spendry 	}
26555344Spendry 	return (0);
26655344Spendry }
26755344Spendry 
26855344Spendry kernfs_sync(mp, waitfor)
26955344Spendry 	struct mount *mp;
27055344Spendry 	int waitfor;
27155344Spendry {
27255344Spendry 	return (0);
27355344Spendry }
27455344Spendry 
27555344Spendry /*
27655351Spendry  * Kernfs flat namespace lookup.
27755344Spendry  * Currently unsupported.
27855344Spendry  */
27955344Spendry kernfs_vget(mp, ino, vpp)
28055344Spendry 	struct mount *mp;
28155344Spendry 	ino_t ino;
28255344Spendry 	struct vnode **vpp;
28355344Spendry {
28455344Spendry 
28555344Spendry 	return (EOPNOTSUPP);
28655344Spendry }
28755344Spendry 
28855344Spendry 
28955344Spendry kernfs_fhtovp(mp, fhp, setgen, vpp)
29055344Spendry 	struct mount *mp;
29155344Spendry 	struct fid *fhp;
29255344Spendry 	int setgen;
29355344Spendry 	struct vnode **vpp;
29455344Spendry {
29555344Spendry 	return (EOPNOTSUPP);
29655344Spendry }
29755344Spendry 
29855344Spendry kernfs_vptofh(vp, fhp)
29955344Spendry 	struct vnode *vp;
30055344Spendry 	struct fid *fhp;
30155344Spendry {
30255344Spendry 	return (EOPNOTSUPP);
30355344Spendry }
30455344Spendry 
30555344Spendry struct vfsops kernfs_vfsops = {
30655344Spendry 	kernfs_mount,
30755344Spendry 	kernfs_start,
30855344Spendry 	kernfs_unmount,
30955344Spendry 	kernfs_root,
31055344Spendry 	kernfs_quotactl,
31155344Spendry 	kernfs_statfs,
31255344Spendry 	kernfs_sync,
31355344Spendry 	kernfs_vget,
31455344Spendry 	kernfs_fhtovp,
31555344Spendry 	kernfs_vptofh,
31655344Spendry 	kernfs_init,
31755344Spendry };
318