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