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