xref: /openbsd-src/sys/kern/vfs_vops.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: vfs_vops.c,v 1.4 2011/07/02 15:52:25 thib Exp $	*/
2 /*
3  * Copyright (c) 2010 Thordur I. Bjornsson <thib@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  *
17  * Copyright (c) 1992, 1993
18  *	The Regents of the University of California.  All rights reserved.
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions
22  * are met:
23  * 1. Redistributions of source code must retain the above copyright
24  *    notice, this list of conditions and the following disclaimer.
25  * 2. Redistributions in binary form must reproduce the above copyright
26  *    notice, this list of conditions and the following disclaimer in the
27  *    documentation and/or other materials provided with the distribution.
28  * 3. Neither the name of the University nor the names of its contributors
29  *    may be used to endorse or promote products derived from this software
30  *    without specific prior written permission.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS AS IS'' AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42  * SUCH DAMAGE.
43  */
44 
45 #include <sys/param.h>
46 #include <sys/mount.h>
47 #include <sys/vnode.h>
48 
49 #ifdef VFSLCKDEBUG
50 #define ASSERT_VP_ISLOCKED(vp) do {                             \
51         if (((vp)->v_flag & VLOCKSWORK) && !VOP_ISLOCKED(vp))   \
52                 VOP_PRINT(vp);                                  \
53                 panic("vp not locked");                         \
54 } while (0)
55 #else
56 #define ASSERT_VP_ISLOCKED(vp)  /* nothing */
57 #endif
58 
59 int
60 VOP_ISLOCKED(struct vnode *vp)
61 {
62 	struct vop_islocked_args a;
63 	a.a_vp = vp;
64 
65 	if (vp->v_op->vop_islocked == NULL)
66 		return (EOPNOTSUPP);
67 
68 	return ((vp->v_op->vop_islocked)(&a));
69 }
70 
71 int
72 VOP_LOOKUP(struct vnode *dvp, struct vnode **vpp,
73     struct componentname *cnp)
74 {
75 	struct vop_lookup_args a;
76 	a.a_dvp = dvp;
77 	a.a_vpp = vpp;
78 	a.a_cnp = cnp;
79 
80 	if (dvp->v_op->vop_lookup == NULL)
81 		return (EOPNOTSUPP);
82 
83 	return ((dvp->v_op->vop_lookup)(&a));
84 }
85 
86 int
87 VOP_CREATE(struct vnode *dvp, struct vnode **vpp,
88     struct componentname *cnp, struct vattr *vap)
89 {
90 	struct vop_create_args a;
91 	a.a_dvp = dvp;
92 	a.a_vpp = vpp;
93 	a.a_cnp = cnp;
94 	a.a_vap = vap;
95 
96 	ASSERT_VP_ISLOCKED(dvp);
97 
98 	if (dvp->v_op->vop_create == NULL)
99 		return (EOPNOTSUPP);
100 
101 	return ((dvp->v_op->vop_create)(&a));
102 }
103 
104 int
105 VOP_MKNOD(struct vnode *dvp, struct vnode **vpp,
106     struct componentname *cnp, struct vattr *vap)
107 {
108 	struct vop_mknod_args a;
109 	a.a_dvp = dvp;
110 	a.a_vpp = vpp;
111 	a.a_cnp = cnp;
112 	a.a_vap = vap;
113 
114 	ASSERT_VP_ISLOCKED(dvp);
115 
116 	if (dvp->v_op->vop_mknod == NULL)
117 		return (EOPNOTSUPP);
118 
119 	return ((dvp->v_op->vop_mknod)(&a));
120 }
121 
122 int
123 VOP_OPEN(struct vnode *vp, int mode, struct ucred *cred, struct proc *p)
124 {
125 	struct vop_open_args a;
126 	a.a_vp = vp;
127 	a.a_mode = mode;
128 	a.a_cred = cred;
129 	a.a_p = p;
130 
131 	if (vp->v_op->vop_open == NULL)
132 		return (EOPNOTSUPP);
133 
134 	return ((vp->v_op->vop_open)(&a));
135 }
136 
137 int
138 VOP_CLOSE(struct vnode *vp, int fflag, struct ucred *cred, struct proc *p)
139 {
140 	struct vop_close_args a;
141 	a.a_vp = vp;
142 	a.a_fflag = fflag;
143 	a.a_cred = cred;
144 	a.a_p = p;
145 
146 	ASSERT_VP_ISLOCKED(vp);
147 
148 	if (vp->v_op->vop_close == NULL)
149 		return (EOPNOTSUPP);
150 
151 	return ((vp->v_op->vop_close)(&a));
152 }
153 
154 int
155 VOP_ACCESS(struct vnode *vp, int mode, struct ucred *cred, struct proc *p)
156 {
157 	struct vop_access_args a;
158 	a.a_vp = vp;
159 	a.a_mode = mode;
160 	a.a_cred = cred;
161 	a.a_p = p;
162 
163 	ASSERT_VP_ISLOCKED(vp);
164 
165 	if (vp->v_op->vop_access == NULL)
166 		return (EOPNOTSUPP);
167 
168 	return ((vp->v_op->vop_access)(&a));
169 }
170 
171 int
172 VOP_GETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred,
173     struct proc *p)
174 {
175 	struct vop_getattr_args a;
176 	a.a_vp = vp;
177 	a.a_vap = vap;
178 	a.a_cred = cred;
179 	a.a_p = p;
180 
181 	if (vp->v_op->vop_getattr == NULL)
182 		return (EOPNOTSUPP);
183 
184 	return ((vp->v_op->vop_getattr)(&a));
185 }
186 
187 int
188 VOP_SETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred,
189     struct proc *p)
190 {
191 	struct vop_setattr_args a;
192 	a.a_vp = vp;
193 	a.a_vap = vap;
194 	a.a_cred = cred;
195 	a.a_p = p;
196 
197 	ASSERT_VP_ISLOCKED(vp);
198 
199 	if (vp->v_op->vop_setattr == NULL)
200 		return (EOPNOTSUPP);
201 
202 	return ((vp->v_op->vop_setattr)(&a));
203 }
204 
205 int
206 VOP_READ(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
207 {
208 	struct vop_read_args a;
209 	a.a_vp = vp;
210 	a.a_uio = uio;
211 	a.a_ioflag = ioflag;
212 	a.a_cred = cred;
213 
214 	ASSERT_VP_ISLOCKED(vp);
215 
216 	if (vp->v_op->vop_read == NULL)
217 		return (EOPNOTSUPP);
218 
219 	return ((vp->v_op->vop_read)(&a));
220 }
221 
222 int
223 VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag,
224     struct ucred *cred)
225 {
226 	struct vop_write_args a;
227 	a.a_vp = vp;
228 	a.a_uio = uio;
229 	a.a_ioflag = ioflag;
230 	a.a_cred = cred;
231 
232 	ASSERT_VP_ISLOCKED(vp);
233 
234 	if (vp->v_op->vop_write == NULL)
235 		return (EOPNOTSUPP);
236 
237 	return ((vp->v_op->vop_write)(&a));
238 }
239 
240 int
241 VOP_IOCTL(struct vnode *vp, u_long command, void *data, int fflag,
242     struct ucred *cred, struct proc *p)
243 {
244 	struct vop_ioctl_args a;
245 	a.a_vp = vp;
246 	a.a_command = command;
247 	a.a_data = data;
248 	a.a_fflag = fflag;
249 	a.a_cred = cred;
250 	a.a_p = p;
251 
252 	if (vp->v_op->vop_ioctl == NULL)
253 		return (EOPNOTSUPP);
254 
255 	return ((vp->v_op->vop_ioctl)(&a));
256 
257 }
258 
259 int
260 VOP_POLL(struct vnode *vp, int events, struct proc *p)
261 {
262 	struct vop_poll_args a;
263 	a.a_vp = vp;
264 	a.a_events = events;
265 	a.a_p = p;
266 
267 	if (vp->v_op->vop_poll == NULL)
268 		return (EOPNOTSUPP);
269 
270 	return ((vp->v_op->vop_poll)(&a));
271 }
272 
273 int
274 VOP_KQFILTER(struct vnode *vp, struct knote *kn)
275 {
276 	struct vop_kqfilter_args a;
277 	a.a_vp = vp;
278 	a.a_kn = kn;
279 
280 	if (vp->v_op->vop_kqfilter == NULL)
281 		return (EOPNOTSUPP);
282 
283 	return ((vp->v_op->vop_kqfilter)(&a));
284 }
285 
286 int
287 VOP_REVOKE(struct vnode *vp, int flags)
288 {
289 	struct vop_revoke_args a;
290 	a.a_vp = vp;
291 	a.a_flags = flags;
292 
293 	if (vp->v_op->vop_revoke == NULL)
294 		return (EOPNOTSUPP);
295 
296 	return ((vp->v_op->vop_revoke)(&a));
297 }
298 
299 int
300 VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor,
301     struct proc *p)
302 {
303 	struct vop_fsync_args a;
304 	a.a_vp = vp;
305 	a.a_cred = cred;
306 	a.a_waitfor = waitfor;
307 	a.a_p = p;
308 
309 	ASSERT_VP_ISLOCKED(vp);
310 
311 	if (vp->v_op->vop_fsync == NULL)
312 		return (EOPNOTSUPP);
313 
314 	return ((vp->v_op->vop_fsync)(&a));
315 }
316 
317 int
318 VOP_REMOVE(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
319 {
320 	struct vop_remove_args a;
321 	a.a_dvp = dvp;
322         a.a_vp = vp;
323 	a.a_cnp = cnp;
324 
325 	ASSERT_VP_ISLOCKED(dvp);
326 	ASSERT_VP_ISLOCKED(vp);
327 
328 	if (dvp->v_op->vop_remove == NULL)
329 		return (EOPNOTSUPP);
330 
331 	return ((dvp->v_op->vop_remove)(&a));
332 }
333 
334 int
335 VOP_LINK(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
336 {
337 	struct vop_link_args a;
338 	a.a_dvp = dvp;
339 	a.a_vp = vp;
340 	a.a_cnp = cnp;
341 
342 	ASSERT_VP_ISLOCKED(dvp);
343 
344 	if (dvp->v_op->vop_link == NULL)
345 		return (EOPNOTSUPP);
346 
347 	return ((dvp->v_op->vop_link)(&a));
348 }
349 
350 int
351 VOP_RENAME(struct vnode *fdvp, struct vnode *fvp,
352     struct componentname *fcnp, struct vnode *tdvp, struct vnode *tvp,
353     struct componentname *tcnp)
354 {
355 	struct vop_rename_args a;
356 	a.a_fdvp = fdvp;
357 	a.a_fvp = fvp;
358 	a.a_fcnp = fcnp;
359 	a.a_tdvp = tdvp;
360 	a.a_tvp = tvp;
361 	a.a_tcnp = tcnp;
362 
363 	ASSERT_VP_ISLOCKED(tdvp);
364 
365 	if (fdvp->v_op->vop_rename == NULL)
366 		return (EOPNOTSUPP);
367 
368 	return ((fdvp->v_op->vop_rename)(&a));
369 }
370 
371 int
372 VOP_MKDIR(struct vnode *dvp, struct vnode **vpp,
373     struct componentname *cnp, struct vattr *vap)
374 {
375 	struct vop_mkdir_args a;
376 	a.a_dvp = dvp;
377 	a.a_vpp = vpp;
378 	a.a_cnp = cnp;
379 	a.a_vap = vap;
380 
381 	ASSERT_VP_ISLOCKED(dvp);
382 
383 	if (dvp->v_op->vop_mkdir == NULL)
384 		return (EOPNOTSUPP);
385 
386 	return ((dvp->v_op->vop_mkdir)(&a));
387 }
388 
389 int
390 VOP_RMDIR(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
391 {
392 	struct vop_rmdir_args a;
393 	a.a_dvp = dvp;
394 	a.a_vp = vp;
395 	a.a_cnp = cnp;
396 
397 	ASSERT_VP_ISLOCKED(dvp);
398 	ASSERT_VP_ISLOCKED(vp);
399 
400 	if (dvp->v_op->vop_rmdir == NULL)
401 		return (EOPNOTSUPP);
402 
403 	return ((dvp->v_op->vop_rmdir)(&a));
404 }
405 
406 int
407 VOP_SYMLINK(struct vnode *dvp, struct vnode **vpp,
408     struct componentname *cnp, struct vattr *vap, char *target)
409 {
410 	struct vop_symlink_args a;
411 	a.a_dvp = dvp;
412 	a.a_vpp = vpp;
413 	a.a_cnp = cnp;
414 	a.a_vap = vap;
415 	a.a_target = target;
416 
417 	ASSERT_VP_ISLOCKED(dvp);
418 
419 	if (dvp->v_op->vop_symlink == NULL)
420 		return (EOPNOTSUPP);
421 
422 	return ((dvp->v_op->vop_symlink)(&a));
423 }
424 
425 int
426 VOP_READDIR(struct vnode *vp, struct uio *uio, struct ucred *cred,
427     int *eofflag, int *ncookies, u_long **cookies)
428 {
429 	struct vop_readdir_args a;
430 	a.a_vp = vp;
431 	a.a_uio = uio;
432 	a.a_cred = cred;
433 	a.a_eofflag = eofflag;
434 	a.a_ncookies = ncookies;
435 	a.a_cookies = cookies;
436 
437 	ASSERT_VP_ISLOCKED(vp);
438 
439 	if (vp->v_op->vop_readdir == NULL)
440 		return (EOPNOTSUPP);
441 
442 	return ((vp->v_op->vop_readdir)(&a));
443 }
444 
445 int
446 VOP_READLINK(struct vnode *vp, struct uio *uio, struct ucred *cred)
447 {
448 	struct vop_readlink_args a;
449 	a.a_vp = vp;
450 	a.a_uio = uio;
451 	a.a_cred = cred;
452 
453 	ASSERT_VP_ISLOCKED(vp);
454 
455 	if (vp->v_op->vop_readlink == NULL)
456 		return (EOPNOTSUPP);
457 
458 	return ((vp->v_op->vop_readlink)(&a));
459 }
460 
461 int
462 VOP_ABORTOP(struct vnode *dvp, struct componentname *cnp)
463 {
464 	struct vop_abortop_args a;
465 	a.a_dvp = dvp;
466 	a.a_cnp = cnp;
467 
468 	if (dvp->v_op->vop_abortop == NULL)
469 		return (EOPNOTSUPP);
470 
471 	return ((dvp->v_op->vop_abortop)(&a));
472 }
473 
474 int
475 VOP_INACTIVE(struct vnode *vp, struct proc *p)
476 {
477 	struct vop_inactive_args a;
478 	a.a_vp = vp;
479 	a.a_p = p;
480 
481 	ASSERT_VP_ISLOCKED(vp);
482 
483 	if (vp->v_op->vop_inactive == NULL)
484 		return (EOPNOTSUPP);
485 
486 	return ((vp->v_op->vop_inactive)(&a));
487 }
488 
489 int
490 VOP_RECLAIM(struct vnode *vp, struct proc *p)
491 {
492 	struct vop_reclaim_args a;
493 	a.a_vp = vp;
494 	a.a_p = p;
495 
496 	if (vp->v_op->vop_reclaim == NULL)
497 		return (EOPNOTSUPP);
498 
499 	return ((vp->v_op->vop_reclaim)(&a));
500 }
501 
502 int
503 VOP_LOCK(struct vnode *vp, int flags, struct proc *p)
504 {
505 	struct vop_lock_args a;
506 	a.a_vp = vp;
507 	a.a_flags = flags;
508 	a.a_p = p;
509 
510 	if (vp->v_op->vop_lock == NULL)
511 		return (EOPNOTSUPP);
512 
513 	return ((vp->v_op->vop_lock)(&a));
514 }
515 
516 int
517 VOP_UNLOCK(struct vnode *vp, int flags, struct proc *p)
518 {
519 	struct vop_unlock_args a;
520 	a.a_vp = vp;
521 	a.a_flags = flags;
522 	a.a_p = p;
523 
524 	if (vp->v_op->vop_unlock == NULL)
525 		return (EOPNOTSUPP);
526 
527 	return ((vp->v_op->vop_unlock)(&a));
528 }
529 
530 int
531 VOP_BMAP(struct vnode *vp, daddr64_t bn, struct vnode **vpp,
532     daddr64_t *bnp, int *runp)
533 {
534 	struct vop_bmap_args a;
535 	a.a_vp = vp;
536 	a.a_bn = bn;
537 	a.a_vpp = vpp;
538 	a.a_bnp = bnp;
539 	a.a_runp = runp;
540 
541 	ASSERT_VP_ISLOCKED(vp);
542 
543 	if (vp->v_op->vop_bmap == NULL)
544 		return (EOPNOTSUPP);
545 
546 	return ((vp->v_op->vop_bmap)(&a));
547 }
548 
549 int
550 VOP_PRINT(struct vnode *vp)
551 {
552 	struct vop_print_args a;
553 	a.a_vp = vp;
554 
555 	if (vp->v_op->vop_print == NULL)
556 		return (EOPNOTSUPP);
557 
558 	return ((vp->v_op->vop_print)(&a));
559 }
560 
561 int
562 VOP_PATHCONF(struct vnode *vp, int name, register_t *retval)
563 {
564 	struct vop_pathconf_args a;
565 	a.a_vp = vp;
566 	a.a_name = name;
567 	a.a_retval = retval;
568 
569 	ASSERT_VP_ISLOCKED(vp);
570 
571 	if (vp->v_op->vop_pathconf == NULL)
572 		return (EOPNOTSUPP);
573 
574 	return ((vp->v_op->vop_pathconf)(&a));
575 }
576 
577 int
578 VOP_ADVLOCK(struct vnode *vp, void *id, int op, struct flock *fl, int flags)
579 {
580 	struct vop_advlock_args a;
581 	a.a_vp = vp;
582 	a.a_id = id;
583 	a.a_op = op;
584 	a.a_fl = fl;
585 	a.a_flags = flags;
586 
587 	if (vp->v_op->vop_advlock == NULL)
588 		return (EOPNOTSUPP);
589 
590 	return ((vp->v_op->vop_advlock)(&a));
591 }
592 
593 int
594 VOP_REALLOCBLKS(struct vnode *vp, struct cluster_save *buflist)
595 {
596 	struct vop_reallocblks_args a;
597 	a.a_vp = vp;
598 	a.a_buflist = buflist;
599 
600 	ASSERT_VP_ISLOCKED(vp);
601 
602 	if (vp->v_op->vop_reallocblks == NULL)
603 		return (EOPNOTSUPP);
604 
605 	return ((vp->v_op->vop_reallocblks)(&a));
606 }
607 
608 int
609 VOP_STRATEGY(struct buf *bp)
610 {
611 	struct vop_strategy_args a;
612 	a.a_bp = bp;
613 
614 	if (bp->b_vp->v_op->vop_strategy == NULL)
615 		return (EOPNOTSUPP);
616 
617 	return ((bp->b_vp->v_op->vop_strategy)(&a));
618 }
619 
620 int
621 VOP_BWRITE(struct buf *bp)
622 {
623 	struct vop_bwrite_args a;
624 	a.a_bp = bp;
625 
626 	if (bp->b_vp->v_op->vop_bwrite == NULL)
627 		return (EOPNOTSUPP);
628 
629 	return ((bp->b_vp->v_op->vop_bwrite)(&a));
630 }
631