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