1 /*	$OpenBSD: vfs_default.c,v 1.26 2005/07/03 20:13:59 drahn 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 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/proc.h>
43 #include <sys/mount.h>
44 #include <sys/vnode.h>
45 #include <sys/namei.h>
46 #include <sys/malloc.h>
47 #include <sys/pool.h>
48 #include <sys/event.h>
49 #include <miscfs/specfs/specdev.h>
50 
51 
52 extern struct simplelock spechash_slock;
53 
54 int filt_generic_readwrite(struct knote *kn, long hint);
55 void filt_generic_detach(struct knote *kn);
56 
57 /*
58  * Eliminate all activity associated with  the requested vnode
59  * and with all vnodes aliased to the requested vnode.
60  */
61 int
vop_generic_revoke(v)62 vop_generic_revoke(v)
63 	void *v;
64 {
65 	struct vop_revoke_args /* {
66 		struct vnodeop_desc *a_desc;
67 		struct vnode *a_vp;
68 		int a_flags;
69 	} */ *ap = v;
70 	struct vnode *vp, *vq;
71 	struct proc *p = curproc;
72 
73 #ifdef DIAGNOSTIC
74 	if ((ap->a_flags & REVOKEALL) == 0)
75 		panic("vop_generic_revoke");
76 #endif
77 
78 	vp = ap->a_vp;
79 	simple_lock(&vp->v_interlock);
80 
81 	if (vp->v_flag & VALIASED) {
82 		/*
83 		 * If a vgone (or vclean) is already in progress,
84 		 * wait until it is done and return.
85 		 */
86 		if (vp->v_flag & VXLOCK) {
87 			vp->v_flag |= VXWANT;
88 			simple_unlock(&vp->v_interlock);
89 			tsleep(vp, PINOD, "vop_generic_revokeall", 0);
90 			return(0);
91 		}
92 		/*
93 		 * Ensure that vp will not be vgone'd while we
94 		 * are eliminating its aliases.
95 		 */
96 		vp->v_flag |= VXLOCK;
97 		simple_unlock(&vp->v_interlock);
98 		while (vp->v_flag & VALIASED) {
99 			simple_lock(&spechash_slock);
100 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
101 				if (vq->v_rdev != vp->v_rdev ||
102 				    vq->v_type != vp->v_type || vp == vq)
103 					continue;
104 				simple_unlock(&spechash_slock);
105 				vgone(vq);
106 				break;
107 			}
108 			simple_unlock(&spechash_slock);
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 	vgonel(vp, p);
119 	return (0);
120 }
121 
122 
123 int
vop_generic_bwrite(v)124 vop_generic_bwrite(v)
125 	void *v;
126 {
127 	struct vop_bwrite_args *ap = v;
128 
129 	return (bwrite(ap->a_bp));
130 }
131 
132 
133 int
vop_generic_abortop(v)134 vop_generic_abortop(v)
135 	void *v;
136 {
137 	struct vop_abortop_args /* {
138 		struct vnodeop_desc *a_desc;
139 		struct vnode *a_dvp;
140 		struct componentname *a_cnp;
141 	} */ *ap = v;
142 
143 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
144 		pool_put(&namei_pool, ap->a_cnp->cn_pnbuf);
145 	return (0);
146 }
147 
148 /*
149  * Stubs to use when there is no locking to be done on the underlying object.
150  * A minimal shared lock is necessary to ensure that the underlying object
151  * is not revoked while an operation is in progress. So, an active shared
152  * count is maintained in an auxiliary vnode lock structure.
153  */
154 int
vop_generic_lock(v)155 vop_generic_lock(v)
156 	void *v;
157 {
158 	struct vop_lock_args /* {
159 		struct vnodeop_desc *a_desc;
160 		struct vnode *a_vp;
161 		int a_flags;
162 		struct proc *a_p;
163 	} */ *ap = v;
164 
165 #ifdef notyet
166 	/*
167 	 * This code cannot be used until all the non-locking filesystems
168 	 * (notably NFS) are converted to properly lock and release nodes.
169 	 * Also, certain vnode operations change the locking state within
170 	 * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
171 	 * and symlink). Ideally these operations should not change the
172 	 * lock state, but should be changed to let the caller of the
173 	 * function unlock them. Otherwise all intermediate vnode layers
174 	 * (such as union, umapfs, etc) must catch these functions to do
175 	 * the necessary locking at their layer. Note that the inactive
176 	 * and lookup operations also change their lock state, but this
177 	 * cannot be avoided, so these two operations will always need
178 	 * to be handled in intermediate layers.
179 	 */
180 	struct vnode *vp = ap->a_vp;
181 	int vnflags, flags = ap->a_flags;
182 
183 	if (vp->v_vnlock == NULL) {
184 		if ((flags & LK_TYPE_MASK) == LK_DRAIN)
185 			return (0);
186 		MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock),
187 		    M_VNODE, M_WAITOK);
188 		lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
189 	}
190 	switch (flags & LK_TYPE_MASK) {
191 	case LK_DRAIN:
192 		vnflags = LK_DRAIN;
193 		break;
194 	case LK_EXCLUSIVE:
195 	case LK_SHARED:
196 		vnflags = LK_SHARED;
197 		break;
198 	case LK_UPGRADE:
199 	case LK_EXCLUPGRADE:
200 	case LK_DOWNGRADE:
201 		return (0);
202 	case LK_RELEASE:
203 	default:
204 		panic("vop_generic_lock: bad operation %d", flags & LK_TYPE_MASK);
205 	}
206 	if (flags & LK_INTERLOCK)
207 		vnflags |= LK_INTERLOCK;
208 	return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p));
209 #else /* for now */
210 	/*
211 	 * Since we are not using the lock manager, we must clear
212 	 * the interlock here.
213 	 */
214 	if (ap->a_flags & LK_INTERLOCK)
215 		simple_unlock(&ap->a_vp->v_interlock);
216 	return (0);
217 #endif
218 }
219 
220 /*
221  * Decrement the active use count.
222  */
223 
224 int
vop_generic_unlock(v)225 vop_generic_unlock(v)
226 	void *v;
227 {
228 	return (0);
229 }
230 
231 /*
232  * Return whether or not the node is in use.
233  */
234 int
vop_generic_islocked(v)235 vop_generic_islocked(v)
236 	void *v;
237 {
238 	return (0);
239 }
240 
241 struct filterops generic_filtops =
242 	{ 1, NULL, filt_generic_detach, filt_generic_readwrite };
243 
244 int
vop_generic_kqfilter(v)245 vop_generic_kqfilter(v)
246 	void *v;
247 {
248 	struct vop_kqfilter_args /* {
249 		struct vnodeop_desc *a_desc;
250 		struct vnode *a_vp;
251 		struct knote *a_kn;
252 	} */ *ap = v;
253 	struct knote *kn = ap->a_kn;
254 
255 	switch (kn->kn_filter) {
256 	case EVFILT_READ:
257 	case EVFILT_WRITE:
258 		kn->kn_fop = &generic_filtops;
259 		break;
260 	default:
261 		return (1);
262 	}
263 
264 	return (0);
265 }
266 
267 void
filt_generic_detach(struct knote * kn)268 filt_generic_detach(struct knote *kn)
269 {
270 }
271 
272 int
filt_generic_readwrite(struct knote * kn,long hint)273 filt_generic_readwrite(struct knote *kn, long hint)
274 {
275 	/*
276 	 * filesystem is gone, so set the EOF flag and schedule
277 	 * the knote for deletion.
278 	 */
279 	if (hint == NOTE_REVOKE) {
280 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
281 		return (1);
282 	}
283 
284         kn->kn_data = 0;
285         return (1);
286 }
287 
288 int lease_check(void *);
289 
290 int
lease_check(void * v)291 lease_check(void *v)
292 {
293 	return (0);
294 }
295