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.3 (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 205 #ifdef KERNFS_DIAGNOSTIC 206 printf("kernfs_root(mp = %x)\n", mp); 207 #endif 208 209 /* 210 * Return locked reference to root. 211 */ 212 vp = VFSTOKERNFS(mp)->kf_root; 213 VREF(vp); 214 VOP_LOCK(vp); 215 *vpp = vp; 216 return (0); 217 } 218 219 kernfs_quotactl(mp, cmd, uid, arg, p) 220 struct mount *mp; 221 int cmd; 222 uid_t uid; 223 caddr_t arg; 224 struct proc *p; 225 { 226 return (EOPNOTSUPP); 227 } 228 229 kernfs_statfs(mp, sbp, p) 230 struct mount *mp; 231 struct statfs *sbp; 232 struct proc *p; 233 { 234 #ifdef KERNFS_DIAGNOSTIC 235 printf("kernfs_statfs(mp = %x)\n", mp); 236 #endif 237 238 sbp->f_type = MOUNT_KERNFS; 239 sbp->f_flags = 0; 240 sbp->f_bsize = DEV_BSIZE; 241 sbp->f_iosize = DEV_BSIZE; 242 sbp->f_blocks = 2; /* 1K to keep df happy */ 243 sbp->f_bfree = 0; 244 sbp->f_bavail = 0; 245 sbp->f_files = 0; 246 sbp->f_ffree = 0; 247 if (sbp != &mp->mnt_stat) { 248 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 249 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 250 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 251 } 252 return (0); 253 } 254 255 kernfs_sync(mp, waitfor) 256 struct mount *mp; 257 int waitfor; 258 { 259 return (0); 260 } 261 262 /* 263 * Kernfs flat namespace lookup. 264 * Currently unsupported. 265 */ 266 kernfs_vget(mp, ino, vpp) 267 struct mount *mp; 268 ino_t ino; 269 struct vnode **vpp; 270 { 271 272 return (EOPNOTSUPP); 273 } 274 275 276 kernfs_fhtovp(mp, fhp, setgen, vpp) 277 struct mount *mp; 278 struct fid *fhp; 279 int setgen; 280 struct vnode **vpp; 281 { 282 return (EOPNOTSUPP); 283 } 284 285 kernfs_vptofh(vp, fhp) 286 struct vnode *vp; 287 struct fid *fhp; 288 { 289 return (EOPNOTSUPP); 290 } 291 292 struct vfsops kernfs_vfsops = { 293 kernfs_mount, 294 kernfs_start, 295 kernfs_unmount, 296 kernfs_root, 297 kernfs_quotactl, 298 kernfs_statfs, 299 kernfs_sync, 300 kernfs_vget, 301 kernfs_fhtovp, 302 kernfs_vptofh, 303 kernfs_init, 304 }; 305