dead_vnops.c revision 138270
1169689Skan/* 2169689Skan * Copyright (c) 1989, 1993 3169689Skan * The Regents of the University of California. All rights reserved. 4169689Skan * 5169689Skan * Redistribution and use in source and binary forms, with or without 6169689Skan * modification, are permitted provided that the following conditions 7169689Skan * are met: 8169689Skan * 1. Redistributions of source code must retain the above copyright 9169689Skan * notice, this list of conditions and the following disclaimer. 10169689Skan * 2. Redistributions in binary form must reproduce the above copyright 11169689Skan * notice, this list of conditions and the following disclaimer in the 12169689Skan * documentation and/or other materials provided with the distribution. 13169689Skan * 4. Neither the name of the University nor the names of its contributors 14169689Skan * may be used to endorse or promote products derived from this software 15169689Skan * without specific prior written permission. 16169689Skan * 17169689Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20169689Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27169689Skan * SUCH DAMAGE. 28169689Skan * 29169689Skan * @(#)dead_vnops.c 8.1 (Berkeley) 6/10/93 30169689Skan * $FreeBSD: head/sys/fs/deadfs/dead_vnops.c 138270 2004-12-01 12:24:41Z phk $ 31169689Skan */ 32169689Skan 33169689Skan#include <sys/param.h> 34169689Skan#include <sys/systm.h> 35169689Skan#include <sys/kernel.h> 36169689Skan#include <sys/lock.h> 37169689Skan#include <sys/mutex.h> 38169689Skan#include <sys/poll.h> 39169689Skan#include <sys/vnode.h> 40169689Skan 41169689Skanstatic int chkvnlock(struct vnode *); 42169689Skan/* 43169689Skan * Prototypes for dead operations on vnodes. 44169689Skan */ 45169689Skanstatic vop_bmap_t dead_bmap; 46169689Skanstatic vop_ioctl_t dead_ioctl; 47169689Skanstatic vop_lock_t dead_lock; 48169689Skanstatic vop_lookup_t dead_lookup; 49169689Skanstatic vop_open_t dead_open; 50169689Skanstatic vop_poll_t dead_poll; 51169689Skanstatic vop_read_t dead_read; 52169689Skanstatic vop_write_t dead_write; 53169689Skan 54169689Skanvop_t **dead_vnodeop_p; 55169689Skanstatic struct vnodeopv_entry_desc dead_vnodeop_entries[] = { 56169689Skan { &vop_default_desc, (vop_t *) vop_defaultop }, 57169689Skan { &vop_access_desc, (vop_t *) vop_ebadf }, 58169689Skan { &vop_advlock_desc, (vop_t *) vop_ebadf }, 59169689Skan { &vop_bmap_desc, (vop_t *) dead_bmap }, 60169689Skan { &vop_create_desc, (vop_t *) vop_panic }, 61169689Skan { &vop_getattr_desc, (vop_t *) vop_ebadf }, 62169689Skan { &vop_inactive_desc, (vop_t *) vop_null }, 63169689Skan { &vop_ioctl_desc, (vop_t *) dead_ioctl }, 64169689Skan { &vop_link_desc, (vop_t *) vop_panic }, 65169689Skan { &vop_lock_desc, (vop_t *) dead_lock }, 66169689Skan { &vop_lookup_desc, (vop_t *) dead_lookup }, 67169689Skan { &vop_mkdir_desc, (vop_t *) vop_panic }, 68169689Skan { &vop_mknod_desc, (vop_t *) vop_panic }, 69169689Skan { &vop_open_desc, (vop_t *) dead_open }, 70169689Skan { &vop_pathconf_desc, (vop_t *) vop_ebadf }, /* per pathconf(2) */ 71169689Skan { &vop_poll_desc, (vop_t *) dead_poll }, 72169689Skan { &vop_read_desc, (vop_t *) dead_read }, 73169689Skan { &vop_readdir_desc, (vop_t *) vop_ebadf }, 74169689Skan { &vop_readlink_desc, (vop_t *) vop_ebadf }, 75169689Skan { &vop_reclaim_desc, (vop_t *) vop_null }, 76169689Skan { &vop_remove_desc, (vop_t *) vop_panic }, 77169689Skan { &vop_rename_desc, (vop_t *) vop_panic }, 78169689Skan { &vop_rmdir_desc, (vop_t *) vop_panic }, 79169689Skan { &vop_setattr_desc, (vop_t *) vop_ebadf }, 80169689Skan { &vop_symlink_desc, (vop_t *) vop_panic }, 81169689Skan { &vop_write_desc, (vop_t *) dead_write }, 82169689Skan { NULL, NULL } 83169689Skan}; 84169689Skanstatic struct vnodeopv_desc dead_vnodeop_opv_desc = 85169689Skan { &dead_vnodeop_p, dead_vnodeop_entries }; 86169689Skan 87169689SkanVNODEOP_SET(dead_vnodeop_opv_desc); 88169689Skan 89169689Skan/* 90169689Skan * Trivial lookup routine that always fails. 91169689Skan */ 92169689Skan/* ARGSUSED */ 93169689Skanstatic int 94169689Skandead_lookup(ap) 95169689Skan struct vop_lookup_args /* { 96169689Skan struct vnode * a_dvp; 97169689Skan struct vnode ** a_vpp; 98169689Skan struct componentname * a_cnp; 99169689Skan } */ *ap; 100169689Skan{ 101169689Skan 102169689Skan *ap->a_vpp = NULL; 103169689Skan return (ENOTDIR); 104169689Skan} 105169689Skan 106169689Skan/* 107169689Skan * Open always fails as if device did not exist. 108169689Skan */ 109169689Skan/* ARGSUSED */ 110169689Skanstatic int 111169689Skandead_open(ap) 112169689Skan struct vop_open_args /* { 113169689Skan struct vnode *a_vp; 114169689Skan int a_mode; 115169689Skan struct ucred *a_cred; 116169689Skan struct proc *a_p; 117169689Skan } */ *ap; 118169689Skan{ 119169689Skan 120169689Skan return (ENXIO); 121169689Skan} 122169689Skan 123169689Skan/* 124169689Skan * Vnode op for read 125169689Skan */ 126169689Skan/* ARGSUSED */ 127169689Skanstatic int 128169689Skandead_read(ap) 129169689Skan struct vop_read_args /* { 130169689Skan struct vnode *a_vp; 131169689Skan struct uio *a_uio; 132169689Skan int a_ioflag; 133169689Skan struct ucred *a_cred; 134169689Skan } */ *ap; 135169689Skan{ 136169689Skan 137169689Skan if (chkvnlock(ap->a_vp)) 138169689Skan panic("dead_read: lock"); 139169689Skan /* 140169689Skan * Return EOF for tty devices, EIO for others 141169689Skan */ 142169689Skan if ((ap->a_vp->v_vflag & VV_ISTTY) == 0) 143169689Skan return (EIO); 144169689Skan return (0); 145169689Skan} 146169689Skan 147169689Skan/* 148169689Skan * Vnode op for write 149169689Skan */ 150169689Skan/* ARGSUSED */ 151169689Skanstatic int 152169689Skandead_write(ap) 153169689Skan struct vop_write_args /* { 154169689Skan struct vnode *a_vp; 155169689Skan struct uio *a_uio; 156169689Skan int a_ioflag; 157169689Skan struct ucred *a_cred; 158169689Skan } */ *ap; 159169689Skan{ 160169689Skan 161169689Skan if (chkvnlock(ap->a_vp)) 162169689Skan panic("dead_write: lock"); 163169689Skan return (EIO); 164169689Skan} 165169689Skan 166/* 167 * Device ioctl operation. 168 */ 169/* ARGSUSED */ 170static int 171dead_ioctl(ap) 172 struct vop_ioctl_args /* { 173 struct vnode *a_vp; 174 u_long a_command; 175 caddr_t a_data; 176 int a_fflag; 177 struct ucred *a_cred; 178 struct proc *a_p; 179 } */ *ap; 180{ 181 182 if (!chkvnlock(ap->a_vp)) 183 return (ENOTTY); 184 /* XXX: Doesn't this just recurse back here ? */ 185 return (VCALL(ap->a_vp, VOFFSET(vop_ioctl), ap)); 186} 187 188 189/* 190 * Wait until the vnode has finished changing state. 191 */ 192static int 193dead_lock(ap) 194 struct vop_lock_args /* { 195 struct vnode *a_vp; 196 int a_flags; 197 struct proc *a_p; 198 } */ *ap; 199{ 200 struct vnode *vp = ap->a_vp; 201 202 /* 203 * Since we are not using the lock manager, we must clear 204 * the interlock here. 205 */ 206 if (ap->a_flags & LK_INTERLOCK) { 207 mtx_unlock(&vp->v_interlock); 208 ap->a_flags &= ~LK_INTERLOCK; 209 } 210 if (!chkvnlock(vp)) 211 return (0); 212 return (VCALL(vp, VOFFSET(vop_lock), ap)); 213} 214 215/* 216 * Wait until the vnode has finished changing state. 217 */ 218static int 219dead_bmap(ap) 220 struct vop_bmap_args /* { 221 struct vnode *a_vp; 222 daddr_t a_bn; 223 struct bufobj **a_bop; 224 daddr_t *a_bnp; 225 int *a_runp; 226 int *a_runb; 227 } */ *ap; 228{ 229 230 if (!chkvnlock(ap->a_vp)) 231 return (EIO); 232 return (VOP_BMAP(ap->a_vp, ap->a_bn, ap->a_bop, ap->a_bnp, ap->a_runp, ap->a_runb)); 233} 234 235/* 236 * We have to wait during times when the vnode is 237 * in a state of change. 238 */ 239static int 240chkvnlock(vp) 241 register struct vnode *vp; 242{ 243 int locked = 0; 244 245 VI_LOCK(vp); 246 while (vp->v_iflag & VI_XLOCK) { 247 vp->v_iflag |= VI_XWANT; 248 (void) msleep((caddr_t)vp, VI_MTX(vp), PINOD, "ckvnlk", 0); 249 locked = 1; 250 } 251 VI_UNLOCK(vp); 252 return (locked); 253} 254 255/* 256 * Trivial poll routine that always returns POLLHUP. 257 * This is necessary so that a process which is polling a file 258 * gets notified when that file is revoke()d. 259 */ 260static int 261dead_poll(ap) 262 struct vop_poll_args *ap; 263{ 264 return (POLLHUP); 265} 266