1 /* 2 * Copyright (c) 1992, 1993 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.7 (Berkeley) 03/29/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 extern int doforce; 131 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root; 132 133 #ifdef KERNFS_DIAGNOSTIC 134 printf("kernfs_unmount(mp = %x)\n", mp); 135 #endif 136 137 if (mntflags & MNT_FORCE) { 138 /* kernfs can never be rootfs so don't check for it */ 139 if (!doforce) 140 return (EINVAL); 141 flags |= FORCECLOSE; 142 } 143 144 /* 145 * Clear out buffer cache. I don't think we 146 * ever get anything cached at this level at the 147 * moment, but who knows... 148 */ 149 if (rootvp->v_usecount > 1) 150 return (EBUSY); 151 #ifdef KERNFS_DIAGNOSTIC 152 printf("kernfs_unmount: calling vflush\n"); 153 #endif 154 if (error = vflush(mp, rootvp, flags)) 155 return (error); 156 157 #ifdef KERNFS_DIAGNOSTIC 158 vprint("kernfs root", rootvp); 159 #endif 160 /* 161 * Release reference on underlying root vnode 162 */ 163 vrele(rootvp); 164 /* 165 * And blow it away for future re-use 166 */ 167 VOP_REVOKE(rootvp, 0); 168 /* 169 * Finally, throw away the kernfs_mount structure 170 */ 171 free(mp->mnt_data, M_UFSMNT); /* XXX */ 172 mp->mnt_data = 0; 173 return 0; 174 } 175 176 kernfs_root(mp, vpp) 177 struct mount *mp; 178 struct vnode **vpp; 179 { 180 struct vnode *vp; 181 182 #ifdef KERNFS_DIAGNOSTIC 183 printf("kernfs_root(mp = %x)\n", mp); 184 #endif 185 186 /* 187 * Return locked reference to root. 188 */ 189 vp = VFSTOKERNFS(mp)->kf_root; 190 VREF(vp); 191 VOP_LOCK(vp); 192 *vpp = vp; 193 return (0); 194 } 195 196 kernfs_statfs(mp, sbp, p) 197 struct mount *mp; 198 struct statfs *sbp; 199 struct proc *p; 200 { 201 #ifdef KERNFS_DIAGNOSTIC 202 printf("kernfs_statfs(mp = %x)\n", mp); 203 #endif 204 205 sbp->f_flags = 0; 206 sbp->f_bsize = DEV_BSIZE; 207 sbp->f_iosize = DEV_BSIZE; 208 sbp->f_blocks = 2; /* 1K to keep df happy */ 209 sbp->f_bfree = 0; 210 sbp->f_bavail = 0; 211 sbp->f_files = 0; 212 sbp->f_ffree = 0; 213 if (sbp != &mp->mnt_stat) { 214 sbp->f_type = mp->mnt_vfc->vfc_typenum; 215 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 216 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 217 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 218 } 219 return (0); 220 } 221 222 struct vfsops kernfs_vfsops = { 223 kernfs_mount, 224 kernfs_start, 225 kernfs_unmount, 226 kernfs_root, 227 kernfs_quotactl, 228 kernfs_statfs, 229 kernfs_sync, 230 kernfs_vget, 231 kernfs_fhtovp, 232 kernfs_vptofh, 233 kernfs_init, 234 kernfs_sysctl, 235 }; 236