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.6 (Berkeley) 02/23/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() 33 { 34 35 } 36 37 void 38 kernfs_get_rrootdev() 39 { 40 static int tried = 0; 41 int cmaj; 42 43 if (tried) { 44 /* Already did it once. */ 45 return; 46 } 47 tried = 1; 48 49 if (rootdev == NODEV) 50 return; 51 for (cmaj = 0; cmaj < nchrdev; cmaj++) { 52 rrootdev = makedev(cmaj, minor(rootdev)); 53 if (chrtoblk(rrootdev) == rootdev) 54 return; 55 } 56 rrootdev = NODEV; 57 printf("kernfs_get_rrootdev: no raw root device\n"); 58 } 59 60 /* 61 * Mount the Kernel params filesystem 62 */ 63 kernfs_mount(mp, path, data, ndp, p) 64 struct mount *mp; 65 char *path; 66 caddr_t data; 67 struct nameidata *ndp; 68 struct proc *p; 69 { 70 int error = 0; 71 u_int size; 72 struct kernfs_mount *fmp; 73 struct vnode *rvp; 74 75 #ifdef KERNFS_DIAGNOSTIC 76 printf("kernfs_mount(mp = %x)\n", mp); 77 #endif 78 79 /* 80 * Update is a no-op 81 */ 82 if (mp->mnt_flag & MNT_UPDATE) 83 return (EOPNOTSUPP); 84 85 error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp); /* XXX */ 86 if (error) 87 return (error); 88 89 MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount), 90 M_UFSMNT, M_WAITOK); /* XXX */ 91 rvp->v_type = VDIR; 92 rvp->v_flag |= VROOT; 93 #ifdef KERNFS_DIAGNOSTIC 94 printf("kernfs_mount: root vp = %x\n", rvp); 95 #endif 96 fmp->kf_root = rvp; 97 mp->mnt_flag |= MNT_LOCAL; 98 mp->mnt_data = (qaddr_t) fmp; 99 getnewfsid(mp, MOUNT_KERNFS); 100 101 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 102 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 103 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); 104 bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs")); 105 #ifdef KERNFS_DIAGNOSTIC 106 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname); 107 #endif 108 109 kernfs_get_rrootdev(); 110 return (0); 111 } 112 113 kernfs_start(mp, flags, p) 114 struct mount *mp; 115 int flags; 116 struct proc *p; 117 { 118 return (0); 119 } 120 121 kernfs_unmount(mp, mntflags, p) 122 struct mount *mp; 123 int mntflags; 124 struct proc *p; 125 { 126 int error; 127 int flags = 0; 128 extern int doforce; 129 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root; 130 131 #ifdef KERNFS_DIAGNOSTIC 132 printf("kernfs_unmount(mp = %x)\n", mp); 133 #endif 134 135 if (mntflags & MNT_FORCE) { 136 /* kernfs can never be rootfs so don't check for it */ 137 if (!doforce) 138 return (EINVAL); 139 flags |= FORCECLOSE; 140 } 141 142 /* 143 * Clear out buffer cache. I don't think we 144 * ever get anything cached at this level at the 145 * moment, but who knows... 146 */ 147 if (rootvp->v_usecount > 1) 148 return (EBUSY); 149 #ifdef KERNFS_DIAGNOSTIC 150 printf("kernfs_unmount: calling vflush\n"); 151 #endif 152 if (error = vflush(mp, rootvp, flags)) 153 return (error); 154 155 #ifdef KERNFS_DIAGNOSTIC 156 vprint("kernfs root", rootvp); 157 #endif 158 /* 159 * Release reference on underlying root vnode 160 */ 161 vrele(rootvp); 162 /* 163 * And blow it away for future re-use 164 */ 165 VOP_REVOKE(rootvp, 0); 166 /* 167 * Finally, throw away the kernfs_mount structure 168 */ 169 free(mp->mnt_data, M_UFSMNT); /* XXX */ 170 mp->mnt_data = 0; 171 return 0; 172 } 173 174 kernfs_root(mp, vpp) 175 struct mount *mp; 176 struct vnode **vpp; 177 { 178 struct vnode *vp; 179 180 #ifdef KERNFS_DIAGNOSTIC 181 printf("kernfs_root(mp = %x)\n", mp); 182 #endif 183 184 /* 185 * Return locked reference to root. 186 */ 187 vp = VFSTOKERNFS(mp)->kf_root; 188 VREF(vp); 189 VOP_LOCK(vp); 190 *vpp = vp; 191 return (0); 192 } 193 194 kernfs_quotactl(mp, cmd, uid, arg, p) 195 struct mount *mp; 196 int cmd; 197 uid_t uid; 198 caddr_t arg; 199 struct proc *p; 200 { 201 return (EOPNOTSUPP); 202 } 203 204 kernfs_statfs(mp, sbp, p) 205 struct mount *mp; 206 struct statfs *sbp; 207 struct proc *p; 208 { 209 #ifdef KERNFS_DIAGNOSTIC 210 printf("kernfs_statfs(mp = %x)\n", mp); 211 #endif 212 213 sbp->f_type = MOUNT_KERNFS; 214 sbp->f_flags = 0; 215 sbp->f_bsize = DEV_BSIZE; 216 sbp->f_iosize = DEV_BSIZE; 217 sbp->f_blocks = 2; /* 1K to keep df happy */ 218 sbp->f_bfree = 0; 219 sbp->f_bavail = 0; 220 sbp->f_files = 0; 221 sbp->f_ffree = 0; 222 if (sbp != &mp->mnt_stat) { 223 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 224 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 225 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 226 } 227 return (0); 228 } 229 230 kernfs_sync(mp, waitfor) 231 struct mount *mp; 232 int waitfor; 233 { 234 return (0); 235 } 236 237 /* 238 * Kernfs flat namespace lookup. 239 * Currently unsupported. 240 */ 241 kernfs_vget(mp, ino, vpp) 242 struct mount *mp; 243 ino_t ino; 244 struct vnode **vpp; 245 { 246 247 return (EOPNOTSUPP); 248 } 249 250 251 kernfs_fhtovp(mp, fhp, setgen, vpp) 252 struct mount *mp; 253 struct fid *fhp; 254 int setgen; 255 struct vnode **vpp; 256 { 257 return (EOPNOTSUPP); 258 } 259 260 kernfs_vptofh(vp, fhp) 261 struct vnode *vp; 262 struct fid *fhp; 263 { 264 return (EOPNOTSUPP); 265 } 266 267 struct vfsops kernfs_vfsops = { 268 kernfs_mount, 269 kernfs_start, 270 kernfs_unmount, 271 kernfs_root, 272 kernfs_quotactl, 273 kernfs_statfs, 274 kernfs_sync, 275 kernfs_vget, 276 kernfs_fhtovp, 277 kernfs_vptofh, 278 kernfs_init, 279 }; 280