xref: /openbsd-src/sys/kern/vfs_vops.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: vfs_vops.c,v 1.9 2013/08/13 05:52:24 guenther 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 #include <sys/unistd.h>
49 
50 #ifdef VFSLCKDEBUG
51 #define ASSERT_VP_ISLOCKED(vp) do {                             \
52         if (((vp)->v_flag & VLOCKSWORK) && !VOP_ISLOCKED(vp))   \
53                 VOP_PRINT(vp);                                  \
54                 panic("vp not locked");                         \
55 } while (0)
56 #else
57 #define ASSERT_VP_ISLOCKED(vp)  /* nothing */
58 #endif
59 
60 int
61 VOP_ISLOCKED(struct vnode *vp)
62 {
63 	struct vop_islocked_args a;
64 	a.a_vp = vp;
65 
66 	if (vp->v_op->vop_islocked == NULL)
67 		return (EOPNOTSUPP);
68 
69 	return ((vp->v_op->vop_islocked)(&a));
70 }
71 
72 int
73 VOP_LOOKUP(struct vnode *dvp, struct vnode **vpp,
74     struct componentname *cnp)
75 {
76 	struct vop_lookup_args a;
77 	a.a_dvp = dvp;
78 	a.a_vpp = vpp;
79 	a.a_cnp = cnp;
80 
81 	if (dvp->v_op->vop_lookup == NULL)
82 		return (EOPNOTSUPP);
83 
84 	return ((dvp->v_op->vop_lookup)(&a));
85 }
86 
87 int
88 VOP_CREATE(struct vnode *dvp, struct vnode **vpp,
89     struct componentname *cnp, struct vattr *vap)
90 {
91 	struct vop_create_args a;
92 	a.a_dvp = dvp;
93 	a.a_vpp = vpp;
94 	a.a_cnp = cnp;
95 	a.a_vap = vap;
96 
97 	ASSERT_VP_ISLOCKED(dvp);
98 
99 	if (dvp->v_op->vop_create == NULL)
100 		return (EOPNOTSUPP);
101 
102 	return ((dvp->v_op->vop_create)(&a));
103 }
104 
105 int
106 VOP_MKNOD(struct vnode *dvp, struct vnode **vpp,
107     struct componentname *cnp, struct vattr *vap)
108 {
109 	struct vop_mknod_args a;
110 	a.a_dvp = dvp;
111 	a.a_vpp = vpp;
112 	a.a_cnp = cnp;
113 	a.a_vap = vap;
114 
115 	ASSERT_VP_ISLOCKED(dvp);
116 
117 	if (dvp->v_op->vop_mknod == NULL)
118 		return (EOPNOTSUPP);
119 
120 	return ((dvp->v_op->vop_mknod)(&a));
121 }
122 
123 int
124 VOP_OPEN(struct vnode *vp, int mode, struct ucred *cred, struct proc *p)
125 {
126 	struct vop_open_args a;
127 	a.a_vp = vp;
128 	a.a_mode = mode;
129 	a.a_cred = cred;
130 	a.a_p = p;
131 
132 	if (vp->v_op->vop_open == NULL)
133 		return (EOPNOTSUPP);
134 
135 	return ((vp->v_op->vop_open)(&a));
136 }
137 
138 int
139 VOP_CLOSE(struct vnode *vp, int fflag, struct ucred *cred, struct proc *p)
140 {
141 	struct vop_close_args a;
142 	a.a_vp = vp;
143 	a.a_fflag = fflag;
144 	a.a_cred = cred;
145 	a.a_p = p;
146 
147 	ASSERT_VP_ISLOCKED(vp);
148 
149 	if (vp->v_op->vop_close == NULL)
150 		return (EOPNOTSUPP);
151 
152 	return ((vp->v_op->vop_close)(&a));
153 }
154 
155 int
156 VOP_ACCESS(struct vnode *vp, int mode, struct ucred *cred, struct proc *p)
157 {
158 	struct vop_access_args a;
159 	a.a_vp = vp;
160 	a.a_mode = mode;
161 	a.a_cred = cred;
162 	a.a_p = p;
163 
164 	ASSERT_VP_ISLOCKED(vp);
165 
166 	if (vp->v_op->vop_access == NULL)
167 		return (EOPNOTSUPP);
168 
169 	return ((vp->v_op->vop_access)(&a));
170 }
171 
172 int
173 VOP_GETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred,
174     struct proc *p)
175 {
176 	struct vop_getattr_args a;
177 	a.a_vp = vp;
178 	a.a_vap = vap;
179 	a.a_cred = cred;
180 	a.a_p = p;
181 
182 	if (vp->v_op->vop_getattr == NULL)
183 		return (EOPNOTSUPP);
184 
185 	return ((vp->v_op->vop_getattr)(&a));
186 }
187 
188 int
189 VOP_SETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred,
190     struct proc *p)
191 {
192 	struct vop_setattr_args a;
193 	a.a_vp = vp;
194 	a.a_vap = vap;
195 	a.a_cred = cred;
196 	a.a_p = p;
197 
198 	ASSERT_VP_ISLOCKED(vp);
199 
200 	if (vp->v_op->vop_setattr == NULL)
201 		return (EOPNOTSUPP);
202 
203 	return ((vp->v_op->vop_setattr)(&a));
204 }
205 
206 int
207 VOP_READ(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
208 {
209 	struct vop_read_args a;
210 	a.a_vp = vp;
211 	a.a_uio = uio;
212 	a.a_ioflag = ioflag;
213 	a.a_cred = cred;
214 
215 	ASSERT_VP_ISLOCKED(vp);
216 
217 	if (vp->v_op->vop_read == NULL)
218 		return (EOPNOTSUPP);
219 
220 	return ((vp->v_op->vop_read)(&a));
221 }
222 
223 int
224 VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag,
225     struct ucred *cred)
226 {
227 	struct vop_write_args a;
228 	a.a_vp = vp;
229 	a.a_uio = uio;
230 	a.a_ioflag = ioflag;
231 	a.a_cred = cred;
232 
233 	ASSERT_VP_ISLOCKED(vp);
234 
235 	if (vp->v_op->vop_write == NULL)
236 		return (EOPNOTSUPP);
237 
238 	return ((vp->v_op->vop_write)(&a));
239 }
240 
241 int
242 VOP_IOCTL(struct vnode *vp, u_long command, void *data, int fflag,
243     struct ucred *cred, struct proc *p)
244 {
245 	struct vop_ioctl_args a;
246 	a.a_vp = vp;
247 	a.a_command = command;
248 	a.a_data = data;
249 	a.a_fflag = fflag;
250 	a.a_cred = cred;
251 	a.a_p = p;
252 
253 	if (vp->v_op->vop_ioctl == NULL)
254 		return (EOPNOTSUPP);
255 
256 	return ((vp->v_op->vop_ioctl)(&a));
257 
258 }
259 
260 int
261 VOP_POLL(struct vnode *vp, int events, struct proc *p)
262 {
263 	struct vop_poll_args a;
264 	a.a_vp = vp;
265 	a.a_events = events;
266 	a.a_p = p;
267 
268 	if (vp->v_op->vop_poll == NULL)
269 		return (EOPNOTSUPP);
270 
271 	return ((vp->v_op->vop_poll)(&a));
272 }
273 
274 int
275 VOP_KQFILTER(struct vnode *vp, struct knote *kn)
276 {
277 	struct vop_kqfilter_args a;
278 	a.a_vp = vp;
279 	a.a_kn = kn;
280 
281 	if (vp->v_op->vop_kqfilter == NULL)
282 		return (EOPNOTSUPP);
283 
284 	return ((vp->v_op->vop_kqfilter)(&a));
285 }
286 
287 int
288 VOP_REVOKE(struct vnode *vp, int flags)
289 {
290 	struct vop_revoke_args a;
291 	a.a_vp = vp;
292 	a.a_flags = flags;
293 
294 	if (vp->v_op->vop_revoke == NULL)
295 		return (EOPNOTSUPP);
296 
297 	return ((vp->v_op->vop_revoke)(&a));
298 }
299 
300 int
301 VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor,
302     struct proc *p)
303 {
304 	struct vop_fsync_args a;
305 	a.a_vp = vp;
306 	a.a_cred = cred;
307 	a.a_waitfor = waitfor;
308 	a.a_p = p;
309 
310 	ASSERT_VP_ISLOCKED(vp);
311 
312 	if (vp->v_op->vop_fsync == NULL)
313 		return (EOPNOTSUPP);
314 
315 	return ((vp->v_op->vop_fsync)(&a));
316 }
317 
318 int
319 VOP_REMOVE(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
320 {
321 	struct vop_remove_args a;
322 	a.a_dvp = dvp;
323         a.a_vp = vp;
324 	a.a_cnp = cnp;
325 
326 	ASSERT_VP_ISLOCKED(dvp);
327 	ASSERT_VP_ISLOCKED(vp);
328 
329 	if (dvp->v_op->vop_remove == NULL)
330 		return (EOPNOTSUPP);
331 
332 	return ((dvp->v_op->vop_remove)(&a));
333 }
334 
335 int
336 VOP_LINK(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
337 {
338 	struct vop_link_args a;
339 	a.a_dvp = dvp;
340 	a.a_vp = vp;
341 	a.a_cnp = cnp;
342 
343 	ASSERT_VP_ISLOCKED(dvp);
344 
345 	if (dvp->v_op->vop_link == NULL)
346 		return (EOPNOTSUPP);
347 
348 	return ((dvp->v_op->vop_link)(&a));
349 }
350 
351 int
352 VOP_RENAME(struct vnode *fdvp, struct vnode *fvp,
353     struct componentname *fcnp, struct vnode *tdvp, struct vnode *tvp,
354     struct componentname *tcnp)
355 {
356 	struct vop_rename_args a;
357 	a.a_fdvp = fdvp;
358 	a.a_fvp = fvp;
359 	a.a_fcnp = fcnp;
360 	a.a_tdvp = tdvp;
361 	a.a_tvp = tvp;
362 	a.a_tcnp = tcnp;
363 
364 	ASSERT_VP_ISLOCKED(tdvp);
365 
366 	if (fdvp->v_op->vop_rename == NULL)
367 		return (EOPNOTSUPP);
368 
369 	return ((fdvp->v_op->vop_rename)(&a));
370 }
371 
372 int
373 VOP_MKDIR(struct vnode *dvp, struct vnode **vpp,
374     struct componentname *cnp, struct vattr *vap)
375 {
376 	struct vop_mkdir_args a;
377 	a.a_dvp = dvp;
378 	a.a_vpp = vpp;
379 	a.a_cnp = cnp;
380 	a.a_vap = vap;
381 
382 	ASSERT_VP_ISLOCKED(dvp);
383 
384 	if (dvp->v_op->vop_mkdir == NULL)
385 		return (EOPNOTSUPP);
386 
387 	return ((dvp->v_op->vop_mkdir)(&a));
388 }
389 
390 int
391 VOP_RMDIR(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
392 {
393 	struct vop_rmdir_args a;
394 	a.a_dvp = dvp;
395 	a.a_vp = vp;
396 	a.a_cnp = cnp;
397 
398 	ASSERT_VP_ISLOCKED(dvp);
399 	ASSERT_VP_ISLOCKED(vp);
400 
401 	if (dvp->v_op->vop_rmdir == NULL)
402 		return (EOPNOTSUPP);
403 
404 	return ((dvp->v_op->vop_rmdir)(&a));
405 }
406 
407 int
408 VOP_SYMLINK(struct vnode *dvp, struct vnode **vpp,
409     struct componentname *cnp, struct vattr *vap, char *target)
410 {
411 	struct vop_symlink_args a;
412 	a.a_dvp = dvp;
413 	a.a_vpp = vpp;
414 	a.a_cnp = cnp;
415 	a.a_vap = vap;
416 	a.a_target = target;
417 
418 	ASSERT_VP_ISLOCKED(dvp);
419 
420 	if (dvp->v_op->vop_symlink == NULL)
421 		return (EOPNOTSUPP);
422 
423 	return ((dvp->v_op->vop_symlink)(&a));
424 }
425 
426 int
427 VOP_READDIR(struct vnode *vp, struct uio *uio, struct ucred *cred,
428     int *eofflag)
429 {
430 	struct vop_readdir_args a;
431 	a.a_vp = vp;
432 	a.a_uio = uio;
433 	a.a_cred = cred;
434 	a.a_eofflag = eofflag;
435 
436 	ASSERT_VP_ISLOCKED(vp);
437 
438 	if (vp->v_op->vop_readdir == NULL)
439 		return (EOPNOTSUPP);
440 
441 	return ((vp->v_op->vop_readdir)(&a));
442 }
443 
444 int
445 VOP_READLINK(struct vnode *vp, struct uio *uio, struct ucred *cred)
446 {
447 	struct vop_readlink_args a;
448 	a.a_vp = vp;
449 	a.a_uio = uio;
450 	a.a_cred = cred;
451 
452 	ASSERT_VP_ISLOCKED(vp);
453 
454 	if (vp->v_op->vop_readlink == NULL)
455 		return (EOPNOTSUPP);
456 
457 	return ((vp->v_op->vop_readlink)(&a));
458 }
459 
460 int
461 VOP_ABORTOP(struct vnode *dvp, struct componentname *cnp)
462 {
463 	struct vop_abortop_args a;
464 	a.a_dvp = dvp;
465 	a.a_cnp = cnp;
466 
467 	if (dvp->v_op->vop_abortop == NULL)
468 		return (EOPNOTSUPP);
469 
470 	return ((dvp->v_op->vop_abortop)(&a));
471 }
472 
473 int
474 VOP_INACTIVE(struct vnode *vp, struct proc *p)
475 {
476 	struct vop_inactive_args a;
477 	a.a_vp = vp;
478 	a.a_p = p;
479 
480 	ASSERT_VP_ISLOCKED(vp);
481 
482 	if (vp->v_op->vop_inactive == NULL)
483 		return (EOPNOTSUPP);
484 
485 	return ((vp->v_op->vop_inactive)(&a));
486 }
487 
488 int
489 VOP_RECLAIM(struct vnode *vp, struct proc *p)
490 {
491 	struct vop_reclaim_args a;
492 	a.a_vp = vp;
493 	a.a_p = p;
494 
495 	if (vp->v_op->vop_reclaim == NULL)
496 		return (EOPNOTSUPP);
497 
498 	return ((vp->v_op->vop_reclaim)(&a));
499 }
500 
501 int
502 VOP_LOCK(struct vnode *vp, int flags, struct proc *p)
503 {
504 	struct vop_lock_args a;
505 	a.a_vp = vp;
506 	a.a_flags = flags;
507 	a.a_p = p;
508 
509 	if (vp->v_op->vop_lock == NULL)
510 		return (EOPNOTSUPP);
511 
512 	return ((vp->v_op->vop_lock)(&a));
513 }
514 
515 int
516 VOP_UNLOCK(struct vnode *vp, int flags, struct proc *p)
517 {
518 	struct vop_unlock_args a;
519 	a.a_vp = vp;
520 	a.a_flags = flags;
521 	a.a_p = p;
522 
523 	if (vp->v_op->vop_unlock == NULL)
524 		return (EOPNOTSUPP);
525 
526 	return ((vp->v_op->vop_unlock)(&a));
527 }
528 
529 int
530 VOP_BMAP(struct vnode *vp, daddr_t bn, struct vnode **vpp,
531     daddr_t *bnp, int *runp)
532 {
533 	struct vop_bmap_args a;
534 	a.a_vp = vp;
535 	a.a_bn = bn;
536 	a.a_vpp = vpp;
537 	a.a_bnp = bnp;
538 	a.a_runp = runp;
539 
540 	ASSERT_VP_ISLOCKED(vp);
541 
542 	if (vp->v_op->vop_bmap == NULL)
543 		return (EOPNOTSUPP);
544 
545 	return ((vp->v_op->vop_bmap)(&a));
546 }
547 
548 int
549 VOP_PRINT(struct vnode *vp)
550 {
551 	struct vop_print_args a;
552 	a.a_vp = vp;
553 
554 	if (vp->v_op->vop_print == NULL)
555 		return (EOPNOTSUPP);
556 
557 	return ((vp->v_op->vop_print)(&a));
558 }
559 
560 int
561 VOP_PATHCONF(struct vnode *vp, int name, register_t *retval)
562 {
563 	struct vop_pathconf_args a;
564 
565 	/*
566 	 * Handle names that are constant across filesystem
567 	 */
568 	switch (name) {
569 	case _PC_PATH_MAX:
570 		*retval = PATH_MAX;
571 		return (0);
572 	case _PC_PIPE_BUF:
573 		*retval = PIPE_BUF;
574 		return (0);
575 	case _PC_ASYNC_IO:
576 	case _PC_PRIO_IO:
577 	case _PC_SYNC_IO:
578 		*retval = 0;
579 		return (0);
580 
581 	}
582 
583 	a.a_vp = vp;
584 	a.a_name = name;
585 	a.a_retval = retval;
586 
587 	ASSERT_VP_ISLOCKED(vp);
588 
589 	if (vp->v_op->vop_pathconf == NULL)
590 		return (EOPNOTSUPP);
591 
592 	return ((vp->v_op->vop_pathconf)(&a));
593 }
594 
595 int
596 VOP_ADVLOCK(struct vnode *vp, void *id, int op, struct flock *fl, int flags)
597 {
598 	struct vop_advlock_args a;
599 	a.a_vp = vp;
600 	a.a_id = id;
601 	a.a_op = op;
602 	a.a_fl = fl;
603 	a.a_flags = flags;
604 
605 	if (vp->v_op->vop_advlock == NULL)
606 		return (EOPNOTSUPP);
607 
608 	return ((vp->v_op->vop_advlock)(&a));
609 }
610 
611 int
612 VOP_REALLOCBLKS(struct vnode *vp, struct cluster_save *buflist)
613 {
614 	struct vop_reallocblks_args a;
615 	a.a_vp = vp;
616 	a.a_buflist = buflist;
617 
618 	ASSERT_VP_ISLOCKED(vp);
619 
620 	if (vp->v_op->vop_reallocblks == NULL)
621 		return (EOPNOTSUPP);
622 
623 	return ((vp->v_op->vop_reallocblks)(&a));
624 }
625 
626 int
627 VOP_STRATEGY(struct buf *bp)
628 {
629 	struct vop_strategy_args a;
630 	a.a_bp = bp;
631 
632 	if (bp->b_vp->v_op->vop_strategy == NULL)
633 		return (EOPNOTSUPP);
634 
635 	return ((bp->b_vp->v_op->vop_strategy)(&a));
636 }
637 
638 int
639 VOP_BWRITE(struct buf *bp)
640 {
641 	struct vop_bwrite_args a;
642 	a.a_bp = bp;
643 
644 	if (bp->b_vp->v_op->vop_bwrite == NULL)
645 		return (EOPNOTSUPP);
646 
647 	return ((bp->b_vp->v_op->vop_bwrite)(&a));
648 }
649