1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)mfs_vnops.c 8.9 (Berkeley) 03/21/95 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/time.h> 13 #include <sys/kernel.h> 14 #include <sys/proc.h> 15 #include <sys/buf.h> 16 #include <sys/map.h> 17 #include <sys/vnode.h> 18 #include <sys/malloc.h> 19 20 #include <miscfs/specfs/specdev.h> 21 22 #include <machine/vmparam.h> 23 24 #include <ufs/mfs/mfsnode.h> 25 #include <ufs/mfs/mfsiom.h> 26 #include <ufs/mfs/mfs_extern.h> 27 28 /* 29 * mfs vnode operations. 30 */ 31 int (**mfs_vnodeop_p)(); 32 struct vnodeopv_entry_desc mfs_vnodeop_entries[] = { 33 { &vop_default_desc, vn_default_error }, 34 { &vop_lookup_desc, mfs_lookup }, /* lookup */ 35 { &vop_create_desc, mfs_create }, /* create */ 36 { &vop_mknod_desc, mfs_mknod }, /* mknod */ 37 { &vop_open_desc, mfs_open }, /* open */ 38 { &vop_close_desc, mfs_close }, /* close */ 39 { &vop_access_desc, mfs_access }, /* access */ 40 { &vop_getattr_desc, mfs_getattr }, /* getattr */ 41 { &vop_setattr_desc, mfs_setattr }, /* setattr */ 42 { &vop_read_desc, mfs_read }, /* read */ 43 { &vop_write_desc, mfs_write }, /* write */ 44 { &vop_ioctl_desc, mfs_ioctl }, /* ioctl */ 45 { &vop_select_desc, mfs_select }, /* select */ 46 { &vop_revoke_desc, mfs_revoke }, /* revoke */ 47 { &vop_mmap_desc, mfs_mmap }, /* mmap */ 48 { &vop_fsync_desc, spec_fsync }, /* fsync */ 49 { &vop_seek_desc, mfs_seek }, /* seek */ 50 { &vop_remove_desc, mfs_remove }, /* remove */ 51 { &vop_link_desc, mfs_link }, /* link */ 52 { &vop_rename_desc, mfs_rename }, /* rename */ 53 { &vop_mkdir_desc, mfs_mkdir }, /* mkdir */ 54 { &vop_rmdir_desc, mfs_rmdir }, /* rmdir */ 55 { &vop_symlink_desc, mfs_symlink }, /* symlink */ 56 { &vop_readdir_desc, mfs_readdir }, /* readdir */ 57 { &vop_readlink_desc, mfs_readlink }, /* readlink */ 58 { &vop_abortop_desc, mfs_abortop }, /* abortop */ 59 { &vop_inactive_desc, mfs_inactive }, /* inactive */ 60 { &vop_reclaim_desc, mfs_reclaim }, /* reclaim */ 61 { &vop_lock_desc, mfs_lock }, /* lock */ 62 { &vop_unlock_desc, mfs_unlock }, /* unlock */ 63 { &vop_bmap_desc, mfs_bmap }, /* bmap */ 64 { &vop_strategy_desc, mfs_strategy }, /* strategy */ 65 { &vop_print_desc, mfs_print }, /* print */ 66 { &vop_islocked_desc, mfs_islocked }, /* islocked */ 67 { &vop_pathconf_desc, mfs_pathconf }, /* pathconf */ 68 { &vop_advlock_desc, mfs_advlock }, /* advlock */ 69 { &vop_blkatoff_desc, mfs_blkatoff }, /* blkatoff */ 70 { &vop_valloc_desc, mfs_valloc }, /* valloc */ 71 { &vop_vfree_desc, mfs_vfree }, /* vfree */ 72 { &vop_truncate_desc, mfs_truncate }, /* truncate */ 73 { &vop_update_desc, mfs_update }, /* update */ 74 { &vop_bwrite_desc, mfs_bwrite }, /* bwrite */ 75 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 76 }; 77 struct vnodeopv_desc mfs_vnodeop_opv_desc = 78 { &mfs_vnodeop_p, mfs_vnodeop_entries }; 79 80 /* 81 * Vnode Operations. 82 * 83 * Open called to allow memory filesystem to initialize and 84 * validate before actual IO. Record our process identifier 85 * so we can tell when we are doing I/O to ourself. 86 */ 87 /* ARGSUSED */ 88 int 89 mfs_open(ap) 90 struct vop_open_args /* { 91 struct vnode *a_vp; 92 int a_mode; 93 struct ucred *a_cred; 94 struct proc *a_p; 95 } */ *ap; 96 { 97 98 if (ap->a_vp->v_type != VBLK) { 99 panic("mfs_ioctl not VBLK"); 100 /* NOTREACHED */ 101 } 102 return (0); 103 } 104 105 /* 106 * Ioctl operation. 107 */ 108 /* ARGSUSED */ 109 int 110 mfs_ioctl(ap) 111 struct vop_ioctl_args /* { 112 struct vnode *a_vp; 113 int a_command; 114 caddr_t a_data; 115 int a_fflag; 116 struct ucred *a_cred; 117 struct proc *a_p; 118 } */ *ap; 119 { 120 121 return (ENOTTY); 122 } 123 124 /* 125 * Pass I/O requests to the memory filesystem process. 126 */ 127 int 128 mfs_strategy(ap) 129 struct vop_strategy_args /* { 130 struct buf *a_bp; 131 } */ *ap; 132 { 133 register struct buf *bp = ap->a_bp; 134 register struct mfsnode *mfsp; 135 struct vnode *vp; 136 struct proc *p = curproc; /* XXX */ 137 138 if (!vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 139 panic("mfs_strategy: bad dev"); 140 mfsp = VTOMFS(vp); 141 /* check for mini-root access */ 142 if (mfsp->mfs_pid == 0) { 143 caddr_t base; 144 145 base = mfsp->mfs_baseoff + (bp->b_blkno << DEV_BSHIFT); 146 if (bp->b_flags & B_READ) 147 bcopy(base, bp->b_data, bp->b_bcount); 148 else 149 bcopy(bp->b_data, base, bp->b_bcount); 150 biodone(bp); 151 } else if (mfsp->mfs_pid == p->p_pid) { 152 mfs_doio(bp, mfsp->mfs_baseoff); 153 } else { 154 bp->b_actf = mfsp->mfs_buflist; 155 mfsp->mfs_buflist = bp; 156 wakeup((caddr_t)vp); 157 } 158 return (0); 159 } 160 161 /* 162 * Memory file system I/O. 163 * 164 * Trivial on the HP since buffer has already been mapping into KVA space. 165 */ 166 void 167 mfs_doio(bp, base) 168 register struct buf *bp; 169 caddr_t base; 170 { 171 172 base += (bp->b_blkno << DEV_BSHIFT); 173 if (bp->b_flags & B_READ) 174 bp->b_error = copyin(base, bp->b_data, bp->b_bcount); 175 else 176 bp->b_error = copyout(bp->b_data, base, bp->b_bcount); 177 if (bp->b_error) 178 bp->b_flags |= B_ERROR; 179 biodone(bp); 180 } 181 182 /* 183 * This is a noop, simply returning what one has been given. 184 */ 185 int 186 mfs_bmap(ap) 187 struct vop_bmap_args /* { 188 struct vnode *a_vp; 189 ufs_daddr_t a_bn; 190 struct vnode **a_vpp; 191 ufs_daddr_t *a_bnp; 192 int *a_runp; 193 } */ *ap; 194 { 195 196 if (ap->a_vpp != NULL) 197 *ap->a_vpp = ap->a_vp; 198 if (ap->a_bnp != NULL) 199 *ap->a_bnp = ap->a_bn; 200 if (ap->a_runp != NULL) 201 *ap->a_runp = 0; 202 return (0); 203 } 204 205 /* 206 * Memory filesystem close routine 207 */ 208 /* ARGSUSED */ 209 int 210 mfs_close(ap) 211 struct vop_close_args /* { 212 struct vnode *a_vp; 213 int a_fflag; 214 struct ucred *a_cred; 215 struct proc *a_p; 216 } */ *ap; 217 { 218 register struct vnode *vp = ap->a_vp; 219 register struct mfsnode *mfsp = VTOMFS(vp); 220 register struct buf *bp; 221 int error; 222 223 /* 224 * Finish any pending I/O requests. 225 */ 226 while (bp = mfsp->mfs_buflist) { 227 mfsp->mfs_buflist = bp->b_actf; 228 mfs_doio(bp, mfsp->mfs_baseoff); 229 wakeup((caddr_t)bp); 230 } 231 /* 232 * On last close of a memory filesystem 233 * we must invalidate any in core blocks, so that 234 * we can, free up its vnode. 235 */ 236 if (error = vinvalbuf(vp, 1, ap->a_cred, ap->a_p, 0, 0)) 237 return (error); 238 /* 239 * There should be no way to have any more uses of this 240 * vnode, so if we find any other uses, it is a panic. 241 */ 242 if (vp->v_usecount > 1) 243 printf("mfs_close: ref count %d > 1\n", vp->v_usecount); 244 if (vp->v_usecount > 1 || mfsp->mfs_buflist) 245 panic("mfs_close"); 246 /* 247 * Send a request to the filesystem server to exit. 248 */ 249 mfsp->mfs_buflist = (struct buf *)(-1); 250 wakeup((caddr_t)vp); 251 return (0); 252 } 253 254 /* 255 * Memory filesystem inactive routine 256 */ 257 /* ARGSUSED */ 258 int 259 mfs_inactive(ap) 260 struct vop_inactive_args /* { 261 struct vnode *a_vp; 262 } */ *ap; 263 { 264 register struct mfsnode *mfsp = VTOMFS(ap->a_vp); 265 266 if (mfsp->mfs_buflist && mfsp->mfs_buflist != (struct buf *)(-1)) 267 panic("mfs_inactive: not inactive (mfs_buflist %x)", 268 mfsp->mfs_buflist); 269 return (0); 270 } 271 272 /* 273 * Reclaim a memory filesystem devvp so that it can be reused. 274 */ 275 int 276 mfs_reclaim(ap) 277 struct vop_reclaim_args /* { 278 struct vnode *a_vp; 279 } */ *ap; 280 { 281 register struct vnode *vp = ap->a_vp; 282 283 FREE(vp->v_data, M_MFSNODE); 284 vp->v_data = NULL; 285 return (0); 286 } 287 288 /* 289 * Print out the contents of an mfsnode. 290 */ 291 int 292 mfs_print(ap) 293 struct vop_print_args /* { 294 struct vnode *a_vp; 295 } */ *ap; 296 { 297 register struct mfsnode *mfsp = VTOMFS(ap->a_vp); 298 299 printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 300 mfsp->mfs_baseoff, mfsp->mfs_size); 301 return (0); 302 } 303 304 /* 305 * Block device bad operation 306 */ 307 int 308 mfs_badop() 309 { 310 311 panic("mfs_badop called\n"); 312 /* NOTREACHED */ 313 } 314 315 /* 316 * Memory based filesystem initialization. 317 */ 318 mfs_init() 319 { 320 321 return; 322 } 323