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