1 /* 2 * Copyright (c) 1992 The Regents of the University of California 3 * Copyright (c) 1990, 1992 Jan-Simon Pendry 4 * All rights reserved. 5 * 6 * This code is derived from software donated to Berkeley by 7 * Jan-Simon Pendry. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)kernfs_vfsops.c 7.4 (Berkeley) 08/01/92 12 */ 13 14 /* 15 * Kernel params Filesystem 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/conf.h> 21 #include <sys/types.h> 22 #include <sys/proc.h> 23 #include <sys/vnode.h> 24 #include <sys/mount.h> 25 #include <sys/namei.h> 26 #include <sys/malloc.h> 27 28 #include <miscfs/specfs/specdev.h> 29 #include <miscfs/kernfs/kernfs.h> 30 31 struct vnode *rrootvp; 32 33 /* 34 * Create a vnode for a character device. 35 */ 36 int 37 cdevvp(dev, vpp) 38 dev_t dev; 39 struct vnode **vpp; 40 { 41 register struct vnode *vp; 42 struct vnode *nvp; 43 int error; 44 45 if (dev == NODEV) 46 return (0); 47 error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp); 48 if (error) { 49 *vpp = 0; 50 return (error); 51 } 52 vp = nvp; 53 vp->v_type = VCHR; 54 if (nvp = checkalias(vp, dev, (struct mount *)0)) { 55 vput(vp); 56 vp = nvp; 57 } 58 *vpp = vp; 59 return (0); 60 } 61 62 kernfs_init() 63 { 64 int cmaj; 65 int bmaj = major(rootdev); 66 int error = ENOENT; 67 68 #ifdef KERNFS_DIAGNOSTIC 69 printf("kernfs_init\n"); /* printed during system boot */ 70 #endif 71 72 for (cmaj = 0; cmaj < nchrdev; cmaj++) { 73 if (cdevsw[cmaj].d_open == bdevsw[bmaj].d_open) { 74 dev_t cdev = makedev(cmaj, minor(rootdev)); 75 error = cdevvp(cdev, &rrootvp); 76 if (error == 0) 77 break; 78 } 79 } 80 81 if (error) { 82 printf("kernfs: no raw boot device\n"); 83 rrootvp = 0; 84 } 85 } 86 87 /* 88 * Mount the Kernel params filesystem 89 */ 90 kernfs_mount(mp, path, data, ndp, p) 91 struct mount *mp; 92 char *path; 93 caddr_t data; 94 struct nameidata *ndp; 95 struct proc *p; 96 { 97 int error = 0; 98 u_int size; 99 struct kernfs_mount *fmp; 100 struct vnode *rvp; 101 102 #ifdef KERNFS_DIAGNOSTIC 103 printf("kernfs_mount(mp = %x)\n", mp); 104 #endif 105 106 /* 107 * Update is a no-op 108 */ 109 if (mp->mnt_flag & MNT_UPDATE) 110 return (EOPNOTSUPP); 111 112 error = getnewvnode(VT_UFS, mp, kernfs_vnodeop_p, &rvp); /* XXX */ 113 if (error) 114 return (error); 115 116 MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount), 117 M_UFSMNT, M_WAITOK); /* XXX */ 118 rvp->v_type = VDIR; 119 rvp->v_flag |= VROOT; 120 #ifdef KERNFS_DIAGNOSTIC 121 printf("kernfs_mount: root vp = %x\n", rvp); 122 #endif 123 fmp->kf_root = rvp; 124 mp->mnt_flag |= MNT_LOCAL; 125 mp->mnt_data = (qaddr_t) fmp; 126 getnewfsid(mp, MOUNT_KERNFS); 127 128 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 129 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 130 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); 131 bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs")); 132 #ifdef KERNFS_DIAGNOSTIC 133 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname); 134 #endif 135 return (0); 136 } 137 138 kernfs_start(mp, flags, p) 139 struct mount *mp; 140 int flags; 141 struct proc *p; 142 { 143 return (0); 144 } 145 146 kernfs_unmount(mp, mntflags, p) 147 struct mount *mp; 148 int mntflags; 149 struct proc *p; 150 { 151 int error; 152 int flags = 0; 153 extern int doforce; 154 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root; 155 156 #ifdef KERNFS_DIAGNOSTIC 157 printf("kernfs_unmount(mp = %x)\n", mp); 158 #endif 159 160 if (mntflags & MNT_FORCE) { 161 /* kernfs can never be rootfs so don't check for it */ 162 if (!doforce) 163 return (EINVAL); 164 flags |= FORCECLOSE; 165 } 166 167 /* 168 * Clear out buffer cache. I don't think we 169 * ever get anything cached at this level at the 170 * moment, but who knows... 171 */ 172 #if 0 173 #ifdef KERNFS_DIAGNOSTIC 174 printf("kernfs_unmount: calling mntflushbuf\n"); 175 #endif 176 mntflushbuf(mp, 0); 177 #ifdef KERNFS_DIAGNOSTIC 178 printf("kernfs_unmount: calling mntinvalbuf\n"); 179 #endif 180 if (mntinvalbuf(mp, 1)) 181 return (EBUSY); 182 #endif 183 if (rootvp->v_usecount > 1) 184 return (EBUSY); 185 #ifdef KERNFS_DIAGNOSTIC 186 printf("kernfs_unmount: calling vflush\n"); 187 #endif 188 if (error = vflush(mp, rootvp, flags)) 189 return (error); 190 191 #ifdef KERNFS_DIAGNOSTIC 192 vprint("kernfs root", rootvp); 193 #endif 194 /* 195 * Release reference on underlying root vnode 196 */ 197 vrele(rootvp); 198 /* 199 * And blow it away for future re-use 200 */ 201 vgone(rootvp); 202 /* 203 * Finally, throw away the kernfs_mount structure 204 */ 205 free(mp->mnt_data, M_UFSMNT); /* XXX */ 206 mp->mnt_data = 0; 207 return 0; 208 } 209 210 kernfs_root(mp, vpp) 211 struct mount *mp; 212 struct vnode **vpp; 213 { 214 struct vnode *vp; 215 int error; 216 217 #ifdef KERNFS_DIAGNOSTIC 218 printf("kernfs_root(mp = %x)\n", mp); 219 #endif 220 221 /* 222 * Return locked reference to root. 223 */ 224 vp = VFSTOKERNFS(mp)->kf_root; 225 VREF(vp); 226 VOP_LOCK(vp); 227 *vpp = vp; 228 return (0); 229 } 230 231 kernfs_quotactl(mp, cmd, uid, arg, p) 232 struct mount *mp; 233 int cmd; 234 uid_t uid; 235 caddr_t arg; 236 struct proc *p; 237 { 238 return (EOPNOTSUPP); 239 } 240 241 kernfs_statfs(mp, sbp, p) 242 struct mount *mp; 243 struct statfs *sbp; 244 struct proc *p; 245 { 246 #ifdef KERNFS_DIAGNOSTIC 247 printf("kernfs_statfs(mp = %x)\n", mp); 248 #endif 249 250 sbp->f_type = MOUNT_KERNFS; 251 sbp->f_flags = 0; 252 sbp->f_bsize = DEV_BSIZE; 253 sbp->f_iosize = DEV_BSIZE; 254 sbp->f_blocks = 2; /* 1K to keep df happy */ 255 sbp->f_bfree = 0; 256 sbp->f_bavail = 0; 257 sbp->f_files = 0; /* Allow for "." */ 258 sbp->f_ffree = 0; /* See comments above */ 259 if (sbp != &mp->mnt_stat) { 260 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 261 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 262 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 263 } 264 return (0); 265 } 266 267 kernfs_sync(mp, waitfor) 268 struct mount *mp; 269 int waitfor; 270 { 271 return (0); 272 } 273 274 /* 275 * Kernfs flat namespace lookup. 276 * Currently unsupported. 277 */ 278 kernfs_vget(mp, ino, vpp) 279 struct mount *mp; 280 ino_t ino; 281 struct vnode **vpp; 282 { 283 284 return (EOPNOTSUPP); 285 } 286 287 288 kernfs_fhtovp(mp, fhp, setgen, vpp) 289 struct mount *mp; 290 struct fid *fhp; 291 int setgen; 292 struct vnode **vpp; 293 { 294 return (EOPNOTSUPP); 295 } 296 297 kernfs_vptofh(vp, fhp) 298 struct vnode *vp; 299 struct fid *fhp; 300 { 301 return (EOPNOTSUPP); 302 } 303 304 struct vfsops kernfs_vfsops = { 305 kernfs_mount, 306 kernfs_start, 307 kernfs_unmount, 308 kernfs_root, 309 kernfs_quotactl, 310 kernfs_statfs, 311 kernfs_sync, 312 kernfs_vget, 313 kernfs_fhtovp, 314 kernfs_vptofh, 315 kernfs_init, 316 }; 317