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