1 /* $OpenBSD: dead_vnops.c,v 1.29 2015/03/14 03:38:51 jsg 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_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 struct vops dead_vops = { 63 .vop_lookup = vop_generic_lookup, 64 .vop_create = dead_badop, 65 .vop_mknod = dead_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_poll = dead_poll, 75 .vop_fsync = nullop, 76 .vop_remove = dead_badop, 77 .vop_link = dead_badop, 78 .vop_rename = dead_badop, 79 .vop_mkdir = dead_badop, 80 .vop_rmdir = dead_badop, 81 .vop_symlink = dead_badop, 82 .vop_readdir = dead_ebadf, 83 .vop_readlink = dead_ebadf, 84 .vop_abortop = dead_badop, 85 .vop_inactive = nullop, 86 .vop_reclaim = nullop, 87 .vop_lock = dead_lock, 88 .vop_unlock = vop_generic_unlock, 89 .vop_bmap = dead_bmap, 90 .vop_strategy = dead_strategy, 91 .vop_print = dead_print, 92 .vop_islocked = vop_generic_islocked, 93 .vop_pathconf = dead_ebadf, 94 .vop_advlock = dead_ebadf, 95 .vop_bwrite = nullop, 96 }; 97 98 /* 99 * Open always fails as if device did not exist. 100 */ 101 /* ARGSUSED */ 102 int 103 dead_open(void *v) 104 { 105 return (ENXIO); 106 } 107 108 /* 109 * Vnode op for read 110 */ 111 /* ARGSUSED */ 112 int 113 dead_read(void *v) 114 { 115 struct vop_read_args *ap = v; 116 117 if (chkvnlock(ap->a_vp)) 118 panic("dead_read: lock"); 119 /* 120 * Return EOF for tty devices, EIO for others 121 */ 122 if ((ap->a_vp->v_flag & VISTTY) == 0) 123 return (EIO); 124 return (0); 125 } 126 127 /* 128 * Vnode op for write 129 */ 130 /* ARGSUSED */ 131 int 132 dead_write(void *v) 133 { 134 struct vop_write_args *ap = v; 135 136 if (chkvnlock(ap->a_vp)) 137 panic("dead_write: lock"); 138 return (EIO); 139 } 140 141 /* 142 * Device ioctl operation. 143 */ 144 /* ARGSUSED */ 145 int 146 dead_ioctl(void *v) 147 { 148 struct vop_ioctl_args *ap = v; 149 150 if (!chkvnlock(ap->a_vp)) 151 return (EBADF); 152 return ((ap->a_vp->v_op->vop_ioctl)(ap)); 153 } 154 155 /* ARGSUSED */ 156 int 157 dead_poll(void *v) 158 { 159 #if 0 160 struct vop_poll_args *ap = v; 161 #endif 162 163 /* 164 * Let the user find out that the descriptor is gone. 165 */ 166 return (POLLHUP); 167 } 168 169 /* 170 * Just call the device strategy routine 171 */ 172 int 173 dead_strategy(void *v) 174 { 175 struct vop_strategy_args *ap = v; 176 int s; 177 178 if (ap->a_bp->b_vp == NULL || !chkvnlock(ap->a_bp->b_vp)) { 179 ap->a_bp->b_flags |= B_ERROR; 180 s = splbio(); 181 biodone(ap->a_bp); 182 splx(s); 183 return (EIO); 184 } 185 return (VOP_STRATEGY(ap->a_bp)); 186 } 187 188 /* 189 * Wait until the vnode has finished changing state. 190 */ 191 int 192 dead_lock(void *v) 193 { 194 struct vop_lock_args *ap = v; 195 struct vnode *vp = ap->a_vp; 196 197 if (ap->a_flags & LK_DRAIN || !chkvnlock(vp)) 198 return (0); 199 200 return ((vp->v_op->vop_lock)(ap)); 201 } 202 203 /* 204 * Wait until the vnode has finished changing state. 205 */ 206 int 207 dead_bmap(void *v) 208 { 209 struct vop_bmap_args *ap = v; 210 211 if (!chkvnlock(ap->a_vp)) 212 return (EIO); 213 return (VOP_BMAP(ap->a_vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp)); 214 } 215 216 /* 217 * Print out the contents of a dead vnode. 218 */ 219 /* ARGSUSED */ 220 int 221 dead_print(void *v) 222 { 223 printf("tag VT_NON, dead vnode\n"); 224 return 0; 225 } 226 227 /* 228 * Empty vnode failed operation 229 */ 230 /*ARGSUSED*/ 231 int 232 dead_ebadf(void *v) 233 { 234 return (EBADF); 235 } 236 237 /* 238 * Empty vnode bad operation 239 */ 240 /*ARGSUSED*/ 241 int 242 dead_badop(void *v) 243 { 244 panic("dead_badop called"); 245 /* NOTREACHED */ 246 } 247 248 /* 249 * We have to wait during times when the vnode is 250 * in a state of change. 251 */ 252 int 253 chkvnlock(struct vnode *vp) 254 { 255 int locked = 0; 256 257 while (vp->v_flag & VXLOCK) { 258 vp->v_flag |= VXWANT; 259 tsleep(vp, PINOD, "chkvnlock", 0); 260 locked = 1; 261 } 262 return (locked); 263 } 264