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