1 /* $OpenBSD: mfs_vnops.c,v 1.48 2016/09/08 16:44:46 tedu Exp $ */ 2 /* $NetBSD: mfs_vnops.c,v 1.8 1996/03/17 02:16:32 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)mfs_vnops.c 8.5 (Berkeley) 7/28/94 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/time.h> 38 #include <sys/kernel.h> 39 #include <sys/proc.h> 40 #include <sys/buf.h> 41 #include <sys/vnode.h> 42 #include <sys/malloc.h> 43 #include <sys/mount.h> 44 #include <sys/specdev.h> 45 46 #include <ufs/mfs/mfsnode.h> 47 #include <ufs/mfs/mfs_extern.h> 48 49 /* mfs vnode operations. */ 50 struct vops mfs_vops = { 51 .vop_lookup = mfs_badop, 52 .vop_create = mfs_badop, 53 .vop_mknod = mfs_badop, 54 .vop_open = mfs_open, 55 .vop_close = mfs_close, 56 .vop_access = mfs_badop, 57 .vop_getattr = mfs_badop, 58 .vop_setattr = mfs_badop, 59 .vop_read = mfs_badop, 60 .vop_write = mfs_badop, 61 .vop_ioctl = mfs_ioctl, 62 .vop_poll = mfs_badop, 63 .vop_revoke = mfs_revoke, 64 .vop_fsync = spec_fsync, 65 .vop_remove = mfs_badop, 66 .vop_link = mfs_badop, 67 .vop_rename = mfs_badop, 68 .vop_mkdir = mfs_badop, 69 .vop_rmdir = mfs_badop, 70 .vop_symlink = mfs_badop, 71 .vop_readdir = mfs_badop, 72 .vop_readlink = mfs_badop, 73 .vop_abortop = mfs_badop, 74 .vop_inactive = mfs_inactive, 75 .vop_reclaim = mfs_reclaim, 76 .vop_lock = vop_generic_lock, 77 .vop_unlock = vop_generic_unlock, 78 .vop_bmap = vop_generic_bmap, 79 .vop_strategy = mfs_strategy, 80 .vop_print = mfs_print, 81 .vop_islocked = vop_generic_islocked, 82 .vop_pathconf = mfs_badop, 83 .vop_advlock = mfs_badop, 84 .vop_bwrite = vop_generic_bwrite 85 }; 86 87 /* 88 * Vnode Operations. 89 * 90 * Open called to allow memory filesystem to initialize and 91 * validate before actual IO. Record our process identifier 92 * so we can tell when we are doing I/O to ourself. 93 */ 94 int 95 mfs_open(void *v) 96 { 97 #ifdef DIAGNOSTIC 98 struct vop_open_args *ap = v; 99 100 if (ap->a_vp->v_type != VBLK) { 101 panic("mfs_open not VBLK"); 102 } 103 #endif 104 return (0); 105 } 106 107 /* 108 * Ioctl operation. 109 */ 110 int 111 mfs_ioctl(void *v) 112 { 113 114 return (ENOTTY); 115 } 116 117 /* 118 * Pass I/O requests to the memory filesystem process. 119 */ 120 int 121 mfs_strategy(void *v) 122 { 123 struct vop_strategy_args *ap = v; 124 struct buf *bp = ap->a_bp; 125 struct mfsnode *mfsp; 126 struct vnode *vp; 127 struct proc *p = curproc; 128 129 if (!vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 130 panic("mfs_strategy: bad dev"); 131 132 mfsp = VTOMFS(vp); 133 if (p != NULL && mfsp->mfs_pid == p->p_pid) { 134 mfs_doio(mfsp, bp); 135 } else { 136 bufq_queue(&mfsp->mfs_bufq, bp); 137 wakeup(vp); 138 } 139 return (0); 140 } 141 142 /* 143 * Memory file system I/O. 144 */ 145 void 146 mfs_doio(struct mfsnode *mfsp, struct buf *bp) 147 { 148 caddr_t base; 149 long offset = bp->b_blkno << DEV_BSHIFT; 150 int s; 151 152 if (bp->b_bcount > mfsp->mfs_size - offset) 153 bp->b_bcount = mfsp->mfs_size - offset; 154 155 base = mfsp->mfs_baseoff + offset; 156 if (bp->b_flags & B_READ) 157 bp->b_error = copyin(base, bp->b_data, bp->b_bcount); 158 else 159 bp->b_error = copyout(bp->b_data, base, bp->b_bcount); 160 if (bp->b_error) 161 bp->b_flags |= B_ERROR; 162 else 163 bp->b_resid = 0; 164 s = splbio(); 165 biodone(bp); 166 splx(s); 167 } 168 169 /* 170 * Memory filesystem close routine 171 */ 172 int 173 mfs_close(void *v) 174 { 175 struct vop_close_args *ap = v; 176 struct vnode *vp = ap->a_vp; 177 struct mfsnode *mfsp = VTOMFS(vp); 178 struct buf *bp; 179 int error; 180 181 /* 182 * Finish any pending I/O requests. 183 */ 184 while (1) { 185 bp = bufq_dequeue(&mfsp->mfs_bufq); 186 if (bp == NULL) 187 break; 188 mfs_doio(mfsp, bp); 189 wakeup(bp); 190 } 191 192 /* 193 * On last close of a memory filesystem we must invalidate any in 194 * core blocks, so that we can free up its vnode. 195 */ 196 if ((error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0)) != 0) 197 return (error); 198 199 #ifdef DIAGNOSTIC 200 /* 201 * There should be no way to have any more buffers on this vnode. 202 */ 203 if (bufq_peek(&mfsp->mfs_bufq)) 204 printf("mfs_close: dirty buffers\n"); 205 #endif 206 207 /* 208 * Send a request to the filesystem server to exit. 209 */ 210 mfsp->mfs_shutdown = 1; 211 wakeup(vp); 212 return (0); 213 } 214 215 /* 216 * Memory filesystem inactive routine 217 */ 218 int 219 mfs_inactive(void *v) 220 { 221 struct vop_inactive_args *ap = v; 222 #ifdef DIAGNOSTIC 223 struct mfsnode *mfsp = VTOMFS(ap->a_vp); 224 225 if (mfsp->mfs_shutdown && bufq_peek(&mfsp->mfs_bufq)) 226 panic("mfs_inactive: not inactive"); 227 #endif 228 VOP_UNLOCK(ap->a_vp, ap->a_p); 229 return (0); 230 } 231 232 /* 233 * Reclaim a memory filesystem devvp so that it can be reused. 234 */ 235 int 236 mfs_reclaim(void *v) 237 { 238 struct vop_reclaim_args *ap = v; 239 struct vnode *vp = ap->a_vp; 240 241 free(vp->v_data, M_MFSNODE, 0); 242 vp->v_data = NULL; 243 return (0); 244 } 245 246 /* 247 * Print out the contents of an mfsnode. 248 */ 249 int 250 mfs_print(void *v) 251 { 252 struct vop_print_args *ap = v; 253 struct mfsnode *mfsp = VTOMFS(ap->a_vp); 254 255 printf("tag VT_MFS, pid %d, base %p, size %ld\n", mfsp->mfs_pid, 256 mfsp->mfs_baseoff, mfsp->mfs_size); 257 return (0); 258 } 259 260 /* 261 * Block device bad operation 262 */ 263 int 264 mfs_badop(void *v) 265 { 266 panic("mfs_badop called"); 267 } 268