genfs_vnops.c revision 1.7 1 /* $NetBSD: genfs_vnops.c,v 1.7 1998/06/05 19:53:00 kleink Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/proc.h>
40 #include <sys/kernel.h>
41 #include <sys/mount.h>
42 #include <sys/namei.h>
43 #include <sys/vnode.h>
44 #include <sys/malloc.h>
45 #include <sys/poll.h>
46
47 #include <miscfs/genfs/genfs.h>
48 #include <miscfs/specfs/specdev.h>
49
50 int
51 genfs_poll(v)
52 void *v;
53 {
54 struct vop_poll_args /* {
55 struct vnode *a_vp;
56 int a_events;
57 struct proc *a_p;
58 } */ *ap = v;
59
60 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
61 }
62
63 int
64 genfs_fsync(v)
65 void *v;
66 {
67 struct vop_fsync_args /* {
68 struct vnode *a_vp;
69 struct ucred *a_cred;
70 int a_flags;
71 struct proc *a_p;
72 } */ *ap = v;
73 register struct vnode *vp = ap->a_vp;
74 struct timespec ts;
75
76 vflushbuf(vp, (ap->a_flags & FSYNC_WAIT) != 0);
77 if ((ap->a_flags & FSYNC_DATAONLY) != 0) {
78 return (0);
79 } else {
80 TIMEVAL_TO_TIMESPEC(&time, &ts);
81 return (VOP_UPDATE(ap->a_vp, &ts, &ts,
82 (ap->a_flags & FSYNC_WAIT) != 0));
83 }
84 }
85
86 int
87 genfs_seek(v)
88 void *v;
89 {
90 struct vop_seek_args /* {
91 struct vnode *a_vp;
92 off_t a_oldoff;
93 off_t a_newoff;
94 struct ucred *a_ucred;
95 } */ *ap = v;
96
97 if (ap->a_newoff < 0)
98 return (EINVAL);
99
100 return (0);
101 }
102
103 int
104 genfs_abortop(v)
105 void *v;
106 {
107 struct vop_abortop_args /* {
108 struct vnode *a_dvp;
109 struct componentname *a_cnp;
110 } */ *ap = v;
111
112 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
113 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
114 return (0);
115 }
116
117 /*ARGSUSED*/
118 int
119 genfs_badop(v)
120 void *v;
121 {
122
123 panic("genfs: bad op");
124 }
125
126 /*ARGSUSED*/
127 int
128 genfs_nullop(v)
129 void *v;
130 {
131
132 return (0);
133 }
134
135 /*ARGSUSED*/
136 int
137 genfs_eopnotsupp(v)
138 void *v;
139 {
140
141 return (EOPNOTSUPP);
142 }
143
144 /*ARGSUSED*/
145 int
146 genfs_ebadf(v)
147 void *v;
148 {
149
150 return (EBADF);
151 }
152
153
154 /*
155 * Eliminate all activity associated with the requested vnode
156 * and with all vnodes aliased to the requested vnode.
157 */
158 int
159 genfs_revoke(v)
160 void *v;
161 {
162 struct vop_revoke_args /* {
163 struct vnode *a_vp;
164 int a_flags;
165 } */ *ap = v;
166 struct vnode *vp, *vq;
167 struct proc *p = curproc; /* XXX */
168
169 #ifdef DIAGNOSTIC
170 if ((ap->a_flags & REVOKEALL) == 0)
171 panic("genfs_revoke: not revokeall");
172 #endif
173
174 vp = ap->a_vp;
175 simple_lock(&vp->v_interlock);
176
177 if (vp->v_flag & VALIASED) {
178 /*
179 * If a vgone (or vclean) is already in progress,
180 * wait until it is done and return.
181 */
182 if (vp->v_flag & VXLOCK) {
183 vp->v_flag |= VXWANT;
184 simple_unlock(&vp->v_interlock);
185 tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0);
186 return (0);
187 }
188 /*
189 * Ensure that vp will not be vgone'd while we
190 * are eliminating its aliases.
191 */
192 vp->v_flag |= VXLOCK;
193 simple_unlock(&vp->v_interlock);
194 while (vp->v_flag & VALIASED) {
195 simple_lock(&spechash_slock);
196 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
197 if (vq->v_rdev != vp->v_rdev ||
198 vq->v_type != vp->v_type || vp == vq)
199 continue;
200 simple_unlock(&spechash_slock);
201 vgone(vq);
202 break;
203 }
204 if (vq == NULLVP)
205 simple_unlock(&spechash_slock);
206 }
207 /*
208 * Remove the lock so that vgone below will
209 * really eliminate the vnode after which time
210 * vgone will awaken any sleepers.
211 */
212 simple_lock(&vp->v_interlock);
213 vp->v_flag &= ~VXLOCK;
214 }
215 vgonel(vp, p);
216 return (0);
217 }
218
219
220 /*
221 * Stubs to use when there is no locking to be done on the underlying object.
222 * A minimal shared lock is necessary to ensure that the underlying object
223 * is not revoked while an operation is in progress. So, an active shared
224 * count is maintained in an auxillary vnode lock structure.
225 */
226 int
227 genfs_nolock(v)
228 void *v;
229 {
230 struct vop_lock_args /* {
231 struct vnode *a_vp;
232 int a_flags;
233 struct proc *a_p;
234 } */ *ap = v;
235
236 #ifdef notyet
237 /*
238 * This code cannot be used until all the non-locking filesystems
239 * (notably NFS) are converted to properly lock and release nodes.
240 * Also, certain vnode operations change the locking state within
241 * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
242 * and symlink). Ideally these operations should not change the
243 * lock state, but should be changed to let the caller of the
244 * function unlock them. Otherwise all intermediate vnode layers
245 * (such as union, umapfs, etc) must catch these functions to do
246 * the necessary locking at their layer. Note that the inactive
247 * and lookup operations also change their lock state, but this
248 * cannot be avoided, so these two operations will always need
249 * to be handled in intermediate layers.
250 */
251 struct vnode *vp = ap->a_vp;
252 int vnflags, flags = ap->a_flags;
253
254 if (vp->v_vnlock == NULL) {
255 if ((flags & LK_TYPE_MASK) == LK_DRAIN)
256 return (0);
257 MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock),
258 M_VNODE, M_WAITOK);
259 lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
260 }
261 switch (flags & LK_TYPE_MASK) {
262 case LK_DRAIN:
263 vnflags = LK_DRAIN;
264 break;
265 case LK_EXCLUSIVE:
266 case LK_SHARED:
267 vnflags = LK_SHARED;
268 break;
269 case LK_UPGRADE:
270 case LK_EXCLUPGRADE:
271 case LK_DOWNGRADE:
272 return (0);
273 case LK_RELEASE:
274 default:
275 panic("vop_nolock: bad operation %d", flags & LK_TYPE_MASK);
276 }
277 if (flags & LK_INTERLOCK)
278 vnflags |= LK_INTERLOCK;
279 return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock));
280 #else /* for now */
281 /*
282 * Since we are not using the lock manager, we must clear
283 * the interlock here.
284 */
285 if (ap->a_flags & LK_INTERLOCK)
286 simple_unlock(&ap->a_vp->v_interlock);
287 return (0);
288 #endif
289 }
290
291 /*
292 * Decrement the active use count.
293 */
294 int
295 genfs_nounlock(v)
296 void *v;
297 {
298 struct vop_unlock_args /* {
299 struct vnode *a_vp;
300 int a_flags;
301 struct proc *a_p;
302 } */ *ap = v;
303 struct vnode *vp = ap->a_vp;
304
305 if (vp->v_vnlock == NULL)
306 return (0);
307 return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL));
308 }
309
310 /*
311 * Return whether or not the node is in use.
312 */
313 int
314 genfs_noislocked(v)
315 void *v;
316 {
317 struct vop_islocked_args /* {
318 struct vnode *a_vp;
319 } */ *ap = v;
320 struct vnode *vp = ap->a_vp;
321
322 if (vp->v_vnlock == NULL)
323 return (0);
324 return (lockstatus(vp->v_vnlock));
325 }
326