155344Spendry /*
269359Spendry * Copyright (c) 1992, 1993, 1995
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*69436Smckusick * @(#)kernfs_vfsops.c 8.10 (Berkeley) 05/14/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
3268617Smckusick kernfs_init(vfsp)
3368617Smckusick struct vfsconf *vfsp;
3455356Spendry {
3555356Spendry
3668617Smckusick return (0);
3755356Spendry }
3855356Spendry
3967387Spendry void
kernfs_get_rrootdev()4067387Spendry kernfs_get_rrootdev()
4155344Spendry {
4267387Spendry static int tried = 0;
4355356Spendry int cmaj;
4455356Spendry
4567387Spendry if (tried) {
4667387Spendry /* Already did it once. */
4767387Spendry return;
4867387Spendry }
4967387Spendry tried = 1;
5055356Spendry
5167387Spendry if (rootdev == NODEV)
5267387Spendry return;
5355356Spendry for (cmaj = 0; cmaj < nchrdev; cmaj++) {
5467387Spendry rrootdev = makedev(cmaj, minor(rootdev));
5567387Spendry if (chrtoblk(rrootdev) == rootdev)
5667387Spendry return;
5755356Spendry }
5867387Spendry rrootdev = NODEV;
5967387Spendry printf("kernfs_get_rrootdev: no raw root device\n");
6055344Spendry }
6155344Spendry
6255344Spendry /*
6355344Spendry * Mount the Kernel params filesystem
6455344Spendry */
6555344Spendry kernfs_mount(mp, path, data, ndp, p)
6655344Spendry struct mount *mp;
6755344Spendry char *path;
6855344Spendry caddr_t data;
6955344Spendry struct nameidata *ndp;
7055344Spendry struct proc *p;
7155344Spendry {
7255344Spendry int error = 0;
7355344Spendry u_int size;
7455344Spendry struct kernfs_mount *fmp;
7555344Spendry struct vnode *rvp;
7655344Spendry
7755344Spendry #ifdef KERNFS_DIAGNOSTIC
7855344Spendry printf("kernfs_mount(mp = %x)\n", mp);
7955344Spendry #endif
8055344Spendry
8155344Spendry /*
8255344Spendry * Update is a no-op
8355344Spendry */
8455344Spendry if (mp->mnt_flag & MNT_UPDATE)
8555344Spendry return (EOPNOTSUPP);
8655344Spendry
8765380Spendry error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp); /* XXX */
8855344Spendry if (error)
8955344Spendry return (error);
9055344Spendry
9155344Spendry MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount),
9255344Spendry M_UFSMNT, M_WAITOK); /* XXX */
9355344Spendry rvp->v_type = VDIR;
9455344Spendry rvp->v_flag |= VROOT;
9555344Spendry #ifdef KERNFS_DIAGNOSTIC
9655344Spendry printf("kernfs_mount: root vp = %x\n", rvp);
9755344Spendry #endif
9855344Spendry fmp->kf_root = rvp;
9955344Spendry mp->mnt_flag |= MNT_LOCAL;
10055344Spendry mp->mnt_data = (qaddr_t) fmp;
10168617Smckusick vfs_getnewfsid(mp);
10255344Spendry
10355344Spendry (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
10455344Spendry bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
10555344Spendry bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
10655344Spendry bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs"));
10755344Spendry #ifdef KERNFS_DIAGNOSTIC
10855344Spendry printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
10955344Spendry #endif
11067387Spendry
11167387Spendry kernfs_get_rrootdev();
11255344Spendry return (0);
11355344Spendry }
11455344Spendry
11555344Spendry kernfs_start(mp, flags, p)
11655344Spendry struct mount *mp;
11755344Spendry int flags;
11855344Spendry struct proc *p;
11955344Spendry {
12055344Spendry return (0);
12155344Spendry }
12255344Spendry
12355344Spendry kernfs_unmount(mp, mntflags, p)
12455344Spendry struct mount *mp;
12555344Spendry int mntflags;
12655344Spendry struct proc *p;
12755344Spendry {
12855344Spendry int error;
12955344Spendry int flags = 0;
13055344Spendry struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
13155344Spendry
13255344Spendry #ifdef KERNFS_DIAGNOSTIC
13355344Spendry printf("kernfs_unmount(mp = %x)\n", mp);
13455344Spendry #endif
13555344Spendry
13669336Smckusick if (mntflags & MNT_FORCE)
13755344Spendry flags |= FORCECLOSE;
13855344Spendry
13955344Spendry /*
14055344Spendry * Clear out buffer cache. I don't think we
14155344Spendry * ever get anything cached at this level at the
14255344Spendry * moment, but who knows...
14355344Spendry */
14455344Spendry if (rootvp->v_usecount > 1)
14555344Spendry return (EBUSY);
14655344Spendry #ifdef KERNFS_DIAGNOSTIC
14755344Spendry printf("kernfs_unmount: calling vflush\n");
14855344Spendry #endif
14955344Spendry if (error = vflush(mp, rootvp, flags))
15055344Spendry return (error);
15155344Spendry
15255344Spendry #ifdef KERNFS_DIAGNOSTIC
15355344Spendry vprint("kernfs root", rootvp);
15455351Spendry #endif
15555344Spendry /*
15655344Spendry * Release reference on underlying root vnode
15755344Spendry */
15855344Spendry vrele(rootvp);
15955344Spendry /*
16055344Spendry * And blow it away for future re-use
16155344Spendry */
16269359Spendry vgone(rootvp);
16355344Spendry /*
16455344Spendry * Finally, throw away the kernfs_mount structure
16555344Spendry */
16655344Spendry free(mp->mnt_data, M_UFSMNT); /* XXX */
16755344Spendry mp->mnt_data = 0;
16855344Spendry return 0;
16955344Spendry }
17055344Spendry
17155344Spendry kernfs_root(mp, vpp)
17255344Spendry struct mount *mp;
17355344Spendry struct vnode **vpp;
17455344Spendry {
175*69436Smckusick struct proc *p = curproc; /* XXX */
17655344Spendry struct vnode *vp;
17755344Spendry
17855344Spendry #ifdef KERNFS_DIAGNOSTIC
17955344Spendry printf("kernfs_root(mp = %x)\n", mp);
18055344Spendry #endif
18155344Spendry
18255344Spendry /*
18355344Spendry * Return locked reference to root.
18455344Spendry */
18555344Spendry vp = VFSTOKERNFS(mp)->kf_root;
18655344Spendry VREF(vp);
187*69436Smckusick vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
18855344Spendry *vpp = vp;
18955344Spendry return (0);
19055344Spendry }
19155344Spendry
19255344Spendry kernfs_statfs(mp, sbp, p)
19355344Spendry struct mount *mp;
19455344Spendry struct statfs *sbp;
19555344Spendry struct proc *p;
19655344Spendry {
19755344Spendry #ifdef KERNFS_DIAGNOSTIC
19855344Spendry printf("kernfs_statfs(mp = %x)\n", mp);
19955344Spendry #endif
20055344Spendry
20155344Spendry sbp->f_flags = 0;
20255344Spendry sbp->f_bsize = DEV_BSIZE;
20355344Spendry sbp->f_iosize = DEV_BSIZE;
20455344Spendry sbp->f_blocks = 2; /* 1K to keep df happy */
20555344Spendry sbp->f_bfree = 0;
20655344Spendry sbp->f_bavail = 0;
20755821Spendry sbp->f_files = 0;
20855821Spendry sbp->f_ffree = 0;
20955344Spendry if (sbp != &mp->mnt_stat) {
21068617Smckusick sbp->f_type = mp->mnt_vfc->vfc_typenum;
21155344Spendry bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
21255344Spendry bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
21355344Spendry bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
21455344Spendry }
21555344Spendry return (0);
21655344Spendry }
21755344Spendry
21855344Spendry struct vfsops kernfs_vfsops = {
21955344Spendry kernfs_mount,
22055344Spendry kernfs_start,
22155344Spendry kernfs_unmount,
22255344Spendry kernfs_root,
22355344Spendry kernfs_quotactl,
22455344Spendry kernfs_statfs,
22555344Spendry kernfs_sync,
22655344Spendry kernfs_vget,
22755344Spendry kernfs_fhtovp,
22855344Spendry kernfs_vptofh,
22955344Spendry kernfs_init,
23068617Smckusick kernfs_sysctl,
23155344Spendry };
232