1 /* 2 * Copyright (c) 1992, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software donated to Berkeley by 6 * Jan-Simon Pendry. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)kernfs_vfsops.c 8.9 (Berkeley) 05/10/95 11 */ 12 13 /* 14 * Kernel params Filesystem 15 */ 16 17 #include <sys/param.h> 18 #include <sys/systm.h> 19 #include <sys/conf.h> 20 #include <sys/types.h> 21 #include <sys/proc.h> 22 #include <sys/vnode.h> 23 #include <sys/mount.h> 24 #include <sys/namei.h> 25 #include <sys/malloc.h> 26 27 #include <miscfs/specfs/specdev.h> 28 #include <miscfs/kernfs/kernfs.h> 29 30 dev_t rrootdev = NODEV; 31 32 kernfs_init(vfsp) 33 struct vfsconf *vfsp; 34 { 35 36 return (0); 37 } 38 39 void 40 kernfs_get_rrootdev() 41 { 42 static int tried = 0; 43 int cmaj; 44 45 if (tried) { 46 /* Already did it once. */ 47 return; 48 } 49 tried = 1; 50 51 if (rootdev == NODEV) 52 return; 53 for (cmaj = 0; cmaj < nchrdev; cmaj++) { 54 rrootdev = makedev(cmaj, minor(rootdev)); 55 if (chrtoblk(rrootdev) == rootdev) 56 return; 57 } 58 rrootdev = NODEV; 59 printf("kernfs_get_rrootdev: no raw root device\n"); 60 } 61 62 /* 63 * Mount the Kernel params filesystem 64 */ 65 kernfs_mount(mp, path, data, ndp, p) 66 struct mount *mp; 67 char *path; 68 caddr_t data; 69 struct nameidata *ndp; 70 struct proc *p; 71 { 72 int error = 0; 73 u_int size; 74 struct kernfs_mount *fmp; 75 struct vnode *rvp; 76 77 #ifdef KERNFS_DIAGNOSTIC 78 printf("kernfs_mount(mp = %x)\n", mp); 79 #endif 80 81 /* 82 * Update is a no-op 83 */ 84 if (mp->mnt_flag & MNT_UPDATE) 85 return (EOPNOTSUPP); 86 87 error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp); /* XXX */ 88 if (error) 89 return (error); 90 91 MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount), 92 M_UFSMNT, M_WAITOK); /* XXX */ 93 rvp->v_type = VDIR; 94 rvp->v_flag |= VROOT; 95 #ifdef KERNFS_DIAGNOSTIC 96 printf("kernfs_mount: root vp = %x\n", rvp); 97 #endif 98 fmp->kf_root = rvp; 99 mp->mnt_flag |= MNT_LOCAL; 100 mp->mnt_data = (qaddr_t) fmp; 101 vfs_getnewfsid(mp); 102 103 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 104 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 105 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); 106 bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs")); 107 #ifdef KERNFS_DIAGNOSTIC 108 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname); 109 #endif 110 111 kernfs_get_rrootdev(); 112 return (0); 113 } 114 115 kernfs_start(mp, flags, p) 116 struct mount *mp; 117 int flags; 118 struct proc *p; 119 { 120 return (0); 121 } 122 123 kernfs_unmount(mp, mntflags, p) 124 struct mount *mp; 125 int mntflags; 126 struct proc *p; 127 { 128 int error; 129 int flags = 0; 130 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root; 131 132 #ifdef KERNFS_DIAGNOSTIC 133 printf("kernfs_unmount(mp = %x)\n", mp); 134 #endif 135 136 if (mntflags & MNT_FORCE) 137 flags |= FORCECLOSE; 138 139 /* 140 * Clear out buffer cache. I don't think we 141 * ever get anything cached at this level at the 142 * moment, but who knows... 143 */ 144 if (rootvp->v_usecount > 1) 145 return (EBUSY); 146 #ifdef KERNFS_DIAGNOSTIC 147 printf("kernfs_unmount: calling vflush\n"); 148 #endif 149 if (error = vflush(mp, rootvp, flags)) 150 return (error); 151 152 #ifdef KERNFS_DIAGNOSTIC 153 vprint("kernfs root", rootvp); 154 #endif 155 /* 156 * Release reference on underlying root vnode 157 */ 158 vrele(rootvp); 159 /* 160 * And blow it away for future re-use 161 */ 162 vgone(rootvp); 163 /* 164 * Finally, throw away the kernfs_mount structure 165 */ 166 free(mp->mnt_data, M_UFSMNT); /* XXX */ 167 mp->mnt_data = 0; 168 return 0; 169 } 170 171 kernfs_root(mp, vpp) 172 struct mount *mp; 173 struct vnode **vpp; 174 { 175 struct vnode *vp; 176 177 #ifdef KERNFS_DIAGNOSTIC 178 printf("kernfs_root(mp = %x)\n", mp); 179 #endif 180 181 /* 182 * Return locked reference to root. 183 */ 184 vp = VFSTOKERNFS(mp)->kf_root; 185 VREF(vp); 186 VOP_LOCK(vp); 187 *vpp = vp; 188 return (0); 189 } 190 191 kernfs_statfs(mp, sbp, p) 192 struct mount *mp; 193 struct statfs *sbp; 194 struct proc *p; 195 { 196 #ifdef KERNFS_DIAGNOSTIC 197 printf("kernfs_statfs(mp = %x)\n", mp); 198 #endif 199 200 sbp->f_flags = 0; 201 sbp->f_bsize = DEV_BSIZE; 202 sbp->f_iosize = DEV_BSIZE; 203 sbp->f_blocks = 2; /* 1K to keep df happy */ 204 sbp->f_bfree = 0; 205 sbp->f_bavail = 0; 206 sbp->f_files = 0; 207 sbp->f_ffree = 0; 208 if (sbp != &mp->mnt_stat) { 209 sbp->f_type = mp->mnt_vfc->vfc_typenum; 210 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 211 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 212 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 213 } 214 return (0); 215 } 216 217 struct vfsops kernfs_vfsops = { 218 kernfs_mount, 219 kernfs_start, 220 kernfs_unmount, 221 kernfs_root, 222 kernfs_quotactl, 223 kernfs_statfs, 224 kernfs_sync, 225 kernfs_vget, 226 kernfs_fhtovp, 227 kernfs_vptofh, 228 kernfs_init, 229 kernfs_sysctl, 230 }; 231