1 /* $OpenBSD: dead_vnops.c,v 1.41 2022/06/26 05:20:42 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/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 /* 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 int 157 dead_kqfilter(void *v) 158 { 159 struct vop_kqfilter_args *ap = v; 160 161 switch (ap->a_kn->kn_filter) { 162 case EVFILT_READ: 163 case EVFILT_WRITE: 164 ap->a_kn->kn_fop = &dead_filtops; 165 break; 166 case EVFILT_EXCEPT: 167 if ((ap->a_kn->kn_flags & __EV_POLL) == 0) 168 return (EINVAL); 169 ap->a_kn->kn_fop = &dead_filtops; 170 break; 171 default: 172 return (EINVAL); 173 } 174 175 return (0); 176 } 177 178 /* 179 * Just call the device strategy routine 180 */ 181 int 182 dead_strategy(void *v) 183 { 184 struct vop_strategy_args *ap = v; 185 int s; 186 187 if (ap->a_bp->b_vp == NULL || !chkvnlock(ap->a_bp->b_vp)) { 188 ap->a_bp->b_flags |= B_ERROR; 189 s = splbio(); 190 biodone(ap->a_bp); 191 splx(s); 192 return (EIO); 193 } 194 return (VOP_STRATEGY(ap->a_bp->b_vp, ap->a_bp)); 195 } 196 197 int 198 dead_inactive(void *v) 199 { 200 struct vop_inactive_args *ap = v; 201 202 VOP_UNLOCK(ap->a_vp); 203 return (0); 204 } 205 206 /* 207 * Wait until the vnode has finished changing state. 208 */ 209 int 210 dead_lock(void *v) 211 { 212 struct vop_lock_args *ap = v; 213 struct vnode *vp = ap->a_vp; 214 215 if (ap->a_flags & LK_DRAIN || !chkvnlock(vp)) 216 return (0); 217 218 return VOP_LOCK(vp, ap->a_flags); 219 } 220 221 /* 222 * Wait until the vnode has finished changing state. 223 */ 224 int 225 dead_bmap(void *v) 226 { 227 struct vop_bmap_args *ap = v; 228 229 if (!chkvnlock(ap->a_vp)) 230 return (EIO); 231 return (VOP_BMAP(ap->a_vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp)); 232 } 233 234 /* 235 * Print out the contents of a dead vnode. 236 */ 237 /* ARGSUSED */ 238 int 239 dead_print(void *v) 240 { 241 printf("tag VT_NON, dead vnode\n"); 242 return 0; 243 } 244 245 /* 246 * Empty vnode failed operation 247 */ 248 /*ARGSUSED*/ 249 int 250 dead_ebadf(void *v) 251 { 252 return (EBADF); 253 } 254 255 /* 256 * We have to wait during times when the vnode is 257 * in a state of change. 258 */ 259 int 260 chkvnlock(struct vnode *vp) 261 { 262 int locked = 0; 263 264 mtx_enter(&vnode_mtx); 265 while (vp->v_lflag & VXLOCK) { 266 vp->v_lflag |= VXWANT; 267 msleep_nsec(vp, &vnode_mtx, PINOD, "chkvnlock", INFSLP); 268 locked = 1; 269 } 270 mtx_leave(&vnode_mtx); 271 return (locked); 272 } 273