xref: /openbsd-src/sys/kern/vfs_default.c (revision daf88648c0e349d5c02e1504293082072c981640)
1 /*	$OpenBSD: vfs_default.c,v 1.31 2007/01/16 17:52:18 thib 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 <miscfs/specfs/specdev.h>
49 
50 extern struct simplelock spechash_slock;
51 
52 int filt_generic_readwrite(struct knote *, long);
53 void filt_generic_detach(struct knote *);
54 
55 /*
56  * Eliminate all activity associated with the requested vnode
57  * and with all vnodes aliased to the requested vnode.
58  */
59 int
60 vop_generic_revoke(void *v)
61 {
62 	struct vop_revoke_args /* {
63 		struct vnodeop_desc *a_desc;
64 		struct vnode *a_vp;
65 		int a_flags;
66 	} */ *ap = v;
67 	struct vnode *vp, *vq;
68 	struct proc *p = curproc;
69 
70 #ifdef DIAGNOSTIC
71 	if ((ap->a_flags & REVOKEALL) == 0)
72 		panic("vop_generic_revoke");
73 #endif
74 
75 	vp = ap->a_vp;
76 	simple_lock(&vp->v_interlock);
77 
78 	if (vp->v_flag & VALIASED) {
79 		/*
80 		 * If a vgone (or vclean) is already in progress,
81 		 * wait until it is done and return.
82 		 */
83 		if (vp->v_flag & VXLOCK) {
84 			vp->v_flag |= VXWANT;
85 			simple_unlock(&vp->v_interlock);
86 			tsleep(vp, PINOD, "vop_generic_revokeall", 0);
87 
88 			return(0);
89 		}
90 
91 		/*
92 		 * Ensure that vp will not be vgone'd while we
93 		 * are eliminating its aliases.
94 		 */
95 		vp->v_flag |= VXLOCK;
96 		simple_unlock(&vp->v_interlock);
97 		while (vp->v_flag & VALIASED) {
98 			simple_lock(&spechash_slock);
99 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
100 				if (vq->v_rdev != vp->v_rdev ||
101 				    vq->v_type != vp->v_type || vp == vq)
102 					continue;
103 				simple_unlock(&spechash_slock);
104 				vgone(vq);
105 				break;
106 			}
107 			simple_unlock(&spechash_slock);
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 		simple_lock(&vp->v_interlock);
116 		vp->v_flag &= ~VXLOCK;
117 	}
118 
119 	vgonel(vp, p);
120 
121 	return (0);
122 }
123 
124 int
125 vop_generic_bwrite(void *v)
126 {
127 	struct vop_bwrite_args *ap = v;
128 
129 	return (bwrite(ap->a_bp));
130 }
131 
132 int
133 vop_generic_abortop(void *v)
134 {
135 	struct vop_abortop_args /* {
136 		struct vnodeop_desc *a_desc;
137 		struct vnode *a_dvp;
138 		struct componentname *a_cnp;
139 	} */ *ap = v;
140 
141 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
142 		pool_put(&namei_pool, ap->a_cnp->cn_pnbuf);
143 
144 	return (0);
145 }
146 
147 /*
148  * Stubs to use when there is no locking to be done on the underlying object.
149  * A minimal shared lock is necessary to ensure that the underlying object
150  * is not revoked while an operation is in progress. So, an active shared
151  * count should be maintained in an auxiliary vnode lock structure. However,
152  * that's not done now.
153  */
154 int
155 vop_generic_lock(void *v)
156 {
157 	struct vop_lock_args /* {
158 		struct vnodeop_desc *a_desc;
159 		struct vnode *a_vp;
160 		int a_flags;
161 		struct proc *a_p;
162 	} */ *ap = v;
163 
164 	/*
165 	 * Since we are not using the lock manager, we must clear
166 	 * the interlock here.
167 	 */
168 	if (ap->a_flags & LK_INTERLOCK)
169 		simple_unlock(&ap->a_vp->v_interlock);
170 
171 	return (0);
172 }
173 
174 /*
175  * Decrement the active use count. (Not done currently)
176  */
177 int
178 vop_generic_unlock(void *v)
179 {
180 	return (0);
181 }
182 
183 /*
184  * Return whether or not the node is in use. (Not done currently)
185  */
186 int
187 vop_generic_islocked(void *v)
188 {
189 	return (0);
190 }
191 
192 struct filterops generic_filtops =
193 	{ 1, NULL, filt_generic_detach, filt_generic_readwrite };
194 
195 int
196 vop_generic_kqfilter(void *v)
197 {
198 	struct vop_kqfilter_args /* {
199 		struct vnodeop_desc *a_desc;
200 		struct vnode *a_vp;
201 		struct knote *a_kn;
202 	} */ *ap = v;
203 	struct knote *kn = ap->a_kn;
204 
205 	switch (kn->kn_filter) {
206 	case EVFILT_READ:
207 	case EVFILT_WRITE:
208 		kn->kn_fop = &generic_filtops;
209 		break;
210 	default:
211 		return (1);
212 	}
213 
214 	return (0);
215 }
216 
217 void
218 filt_generic_detach(struct knote *kn)
219 {
220 }
221 
222 int
223 filt_generic_readwrite(struct knote *kn, long hint)
224 {
225 	/*
226 	 * filesystem is gone, so set the EOF flag and schedule
227 	 * the knote for deletion.
228 	 */
229 	if (hint == NOTE_REVOKE) {
230 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
231 		return (1);
232 	}
233 
234         kn->kn_data = 0;
235 
236         return (1);
237 }
238