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