xref: /openbsd/sys/kern/vfs_default.c (revision 8932bfb7)
1 /*	$OpenBSD: vfs_default.c,v 1.39 2011/07/04 20:35:35 deraadt Exp $  */
2 
3 /*
4  * Portions of this code are:
5  *
6  * Copyright (c) 1989, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  * (c) UNIX System Laboratories, Inc.
9  * All or some portions of this file are derived from material licensed
10  * to the University of California by American Telephone and Telegraph
11  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
12  * the permission of UNIX System Laboratories, Inc.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/proc.h>
42 #include <sys/mount.h>
43 #include <sys/vnode.h>
44 #include <sys/namei.h>
45 #include <sys/malloc.h>
46 #include <sys/pool.h>
47 #include <sys/event.h>
48 #include <sys/specdev.h>
49 
50 int filt_generic_readwrite(struct knote *, long);
51 void filt_generic_detach(struct knote *);
52 
53 /*
54  * Eliminate all activity associated with the requested vnode
55  * and with all vnodes aliased to the requested vnode.
56  */
57 int
58 vop_generic_revoke(void *v)
59 {
60 	struct vop_revoke_args *ap = v;
61 	struct vnode *vp, *vq;
62 	struct proc *p = curproc;
63 
64 #ifdef DIAGNOSTIC
65 	if ((ap->a_flags & REVOKEALL) == 0)
66 		panic("vop_generic_revoke");
67 #endif
68 
69 	vp = ap->a_vp;
70 
71 	if (vp->v_type == VBLK && vp->v_specinfo != 0) {
72 		struct mount *mp = vp->v_specmountpoint;
73 
74 		/*
75 		 * If we have a mount point associated with the vnode, we must
76 		 * flush it out now, as to not leave a dangling zombie mount
77 		 * point laying around in VFS.
78 		 */
79 		if (mp != NULL && !vfs_busy(mp, VB_WRITE|VB_WAIT))
80 			dounmount(mp, MNT_FORCE | MNT_DOOMED, p, NULL);
81 	}
82 
83 	if (vp->v_flag & VALIASED) {
84 		/*
85 		 * If a vgone (or vclean) is already in progress,
86 		 * wait until it is done and return.
87 		 */
88 		if (vp->v_flag & VXLOCK) {
89 			vp->v_flag |= VXWANT;
90 			tsleep(vp, PINOD, "vop_generic_revokeall", 0);
91 
92 			return(0);
93 		}
94 
95 		/*
96 		 * Ensure that vp will not be vgone'd while we
97 		 * are eliminating its aliases.
98 		 */
99 		vp->v_flag |= VXLOCK;
100 		while (vp->v_flag & VALIASED) {
101 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
102 				if (vq->v_rdev != vp->v_rdev ||
103 				    vq->v_type != vp->v_type || vp == vq)
104 					continue;
105 				vgone(vq);
106 				break;
107 			}
108 		}
109 
110 		/*
111 		 * Remove the lock so that vgone below will
112 		 * really eliminate the vnode after which time
113 		 * vgone will awaken any sleepers.
114 		 */
115 		vp->v_flag &= ~VXLOCK;
116 	}
117 
118 	vgonel(vp, p);
119 
120 	return (0);
121 }
122 
123 int
124 vop_generic_bmap(void *v)
125 {
126 	struct vop_bmap_args *ap = v;
127 
128 	if (ap->a_vpp)
129 		*ap->a_vpp = ap->a_vp;
130 	if (ap->a_bnp)
131 		*ap->a_bnp = ap->a_bn;
132 	if (ap->a_runp)
133 		*ap->a_runp = 0;
134 
135 	return (0);
136 }
137 
138 int
139 vop_generic_bwrite(void *v)
140 {
141 	struct vop_bwrite_args *ap = v;
142 
143 	return (bwrite(ap->a_bp));
144 }
145 
146 int
147 vop_generic_abortop(void *v)
148 {
149 	struct vop_abortop_args *ap = v;
150 
151 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
152 		pool_put(&namei_pool, ap->a_cnp->cn_pnbuf);
153 
154 	return (0);
155 }
156 
157 /*
158  * Stubs to use when there is no locking to be done on the underlying object.
159  * A minimal shared lock is necessary to ensure that the underlying object
160  * is not revoked while an operation is in progress. So, an active shared
161  * count should be maintained in an auxiliary vnode lock structure. However,
162  * that's not done now.
163  */
164 int
165 vop_generic_lock(void *v)
166 {
167 	return (0);
168 }
169 
170 /*
171  * Decrement the active use count. (Not done currently)
172  */
173 int
174 vop_generic_unlock(void *v)
175 {
176 	return (0);
177 }
178 
179 /*
180  * Return whether or not the node is in use. (Not done currently)
181  */
182 int
183 vop_generic_islocked(void *v)
184 {
185 	return (0);
186 }
187 
188 struct filterops generic_filtops =
189 	{ 1, NULL, filt_generic_detach, filt_generic_readwrite };
190 
191 int
192 vop_generic_kqfilter(void *v)
193 {
194 	struct vop_kqfilter_args *ap = v;
195 	struct knote *kn = ap->a_kn;
196 
197 	switch (kn->kn_filter) {
198 	case EVFILT_READ:
199 	case EVFILT_WRITE:
200 		kn->kn_fop = &generic_filtops;
201 		break;
202 	default:
203 		return (EINVAL);
204 	}
205 
206 	return (0);
207 }
208 
209 /* Trivial lookup routine that always fails. */
210 int
211 vop_generic_lookup(void *v)
212 {
213 	struct vop_lookup_args	*ap = v;
214 
215 	*ap->a_vpp = NULL;
216 	return (ENOTDIR);
217 }
218 
219 void
220 filt_generic_detach(struct knote *kn)
221 {
222 }
223 
224 int
225 filt_generic_readwrite(struct knote *kn, long hint)
226 {
227 	/*
228 	 * filesystem is gone, so set the EOF flag and schedule
229 	 * the knote for deletion.
230 	 */
231 	if (hint == NOTE_REVOKE) {
232 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
233 		return (1);
234 	}
235 
236         kn->kn_data = 0;
237 
238         return (1);
239 }
240