1 /* $OpenBSD: mfs_vnops.c,v 1.61 2024/04/16 10:04:41 claudio 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 = vop_generic_badop, 52 .vop_create = vop_generic_badop, 53 .vop_mknod = vop_generic_badop, 54 .vop_open = mfs_open, 55 .vop_close = mfs_close, 56 .vop_access = vop_generic_badop, 57 .vop_getattr = vop_generic_badop, 58 .vop_setattr = vop_generic_badop, 59 .vop_read = vop_generic_badop, 60 .vop_write = vop_generic_badop, 61 .vop_ioctl = mfs_ioctl, 62 .vop_kqfilter = vop_generic_badop, 63 .vop_revoke = vop_generic_revoke, 64 .vop_fsync = spec_fsync, 65 .vop_remove = vop_generic_badop, 66 .vop_link = vop_generic_badop, 67 .vop_rename = vop_generic_badop, 68 .vop_mkdir = vop_generic_badop, 69 .vop_rmdir = vop_generic_badop, 70 .vop_symlink = vop_generic_badop, 71 .vop_readdir = vop_generic_badop, 72 .vop_readlink = vop_generic_badop, 73 .vop_abortop = vop_generic_badop, 74 .vop_inactive = mfs_inactive, 75 .vop_reclaim = mfs_reclaim, 76 .vop_lock = nullop, 77 .vop_unlock = nullop, 78 .vop_islocked = nullop, 79 .vop_bmap = vop_generic_bmap, 80 .vop_strategy = mfs_strategy, 81 .vop_print = mfs_print, 82 .vop_pathconf = vop_generic_badop, 83 .vop_advlock = vop_generic_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 = ap->a_vp; 127 128 if (vp->v_type != VBLK || vp->v_usecount == 0) 129 panic("mfs_strategy: bad dev"); 130 131 mfsp = VTOMFS(vp); 132 if (mfsp->mfs_tid == curproc->p_tid) { 133 mfs_doio(mfsp, bp); 134 } else { 135 bufq_queue(&mfsp->mfs_bufq, bp); 136 wakeup(vp); 137 } 138 return (0); 139 } 140 141 /* 142 * Memory file system I/O. 143 */ 144 void 145 mfs_doio(struct mfsnode *mfsp, struct buf *bp) 146 { 147 caddr_t base; 148 long offset = bp->b_blkno << DEV_BSHIFT; 149 int s; 150 151 if (bp->b_bcount > mfsp->mfs_size - offset) 152 bp->b_bcount = mfsp->mfs_size - offset; 153 154 base = mfsp->mfs_baseoff + offset; 155 if (bp->b_flags & B_READ) 156 bp->b_error = copyin(base, bp->b_data, bp->b_bcount); 157 else 158 bp->b_error = copyout(bp->b_data, base, bp->b_bcount); 159 if (bp->b_error) 160 bp->b_flags |= B_ERROR; 161 else 162 bp->b_resid = 0; 163 s = splbio(); 164 biodone(bp); 165 splx(s); 166 } 167 168 /* 169 * Memory filesystem close routine 170 */ 171 int 172 mfs_close(void *v) 173 { 174 struct vop_close_args *ap = v; 175 struct vnode *vp = ap->a_vp; 176 struct mfsnode *mfsp = VTOMFS(vp); 177 struct buf *bp; 178 int error; 179 180 /* 181 * Finish any pending I/O requests. 182 */ 183 while (1) { 184 bp = bufq_dequeue(&mfsp->mfs_bufq); 185 if (bp == NULL) 186 break; 187 mfs_doio(mfsp, bp); 188 wakeup(bp); 189 } 190 191 /* 192 * On last close of a memory filesystem we must invalidate any in 193 * core blocks, so that we can free up its vnode. 194 */ 195 error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, INFSLP); 196 if (error != 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); 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 struct mfsnode *mfsp = VTOMFS(vp); 241 242 bufq_destroy(&mfsp->mfs_bufq); 243 244 free(vp->v_data, M_MFSNODE, sizeof(struct mfsnode)); 245 vp->v_data = NULL; 246 return (0); 247 } 248 249 /* 250 * Print out the contents of an mfsnode. 251 */ 252 int 253 mfs_print(void *v) 254 { 255 struct vop_print_args *ap = v; 256 struct mfsnode *mfsp = VTOMFS(ap->a_vp); 257 258 printf("tag VT_MFS, tid %d, base %p, size %ld\n", mfsp->mfs_tid, 259 mfsp->mfs_baseoff, mfsp->mfs_size); 260 return (0); 261 } 262