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