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