1 /* $OpenBSD: dead_vnops.c,v 1.43 2024/10/18 05:52:32 miod Exp $ */ 2 /* $NetBSD: dead_vnops.c,v 1.16 1996/02/13 13:12:48 mycroft 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 * @(#)dead_vnops.c 8.2 (Berkeley) 11/21/94 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/event.h> 38 #include <sys/time.h> 39 #include <sys/vnode.h> 40 #include <sys/lock.h> 41 #include <sys/errno.h> 42 #include <sys/buf.h> 43 44 /* 45 * Prototypes for dead operations on vnodes. 46 */ 47 int dead_ebadf(void *); 48 49 int dead_open(void *); 50 int dead_read(void *); 51 int dead_write(void *); 52 int dead_ioctl(void *); 53 int dead_kqfilter(void *v); 54 int dead_inactive(void *); 55 int dead_lock(void *); 56 int dead_bmap(void *); 57 int dead_strategy(void *); 58 int dead_print(void *); 59 60 int chkvnlock(struct vnode *); 61 62 const struct vops dead_vops = { 63 .vop_lookup = vop_generic_lookup, 64 .vop_create = vop_generic_badop, 65 .vop_mknod = vop_generic_badop, 66 .vop_open = dead_open, 67 .vop_close = nullop, 68 .vop_access = dead_ebadf, 69 .vop_getattr = dead_ebadf, 70 .vop_setattr = dead_ebadf, 71 .vop_read = dead_read, 72 .vop_write = dead_write, 73 .vop_ioctl = dead_ioctl, 74 .vop_kqfilter = dead_kqfilter, 75 .vop_revoke = NULL, 76 .vop_fsync = nullop, 77 .vop_remove = vop_generic_badop, 78 .vop_link = vop_generic_badop, 79 .vop_rename = vop_generic_badop, 80 .vop_mkdir = vop_generic_badop, 81 .vop_rmdir = vop_generic_badop, 82 .vop_symlink = vop_generic_badop, 83 .vop_readdir = dead_ebadf, 84 .vop_readlink = dead_ebadf, 85 .vop_abortop = vop_generic_badop, 86 .vop_inactive = dead_inactive, 87 .vop_reclaim = nullop, 88 .vop_lock = dead_lock, 89 .vop_unlock = nullop, 90 .vop_islocked = nullop, 91 .vop_bmap = dead_bmap, 92 .vop_strategy = dead_strategy, 93 .vop_print = dead_print, 94 .vop_pathconf = dead_ebadf, 95 .vop_advlock = dead_ebadf, 96 .vop_bwrite = nullop, 97 }; 98 99 /* 100 * Open always fails as if device did not exist. 101 */ 102 int 103 dead_open(void *v) 104 { 105 return (ENXIO); 106 } 107 108 /* 109 * Vnode op for read 110 */ 111 int 112 dead_read(void *v) 113 { 114 struct vop_read_args *ap = v; 115 116 if (chkvnlock(ap->a_vp)) 117 panic("dead_read: lock"); 118 /* 119 * Return EOF for tty devices, EIO for others 120 */ 121 if ((ap->a_vp->v_flag & VISTTY) == 0) 122 return (EIO); 123 return (0); 124 } 125 126 /* 127 * Vnode op for write 128 */ 129 int 130 dead_write(void *v) 131 { 132 struct vop_write_args *ap = v; 133 134 if (chkvnlock(ap->a_vp)) 135 panic("dead_write: lock"); 136 return (EIO); 137 } 138 139 /* 140 * Device ioctl operation. 141 */ 142 int 143 dead_ioctl(void *v) 144 { 145 struct vop_ioctl_args *ap = v; 146 147 if (!chkvnlock(ap->a_vp)) 148 return (EBADF); 149 return ((ap->a_vp->v_op->vop_ioctl)(ap)); 150 } 151 152 int 153 dead_kqfilter(void *v) 154 { 155 struct vop_kqfilter_args *ap = v; 156 157 switch (ap->a_kn->kn_filter) { 158 case EVFILT_READ: 159 case EVFILT_WRITE: 160 ap->a_kn->kn_fop = &dead_filtops; 161 break; 162 case EVFILT_EXCEPT: 163 if ((ap->a_kn->kn_flags & __EV_POLL) == 0) 164 return (EINVAL); 165 ap->a_kn->kn_fop = &dead_filtops; 166 break; 167 default: 168 return (EINVAL); 169 } 170 171 return (0); 172 } 173 174 /* 175 * Just call the device strategy routine 176 */ 177 int 178 dead_strategy(void *v) 179 { 180 struct vop_strategy_args *ap = v; 181 int s; 182 183 if (ap->a_bp->b_vp == NULL || !chkvnlock(ap->a_bp->b_vp)) { 184 ap->a_bp->b_flags |= B_ERROR; 185 s = splbio(); 186 biodone(ap->a_bp); 187 splx(s); 188 return (EIO); 189 } 190 return (VOP_STRATEGY(ap->a_bp->b_vp, ap->a_bp)); 191 } 192 193 int 194 dead_inactive(void *v) 195 { 196 struct vop_inactive_args *ap = v; 197 198 VOP_UNLOCK(ap->a_vp); 199 return (0); 200 } 201 202 /* 203 * Wait until the vnode has finished changing state. 204 */ 205 int 206 dead_lock(void *v) 207 { 208 struct vop_lock_args *ap = v; 209 struct vnode *vp = ap->a_vp; 210 211 if (ap->a_flags & LK_DRAIN || !chkvnlock(vp)) 212 return (0); 213 214 return VOP_LOCK(vp, ap->a_flags); 215 } 216 217 /* 218 * Wait until the vnode has finished changing state. 219 */ 220 int 221 dead_bmap(void *v) 222 { 223 struct vop_bmap_args *ap = v; 224 225 if (!chkvnlock(ap->a_vp)) 226 return (EIO); 227 return (VOP_BMAP(ap->a_vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp)); 228 } 229 230 /* 231 * Print out the contents of a dead vnode. 232 */ 233 int 234 dead_print(void *v) 235 { 236 #if defined(DEBUG) || defined(DIAGNOSTIC) || defined(VFSLCKDEBUG) 237 printf("tag VT_NON, dead vnode\n"); 238 #endif 239 return 0; 240 } 241 242 /* 243 * Empty vnode failed operation 244 */ 245 int 246 dead_ebadf(void *v) 247 { 248 return (EBADF); 249 } 250 251 /* 252 * We have to wait during times when the vnode is 253 * in a state of change. 254 */ 255 int 256 chkvnlock(struct vnode *vp) 257 { 258 int locked = 0; 259 260 mtx_enter(&vnode_mtx); 261 while (vp->v_lflag & VXLOCK) { 262 vp->v_lflag |= VXWANT; 263 msleep_nsec(vp, &vnode_mtx, PINOD, "chkvnlock", INFSLP); 264 locked = 1; 265 } 266 mtx_leave(&vnode_mtx); 267 return (locked); 268 } 269