xref: /openbsd-src/sys/kern/vfs_default.c (revision 62a742911104f98b9185b2c6b6007d9b1c36396c)
1 /*       $OpenBSD: vfs_default.c,v 1.3 1998/08/06 19:34:24 csapuntz Exp $  */
2 
3 
4 /*
5  *    Portions of this code are:
6  *
7  * Copyright (c) 1989, 1993
8  *	The Regents of the University of California.  All rights reserved.
9  * (c) UNIX System Laboratories, Inc.
10  * All or some portions of this file are derived from material licensed
11  * to the University of California by American Telephone and Telegraph
12  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
13  * the permission of UNIX System Laboratories, Inc.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. All advertising materials mentioning features or use of this software
24  *    must display the following acknowledgement:
25  *	This product includes software developed by the University of
26  *	California, Berkeley and its contributors.
27  * 4. Neither the name of the University nor the names of its contributors
28  *    may be used to endorse or promote products derived from this software
29  *    without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
32  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
35  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41  * SUCH DAMAGE.
42  */
43 
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/proc.h>
48 #include <sys/mount.h>
49 #include <sys/vnode.h>
50 #include <sys/namei.h>
51 #include <sys/malloc.h>
52 #include <miscfs/specfs/specdev.h>
53 
54 
55 extern struct simplelock spechash_slock;
56 
57 /*
58  * Eliminate all activity associated with  the requested vnode
59  * and with all vnodes aliased to the requested vnode.
60  */
61 int
62 vop_generic_revoke(v)
63 	void *v;
64 {
65 	struct vop_revoke_args /* {
66 	        struct vnode *a_vp;
67 		int a_flags;
68 	} */ *ap = v;
69 	struct vnode *vp, *vq;
70 	struct proc *p = curproc;
71 
72 #ifdef DIAGNOSTIC
73 	if ((ap->a_flags & REVOKEALL) == 0)
74 		panic("vop_generic_revoke");
75 #endif
76 
77 	vp = ap->a_vp;
78 	simple_lock(&vp->v_interlock);
79 
80 	if (vp->v_flag & VALIASED) {
81 		/*
82 		 * If a vgone (or vclean) is already in progress,
83 		 * wait until it is done and return.
84 		 */
85 		if (vp->v_flag & VXLOCK) {
86 			vp->v_flag |= VXWANT;
87 			simple_unlock(&vp->v_interlock);
88 			tsleep((caddr_t)vp, PINOD, "vop_generic_revokeall", 0);
89 			return(0);
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 		}
108 		/*
109 		 * Remove the lock so that vgone below will
110 		 * really eliminate the vnode after which time
111 		 * vgone will awaken any sleepers.
112 		 */
113 		simple_lock(&vp->v_interlock);
114 		vp->v_flag &= ~VXLOCK;
115 	}
116 	vgonel(vp, p);
117 	return (0);
118 }
119 
120 
121 int
122 vop_generic_bwrite(v)
123 	void *v;
124 {
125 	struct vop_bwrite_args *ap = v;
126 
127 	return (bwrite(ap->a_bp));
128 }
129 
130 
131 int
132 vop_generic_abortop(v)
133 	void *v;
134 {
135 	struct vop_abortop_args /* {
136 		struct vnode *a_dvp;
137 		struct componentname *a_cnp;
138 	} */ *ap = v;
139 
140 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
141 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
142 	return (0);
143 }
144 
145 /*
146  * Stubs to use when there is no locking to be done on the underlying object.
147  * A minimal shared lock is necessary to ensure that the underlying object
148  * is not revoked while an operation is in progress. So, an active shared
149  * count is maintained in an auxillary vnode lock structure.
150  */
151 int
152 vop_generic_lock(v)
153 	void *v;
154 {
155 	struct vop_lock_args /* {
156 		struct vnode *a_vp;
157 		int a_flags;
158 		struct proc *a_p;
159 	} */ *ap = v;
160 
161 #ifdef notyet
162 	/*
163 	 * This code cannot be used until all the non-locking filesystems
164 	 * (notably NFS) are converted to properly lock and release nodes.
165 	 * Also, certain vnode operations change the locking state within
166 	 * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
167 	 * and symlink). Ideally these operations should not change the
168 	 * lock state, but should be changed to let the caller of the
169 	 * function unlock them. Otherwise all intermediate vnode layers
170 	 * (such as union, umapfs, etc) must catch these functions to do
171 	 * the necessary locking at their layer. Note that the inactive
172 	 * and lookup operations also change their lock state, but this
173 	 * cannot be avoided, so these two operations will always need
174 	 * to be handled in intermediate layers.
175 	 */
176 	struct vnode *vp = ap->a_vp;
177 	int vnflags, flags = ap->a_flags;
178 
179 	if (vp->v_vnlock == NULL) {
180 		if ((flags & LK_TYPE_MASK) == LK_DRAIN)
181 			return (0);
182 		MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock),
183 		    M_VNODE, M_WAITOK);
184 		lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
185 	}
186 	switch (flags & LK_TYPE_MASK) {
187 	case LK_DRAIN:
188 		vnflags = LK_DRAIN;
189 		break;
190 	case LK_EXCLUSIVE:
191 	case LK_SHARED:
192 		vnflags = LK_SHARED;
193 		break;
194 	case LK_UPGRADE:
195 	case LK_EXCLUPGRADE:
196 	case LK_DOWNGRADE:
197 		return (0);
198 	case LK_RELEASE:
199 	default:
200 		panic("vop_generic_lock: bad operation %d", flags & LK_TYPE_MASK);
201 	}
202 	if (flags & LK_INTERLOCK)
203 		vnflags |= LK_INTERLOCK;
204 	return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p));
205 #else /* for now */
206         /*
207          * Since we are not using the lock manager, we must clear
208          * the interlock here.
209          */
210         if (ap->a_flags & LK_INTERLOCK)
211                 simple_unlock(&ap->a_vp->v_interlock);
212         return (0);
213 #endif
214 }
215 
216 /*
217  * Decrement the active use count.
218  */
219 
220 int
221 vop_generic_unlock(v)
222 	void *v;
223 {
224 	struct vop_unlock_args /* {
225 		struct vnode *a_vp;
226 		int a_flags;
227 		struct proc *a_p;
228 	} */ *ap = v;
229 
230 	struct vnode *vp = ap->a_vp;
231 
232 	if (vp->v_vnlock == NULL)
233 		return (0);
234 	return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL, ap->a_p));
235 }
236 
237 /*
238  * Return whether or not the node is in use.
239  */
240 int
241 vop_generic_islocked(v)
242 	void *v;
243 {
244 	struct vop_islocked_args /* {
245 		struct vnode *a_vp;
246 	} */ *ap = v;
247 
248 	struct vnode *vp = ap->a_vp;
249 
250 	if (vp->v_vnlock == NULL)
251 		return (0);
252 	return (lockstatus(vp->v_vnlock));
253 }
254