1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 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 8.2 (Berkeley) 01/04/94 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 = ENXIO; 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_KERNFS, 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 (rootvp->v_usecount > 1) 173 return (EBUSY); 174 #ifdef KERNFS_DIAGNOSTIC 175 printf("kernfs_unmount: calling vflush\n"); 176 #endif 177 if (error = vflush(mp, rootvp, flags)) 178 return (error); 179 180 #ifdef KERNFS_DIAGNOSTIC 181 vprint("kernfs root", rootvp); 182 #endif 183 /* 184 * Release reference on underlying root vnode 185 */ 186 vrele(rootvp); 187 /* 188 * And blow it away for future re-use 189 */ 190 vgone(rootvp); 191 /* 192 * Finally, throw away the kernfs_mount structure 193 */ 194 free(mp->mnt_data, M_UFSMNT); /* XXX */ 195 mp->mnt_data = 0; 196 return 0; 197 } 198 199 kernfs_root(mp, vpp) 200 struct mount *mp; 201 struct vnode **vpp; 202 { 203 struct vnode *vp; 204 int error; 205 206 #ifdef KERNFS_DIAGNOSTIC 207 printf("kernfs_root(mp = %x)\n", mp); 208 #endif 209 210 /* 211 * Return locked reference to root. 212 */ 213 vp = VFSTOKERNFS(mp)->kf_root; 214 VREF(vp); 215 VOP_LOCK(vp); 216 *vpp = vp; 217 return (0); 218 } 219 220 kernfs_quotactl(mp, cmd, uid, arg, p) 221 struct mount *mp; 222 int cmd; 223 uid_t uid; 224 caddr_t arg; 225 struct proc *p; 226 { 227 return (EOPNOTSUPP); 228 } 229 230 kernfs_statfs(mp, sbp, p) 231 struct mount *mp; 232 struct statfs *sbp; 233 struct proc *p; 234 { 235 #ifdef KERNFS_DIAGNOSTIC 236 printf("kernfs_statfs(mp = %x)\n", mp); 237 #endif 238 239 sbp->f_type = MOUNT_KERNFS; 240 sbp->f_flags = 0; 241 sbp->f_bsize = DEV_BSIZE; 242 sbp->f_iosize = DEV_BSIZE; 243 sbp->f_blocks = 2; /* 1K to keep df happy */ 244 sbp->f_bfree = 0; 245 sbp->f_bavail = 0; 246 sbp->f_files = 0; 247 sbp->f_ffree = 0; 248 if (sbp != &mp->mnt_stat) { 249 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 250 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 251 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 252 } 253 return (0); 254 } 255 256 kernfs_sync(mp, waitfor) 257 struct mount *mp; 258 int waitfor; 259 { 260 return (0); 261 } 262 263 /* 264 * Kernfs flat namespace lookup. 265 * Currently unsupported. 266 */ 267 kernfs_vget(mp, ino, vpp) 268 struct mount *mp; 269 ino_t ino; 270 struct vnode **vpp; 271 { 272 273 return (EOPNOTSUPP); 274 } 275 276 277 kernfs_fhtovp(mp, fhp, setgen, vpp) 278 struct mount *mp; 279 struct fid *fhp; 280 int setgen; 281 struct vnode **vpp; 282 { 283 return (EOPNOTSUPP); 284 } 285 286 kernfs_vptofh(vp, fhp) 287 struct vnode *vp; 288 struct fid *fhp; 289 { 290 return (EOPNOTSUPP); 291 } 292 293 struct vfsops kernfs_vfsops = { 294 kernfs_mount, 295 kernfs_start, 296 kernfs_unmount, 297 kernfs_root, 298 kernfs_quotactl, 299 kernfs_statfs, 300 kernfs_sync, 301 kernfs_vget, 302 kernfs_fhtovp, 303 kernfs_vptofh, 304 kernfs_init, 305 }; 306