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