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*69336Smckusick * @(#)kernfs_vfsops.c 8.8 (Berkeley) 05/10/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 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 136*69336Smckusick 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 */ 16268426Smckusick VOP_REVOKE(rootvp, 0); 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 { 17555344Spendry struct vnode *vp; 17655344Spendry 17755344Spendry #ifdef KERNFS_DIAGNOSTIC 17855344Spendry printf("kernfs_root(mp = %x)\n", mp); 17955344Spendry #endif 18055344Spendry 18155344Spendry /* 18255344Spendry * Return locked reference to root. 18355344Spendry */ 18455344Spendry vp = VFSTOKERNFS(mp)->kf_root; 18555344Spendry VREF(vp); 18655344Spendry VOP_LOCK(vp); 18755344Spendry *vpp = vp; 18855344Spendry return (0); 18955344Spendry } 19055344Spendry 19155344Spendry kernfs_statfs(mp, sbp, p) 19255344Spendry struct mount *mp; 19355344Spendry struct statfs *sbp; 19455344Spendry struct proc *p; 19555344Spendry { 19655344Spendry #ifdef KERNFS_DIAGNOSTIC 19755344Spendry printf("kernfs_statfs(mp = %x)\n", mp); 19855344Spendry #endif 19955344Spendry 20055344Spendry sbp->f_flags = 0; 20155344Spendry sbp->f_bsize = DEV_BSIZE; 20255344Spendry sbp->f_iosize = DEV_BSIZE; 20355344Spendry sbp->f_blocks = 2; /* 1K to keep df happy */ 20455344Spendry sbp->f_bfree = 0; 20555344Spendry sbp->f_bavail = 0; 20655821Spendry sbp->f_files = 0; 20755821Spendry sbp->f_ffree = 0; 20855344Spendry if (sbp != &mp->mnt_stat) { 20968617Smckusick sbp->f_type = mp->mnt_vfc->vfc_typenum; 21055344Spendry bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 21155344Spendry bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 21255344Spendry bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 21355344Spendry } 21455344Spendry return (0); 21555344Spendry } 21655344Spendry 21755344Spendry struct vfsops kernfs_vfsops = { 21855344Spendry kernfs_mount, 21955344Spendry kernfs_start, 22055344Spendry kernfs_unmount, 22155344Spendry kernfs_root, 22255344Spendry kernfs_quotactl, 22355344Spendry kernfs_statfs, 22455344Spendry kernfs_sync, 22555344Spendry kernfs_vget, 22655344Spendry kernfs_fhtovp, 22755344Spendry kernfs_vptofh, 22855344Spendry kernfs_init, 22968617Smckusick kernfs_sysctl, 23055344Spendry }; 231