1 /* $OpenBSD: mfs_vnops.c,v 1.54 2020/05/21 09:35:09 mpi 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 const 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_kqfilter = mfs_badop, 64 .vop_revoke = mfs_revoke, 65 .vop_fsync = spec_fsync, 66 .vop_remove = mfs_badop, 67 .vop_link = mfs_badop, 68 .vop_rename = mfs_badop, 69 .vop_mkdir = mfs_badop, 70 .vop_rmdir = mfs_badop, 71 .vop_symlink = mfs_badop, 72 .vop_readdir = mfs_badop, 73 .vop_readlink = mfs_badop, 74 .vop_abortop = mfs_badop, 75 .vop_inactive = mfs_inactive, 76 .vop_reclaim = mfs_reclaim, 77 .vop_lock = vop_generic_lock, 78 .vop_unlock = vop_generic_unlock, 79 .vop_bmap = vop_generic_bmap, 80 .vop_strategy = mfs_strategy, 81 .vop_print = mfs_print, 82 .vop_islocked = vop_generic_islocked, 83 .vop_pathconf = mfs_badop, 84 .vop_advlock = mfs_badop, 85 .vop_bwrite = vop_generic_bwrite 86 }; 87 88 /* 89 * Vnode Operations. 90 * 91 * Open called to allow memory filesystem to initialize and 92 * validate before actual IO. Record our process identifier 93 * so we can tell when we are doing I/O to ourself. 94 */ 95 int 96 mfs_open(void *v) 97 { 98 #ifdef DIAGNOSTIC 99 struct vop_open_args *ap = v; 100 101 if (ap->a_vp->v_type != VBLK) { 102 panic("mfs_open not VBLK"); 103 } 104 #endif 105 return (0); 106 } 107 108 /* 109 * Ioctl operation. 110 */ 111 int 112 mfs_ioctl(void *v) 113 { 114 115 return (ENOTTY); 116 } 117 118 /* 119 * Pass I/O requests to the memory filesystem process. 120 */ 121 int 122 mfs_strategy(void *v) 123 { 124 struct vop_strategy_args *ap = v; 125 struct buf *bp = ap->a_bp; 126 struct mfsnode *mfsp; 127 struct vnode *vp; 128 struct proc *p = curproc; 129 130 if (!vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 131 panic("mfs_strategy: bad dev"); 132 133 mfsp = VTOMFS(vp); 134 if (p != NULL && mfsp->mfs_tid == p->p_tid) { 135 mfs_doio(mfsp, bp); 136 } else { 137 bufq_queue(&mfsp->mfs_bufq, bp); 138 wakeup(vp); 139 } 140 return (0); 141 } 142 143 /* 144 * Memory file system I/O. 145 */ 146 void 147 mfs_doio(struct mfsnode *mfsp, struct buf *bp) 148 { 149 caddr_t base; 150 long offset = bp->b_blkno << DEV_BSHIFT; 151 int s; 152 153 if (bp->b_bcount > mfsp->mfs_size - offset) 154 bp->b_bcount = mfsp->mfs_size - offset; 155 156 base = mfsp->mfs_baseoff + offset; 157 if (bp->b_flags & B_READ) 158 bp->b_error = copyin(base, bp->b_data, bp->b_bcount); 159 else 160 bp->b_error = copyout(bp->b_data, base, bp->b_bcount); 161 if (bp->b_error) 162 bp->b_flags |= B_ERROR; 163 else 164 bp->b_resid = 0; 165 s = splbio(); 166 biodone(bp); 167 splx(s); 168 } 169 170 /* 171 * Memory filesystem close routine 172 */ 173 int 174 mfs_close(void *v) 175 { 176 struct vop_close_args *ap = v; 177 struct vnode *vp = ap->a_vp; 178 struct mfsnode *mfsp = VTOMFS(vp); 179 struct buf *bp; 180 int error; 181 182 /* 183 * Finish any pending I/O requests. 184 */ 185 while (1) { 186 bp = bufq_dequeue(&mfsp->mfs_bufq); 187 if (bp == NULL) 188 break; 189 mfs_doio(mfsp, bp); 190 wakeup(bp); 191 } 192 193 /* 194 * On last close of a memory filesystem we must invalidate any in 195 * core blocks, so that we can free up its vnode. 196 */ 197 error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, INFSLP); 198 if (error != 0) 199 return (error); 200 201 #ifdef DIAGNOSTIC 202 /* 203 * There should be no way to have any more buffers on this vnode. 204 */ 205 if (bufq_peek(&mfsp->mfs_bufq)) 206 printf("mfs_close: dirty buffers\n"); 207 #endif 208 209 /* 210 * Send a request to the filesystem server to exit. 211 */ 212 mfsp->mfs_shutdown = 1; 213 wakeup(vp); 214 return (0); 215 } 216 217 /* 218 * Memory filesystem inactive routine 219 */ 220 int 221 mfs_inactive(void *v) 222 { 223 struct vop_inactive_args *ap = v; 224 #ifdef DIAGNOSTIC 225 struct mfsnode *mfsp = VTOMFS(ap->a_vp); 226 227 if (mfsp->mfs_shutdown && bufq_peek(&mfsp->mfs_bufq)) 228 panic("mfs_inactive: not inactive"); 229 #endif 230 VOP_UNLOCK(ap->a_vp); 231 return (0); 232 } 233 234 /* 235 * Reclaim a memory filesystem devvp so that it can be reused. 236 */ 237 int 238 mfs_reclaim(void *v) 239 { 240 struct vop_reclaim_args *ap = v; 241 struct vnode *vp = ap->a_vp; 242 243 free(vp->v_data, M_MFSNODE, sizeof(struct mfsnode)); 244 vp->v_data = NULL; 245 return (0); 246 } 247 248 /* 249 * Print out the contents of an mfsnode. 250 */ 251 int 252 mfs_print(void *v) 253 { 254 struct vop_print_args *ap = v; 255 struct mfsnode *mfsp = VTOMFS(ap->a_vp); 256 257 printf("tag VT_MFS, tid %d, base %p, size %ld\n", mfsp->mfs_tid, 258 mfsp->mfs_baseoff, mfsp->mfs_size); 259 return (0); 260 } 261 262 /* 263 * Block device bad operation 264 */ 265 int 266 mfs_badop(void *v) 267 { 268 panic("mfs_badop called"); 269 } 270