xref: /netbsd-src/sys/kern/vnode_if.c (revision 867d70fc718005c0918b8b8b2f9d7f2d52d0a0db)
1 /*	$NetBSD: vnode_if.c,v 1.118 2022/07/18 04:32:35 thorpej Exp $	*/
2 
3 /*
4  * Warning: DO NOT EDIT! This file is automatically generated!
5  * (Modifications made here may easily be lost!)
6  *
7  * Created from the file:
8  *	NetBSD: vnode_if.src,v 1.84 2022/05/03 08:33:59 hannken Exp
9  * by the script:
10  *	NetBSD: vnode_if.sh,v 1.76 2022/07/18 04:30:30 thorpej Exp
11  */
12 
13 /*
14  * Copyright (c) 1992, 1993, 1994, 1995
15  *	The Regents of the University of California.  All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 3. Neither the name of the University nor the names of its contributors
26  *    may be used to endorse or promote products derived from this software
27  *    without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  */
41 
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: vnode_if.c,v 1.118 2022/07/18 04:32:35 thorpej Exp $");
44 
45 #ifdef _KERNEL_OPT
46 #include "opt_vnode_lockdebug.h"
47 #endif /* _KERNEL_OPT */
48 
49 #include <sys/param.h>
50 #include <sys/mount.h>
51 #include <sys/buf.h>
52 #include <sys/fcntl.h>
53 #include <sys/vnode.h>
54 #include <sys/lock.h>
55 #include <sys/fstrans.h>
56 
57 enum fst_op { FST_NO, FST_YES, FST_LAZY, FST_TRY };
58 
59 static inline int
60 vop_pre(vnode_t *vp, struct mount **mp, bool *mpsafe, enum fst_op op)
61 {
62 	int error;
63 
64 	*mpsafe = (vp->v_vflag & VV_MPSAFE);
65 
66 	if (!*mpsafe) {
67 		KERNEL_LOCK(1, curlwp);
68 	}
69 
70 	if (op == FST_YES || op == FST_LAZY || op == FST_TRY) {
71 		for (;;) {
72 			*mp = vp->v_mount;
73 			if (op == FST_TRY) {
74 				error = fstrans_start_nowait(*mp);
75 				if (error) {
76 					if (!*mpsafe) {
77 						KERNEL_UNLOCK_ONE(curlwp);
78 					}
79 					return error;
80 				}
81 			} else if (op == FST_LAZY) {
82 				fstrans_start_lazy(*mp);
83 			} else {
84 				fstrans_start(*mp);
85 			}
86 			if (__predict_true(*mp == vp->v_mount))
87 				break;
88 			fstrans_done(*mp);
89 		}
90 	} else {
91 		*mp = vp->v_mount;
92 	}
93 
94 	return 0;
95 }
96 
97 static inline u_quad_t
98 vop_pre_get_size(struct vnode *vp)
99 {
100 	mutex_enter(vp->v_interlock);
101 	KASSERT(vp->v_size != VSIZENOTSET);
102 	u_quad_t rv = (u_quad_t)vp->v_size;
103 	mutex_exit(vp->v_interlock);
104 
105 	return rv;
106 }
107 
108 /*
109  * VOP_RMDIR(), VOP_REMOVE(), and VOP_RENAME() need special handling
110  * because they each drop the caller's references on one or more of
111  * their arguments.  While there must be an open file descriptor in
112  * associated with a vnode in order for knotes to be attached to it,
113  * that status could change during the course of the operation.  So,
114  * for the vnode arguments that are WILLRELE or WILLPUT, we check
115  * pre-op if there are registered knotes, take a hold count if so,
116  * and post-op release the hold after activating any knotes still
117  * associated with the vnode.
118  */
119 
120 #define	VOP_POST_KNOTE(thisvp, e, n)					\
121 do {									\
122 	if (__predict_true((e) == 0)) {					\
123 		/*							\
124 		 * VN_KNOTE() does the VN_KEVENT_INTEREST()		\
125 		 * check for us.					\
126 		 */							\
127 		VN_KNOTE((thisvp), (n));				\
128 	}								\
129 } while (/*CONSTCOND*/0)
130 
131 #define	VOP_POST_KNOTE_HELD(thisvp, e, n)				\
132 do {									\
133 	/*								\
134 	 * We don't perform a VN_KEVENT_INTEREST() check here; it	\
135 	 * was already performed when we did the pre-op work that	\
136 	 * caused the vnode to be held in the first place.		\
137 	 */								\
138 	mutex_enter((thisvp)->v_interlock);				\
139 	if (__predict_true((e) == 0)) {					\
140 		knote(&(thisvp)->v_klist->vk_klist, (n));		\
141 	}								\
142 	holdrelel((thisvp));						\
143 	mutex_exit((thisvp)->v_interlock);				\
144 	/*								\
145 	 * thisvp might be gone now!  Don't touch!			\
146 	 */								\
147 } while (/*CONSTCOND*/0)
148 
149 #define	vop_create_post(ap, e)						\
150 	VOP_POST_KNOTE((ap)->a_dvp, (e), NOTE_WRITE)
151 
152 #define	vop_mknod_post(ap, e)						\
153 	VOP_POST_KNOTE((ap)->a_dvp, (e), NOTE_WRITE)
154 
155 #define	vop_setattr_pre(ap)						\
156 	u_quad_t osize = 0;						\
157 	long vp_events =						\
158 	    VN_KEVENT_INTEREST((ap)->a_vp, NOTE_ATTRIB | NOTE_EXTEND)	\
159 	    ? NOTE_ATTRIB : 0;						\
160 	bool check_extend = false;					\
161 	if (__predict_false(vp_events != 0 &&				\
162 	    (ap)->a_vap->va_size != VNOVALSIZE)) {			\
163 		check_extend = true;					\
164 		osize = vop_pre_get_size((ap)->a_vp);			\
165 	}
166 
167 #define	vop_setattr_post(ap, e)						\
168 do {									\
169 	if (__predict_false(vp_events != 0)) {				\
170 		if (__predict_false(check_extend &&			\
171 		    (ap)->a_vap->va_size > osize)) {			\
172 			vp_events |= NOTE_EXTEND;			\
173 		}							\
174 		VOP_POST_KNOTE((ap)->a_vp, (e), vp_events);		\
175 	}								\
176 } while (/*CONSTCOND*/0)
177 
178 #define	vop_setacl_post(ap, e)						\
179 	VOP_POST_KNOTE((ap)->a_vp, (e), NOTE_ATTRIB)
180 
181 #define	vop_link_post(ap, e)						\
182 do {									\
183 	VOP_POST_KNOTE((ap)->a_dvp, (e), NOTE_WRITE);			\
184 	VOP_POST_KNOTE((ap)->a_vp, (e), NOTE_LINK);			\
185 } while (/*CONSTCOND*/0)
186 
187 #define	vop_mkdir_post(ap, e)						\
188 	VOP_POST_KNOTE((ap)->a_dvp, (e), NOTE_WRITE | NOTE_LINK)
189 
190 #define	vop_remove_pre_common(ap)					\
191 	bool post_event_vp =						\
192 	    VN_KEVENT_INTEREST((ap)->a_vp, NOTE_DELETE | NOTE_LINK);	\
193 	if (__predict_false(post_event_vp)) {				\
194 		vhold((ap)->a_vp);					\
195 	}
196 
197 #define	vop_remove_post_common(ap, e, dn, lc)				\
198 do {									\
199 	VOP_POST_KNOTE((ap)->a_dvp, (e), (dn));				\
200 	if (__predict_false(post_event_vp)) {				\
201 		VOP_POST_KNOTE_HELD((ap)->a_vp, (e),			\
202 		    (lc) ? NOTE_LINK : NOTE_DELETE);			\
203 	}								\
204 } while (/*CONSTCOND*/0)
205 
206 /*
207  * One could make the argument that VOP_REMOVE() should send NOTE_LINK
208  * on vp if the resulting link count is not zero, but that's not what
209  * the documentation says.
210  *
211  * We could change this easily by passing ap->ctx_vp_new_nlink to
212  * vop_remove_post_common().
213  */
214 #define	vop_remove_pre(ap)						\
215 	vop_remove_pre_common((ap));					\
216 	/*								\
217 	 * We will assume that the file being removed is deleted unless	\
218 	 * the file system tells us otherwise by updating vp_new_nlink.	\
219 	 */								\
220 	(ap)->ctx_vp_new_nlink = 0;
221 
222 #define	vop_remove_post(ap, e)						\
223 	vop_remove_post_common((ap), (e), NOTE_WRITE, 0)
224 
225 #define	vop_rmdir_pre(ap)						\
226 	vop_remove_pre_common(ap)
227 
228 #define	vop_rmdir_post(ap, e)						\
229 	vop_remove_post_common((ap), (e), NOTE_WRITE | NOTE_LINK, 0)
230 
231 #define	vop_symlink_post(ap, e)						\
232 	VOP_POST_KNOTE((ap)->a_dvp, (e), NOTE_WRITE)
233 
234 #define	vop_open_post(ap, e)						\
235 	VOP_POST_KNOTE((ap)->a_vp, (e), NOTE_OPEN)
236 
237 #define	vop_close_post(ap, e)						\
238 do {									\
239 	extern int (**dead_vnodeop_p)(void *);				\
240 									\
241 	/* See the definition of VN_KNOTE() in <sys/vnode.h>. */	\
242 	if (__predict_false(VN_KEVENT_INTEREST((ap)->a_vp,		\
243 	    NOTE_CLOSE_WRITE | NOTE_CLOSE) && (e) == 0)) {		\
244 		struct vnode *thisvp = (ap)->a_vp;			\
245 		mutex_enter(thisvp->v_interlock);			\
246 		/*							\
247 		 * Don't send NOTE_CLOSE when closing a vnode that's	\
248 		 * been reclaimed or otherwise revoked; a NOTE_REVOKE	\
249 		 * has already been sent, and this close is effectively	\
250 		 * meaningless from the watcher's perspective.		\
251 		 */							\
252 		if (__predict_true(thisvp->v_op != dead_vnodeop_p)) {	\
253 			knote(&thisvp->v_klist->vk_klist,		\
254 			    ((ap)->a_fflag & FWRITE)			\
255 			    ? NOTE_CLOSE_WRITE : NOTE_CLOSE);		\
256 		}							\
257 		mutex_exit(thisvp->v_interlock);			\
258 	}								\
259 } while (/*CONSTCOND*/0)
260 
261 #define	vop_read_post(ap, e)						\
262 	VOP_POST_KNOTE((ap)->a_vp, (e), NOTE_READ)
263 
264 #define	vop_write_pre(ap)						\
265 	off_t ooffset = 0, noffset = 0;					\
266 	u_quad_t osize = 0;						\
267 	long vp_events =						\
268 	    VN_KEVENT_INTEREST((ap)->a_vp, NOTE_WRITE | NOTE_EXTEND)	\
269 	    ? NOTE_WRITE : 0;						\
270 	if (__predict_false(vp_events != 0)) {				\
271 		ooffset = (ap)->a_uio->uio_offset;			\
272 		osize = vop_pre_get_size((ap)->a_vp);			\
273 	}
274 
275 #define	vop_write_post(ap, e)						\
276 do {									\
277 	/*								\
278 	 * If any data was written, we'll post an event, even if	\
279 	 * there was an error.						\
280 	 */								\
281 	noffset = (ap)->a_uio->uio_offset;				\
282 	if (__predict_false(vp_events != 0 && noffset > ooffset)) {	\
283 		if (noffset > osize) {					\
284 			vp_events |= NOTE_EXTEND;			\
285 		}							\
286 		VN_KNOTE((ap)->a_vp, vp_events);			\
287 	}								\
288 } while (/*CONSTCOND*/0)
289 
290 static inline void
291 vop_post(vnode_t *vp, struct mount *mp, bool mpsafe, enum fst_op op)
292 {
293 
294 	if (op == FST_YES || op == FST_LAZY) {
295 		fstrans_done(mp);
296 	}
297 
298 	if (!mpsafe) {
299 		KERNEL_UNLOCK_ONE(curlwp);
300 	}
301 }
302 
303 static inline void
304 assert_vop_unlocked(vnode_t *vp, const char *str)
305 {
306 #if defined(VNODE_LOCKDEBUG)
307 
308 	if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE)
309 		panic("%s: %p %d/%d is locked but should not be",
310 		    str, vp, vp->v_tag, vp->v_type);
311 #endif
312 }
313 
314 static inline void
315 assert_vop_locked(vnode_t *vp, const char *str)
316 {
317 #if defined(VNODE_LOCKDEBUG)
318 
319 	if (VOP_ISLOCKED(vp) == LK_NONE)
320 		panic("%s: %p %d/%d is not locked but should be",
321 		    str, vp, vp->v_tag, vp->v_type);
322 #endif
323 }
324 
325 static inline void
326 assert_vop_elocked(vnode_t *vp, const char *str)
327 {
328 #if defined(VNODE_LOCKDEBUG)
329 
330 	if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE)
331 		panic("%s: %p %d/%d is not exclusive locked but should be",
332 		    str, vp, vp->v_tag, vp->v_type);
333 #endif
334 }
335 
336 const struct vnodeop_desc vop_default_desc = {
337 	0,
338 	"default",
339 	0,
340 	NULL,
341 	VDESC_NO_OFFSET,
342 	VDESC_NO_OFFSET,
343 	VDESC_NO_OFFSET,
344 };
345 
346 
347 const int vop_bwrite_vp_offsets[] = {
348 	VOPARG_OFFSETOF(struct vop_bwrite_args,a_vp),
349 	VDESC_NO_OFFSET
350 };
351 const struct vnodeop_desc vop_bwrite_desc = {
352 	VOP_BWRITE_DESCOFFSET,
353 	"vop_bwrite",
354 	0,
355 	vop_bwrite_vp_offsets,
356 	VDESC_NO_OFFSET,
357 	VDESC_NO_OFFSET,
358 	VDESC_NO_OFFSET,
359 };
360 int
361 VOP_BWRITE(struct vnode *vp,
362     struct buf *bp)
363 {
364 	int error;
365 	bool mpsafe;
366 	struct vop_bwrite_args a;
367 	struct mount *mp;
368 	a.a_desc = VDESC(vop_bwrite);
369 	a.a_vp = vp;
370 	a.a_bp = bp;
371 	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
372 	if (error)
373 		return error;
374 	error = (VCALL(vp, VOFFSET(vop_bwrite), &a));
375 	vop_post(vp, mp, mpsafe, FST_YES);
376 	return error;
377 }
378 
379 const int vop_parsepath_vp_offsets[] = {
380 	VOPARG_OFFSETOF(struct vop_parsepath_args,a_dvp),
381 	VDESC_NO_OFFSET
382 };
383 const struct vnodeop_desc vop_parsepath_desc = {
384 	VOP_PARSEPATH_DESCOFFSET,
385 	"vop_parsepath",
386 	0,
387 	vop_parsepath_vp_offsets,
388 	VDESC_NO_OFFSET,
389 	VDESC_NO_OFFSET,
390 	VDESC_NO_OFFSET,
391 };
392 int
393 VOP_PARSEPATH(struct vnode *dvp,
394     const char *name,
395     size_t *retval)
396 {
397 	int error;
398 	bool mpsafe;
399 	struct vop_parsepath_args a;
400 	struct mount *mp;
401 	a.a_desc = VDESC(vop_parsepath);
402 	a.a_dvp = dvp;
403 	a.a_name = name;
404 	a.a_retval = retval;
405 	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
406 	if (error)
407 		return error;
408 	error = (VCALL(dvp, VOFFSET(vop_parsepath), &a));
409 	vop_post(dvp, mp, mpsafe, FST_NO);
410 	return error;
411 }
412 
413 const int vop_lookup_vp_offsets[] = {
414 	VOPARG_OFFSETOF(struct vop_lookup_v2_args,a_dvp),
415 	VDESC_NO_OFFSET
416 };
417 const struct vnodeop_desc vop_lookup_desc = {
418 	VOP_LOOKUP_DESCOFFSET,
419 	"vop_lookup",
420 	0,
421 	vop_lookup_vp_offsets,
422 	VOPARG_OFFSETOF(struct vop_lookup_v2_args, a_vpp),
423 	VDESC_NO_OFFSET,
424 	VOPARG_OFFSETOF(struct vop_lookup_v2_args, a_cnp),
425 };
426 int
427 VOP_LOOKUP(struct vnode *dvp,
428     struct vnode **vpp,
429     struct componentname *cnp)
430 {
431 	int error;
432 	bool mpsafe;
433 	struct vop_lookup_v2_args a;
434 	struct mount *mp;
435 	a.a_desc = VDESC(vop_lookup);
436 	a.a_dvp = dvp;
437 	a.a_vpp = vpp;
438 	a.a_cnp = cnp;
439 	assert_vop_locked(dvp, "vop_lookup: dvp");
440 	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
441 	if (error)
442 		return error;
443 	error = (VCALL(dvp, VOFFSET(vop_lookup), &a));
444 	vop_post(dvp, mp, mpsafe, FST_NO);
445 #ifdef DIAGNOSTIC
446 	if (error == 0)
447 		KASSERT((*vpp)->v_size != VSIZENOTSET
448 		    && (*vpp)->v_writesize != VSIZENOTSET);
449 #endif /* DIAGNOSTIC */
450 	return error;
451 }
452 
453 const int vop_create_vp_offsets[] = {
454 	VOPARG_OFFSETOF(struct vop_create_v3_args,a_dvp),
455 	VDESC_NO_OFFSET
456 };
457 const struct vnodeop_desc vop_create_desc = {
458 	VOP_CREATE_DESCOFFSET,
459 	"vop_create",
460 	0,
461 	vop_create_vp_offsets,
462 	VOPARG_OFFSETOF(struct vop_create_v3_args, a_vpp),
463 	VDESC_NO_OFFSET,
464 	VOPARG_OFFSETOF(struct vop_create_v3_args, a_cnp),
465 };
466 int
467 VOP_CREATE(struct vnode *dvp,
468     struct vnode **vpp,
469     struct componentname *cnp,
470     struct vattr *vap)
471 {
472 	int error;
473 	bool mpsafe;
474 	struct vop_create_v3_args a;
475 	struct mount *mp;
476 	a.a_desc = VDESC(vop_create);
477 	a.a_dvp = dvp;
478 	a.a_vpp = vpp;
479 	a.a_cnp = cnp;
480 	a.a_vap = vap;
481 	assert_vop_elocked(dvp, "vop_create: dvp");
482 	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
483 	if (error)
484 		return error;
485 	error = (VCALL(dvp, VOFFSET(vop_create), &a));
486 	vop_post(dvp, mp, mpsafe, FST_NO);
487 	vop_create_post(&a, error);
488 #ifdef DIAGNOSTIC
489 	if (error == 0)
490 		KASSERT((*vpp)->v_size != VSIZENOTSET
491 		    && (*vpp)->v_writesize != VSIZENOTSET);
492 #endif /* DIAGNOSTIC */
493 	return error;
494 }
495 
496 const int vop_mknod_vp_offsets[] = {
497 	VOPARG_OFFSETOF(struct vop_mknod_v3_args,a_dvp),
498 	VDESC_NO_OFFSET
499 };
500 const struct vnodeop_desc vop_mknod_desc = {
501 	VOP_MKNOD_DESCOFFSET,
502 	"vop_mknod",
503 	0,
504 	vop_mknod_vp_offsets,
505 	VOPARG_OFFSETOF(struct vop_mknod_v3_args, a_vpp),
506 	VDESC_NO_OFFSET,
507 	VOPARG_OFFSETOF(struct vop_mknod_v3_args, a_cnp),
508 };
509 int
510 VOP_MKNOD(struct vnode *dvp,
511     struct vnode **vpp,
512     struct componentname *cnp,
513     struct vattr *vap)
514 {
515 	int error;
516 	bool mpsafe;
517 	struct vop_mknod_v3_args a;
518 	struct mount *mp;
519 	a.a_desc = VDESC(vop_mknod);
520 	a.a_dvp = dvp;
521 	a.a_vpp = vpp;
522 	a.a_cnp = cnp;
523 	a.a_vap = vap;
524 	assert_vop_elocked(dvp, "vop_mknod: dvp");
525 	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
526 	if (error)
527 		return error;
528 	error = (VCALL(dvp, VOFFSET(vop_mknod), &a));
529 	vop_post(dvp, mp, mpsafe, FST_NO);
530 	vop_mknod_post(&a, error);
531 #ifdef DIAGNOSTIC
532 	if (error == 0)
533 		KASSERT((*vpp)->v_size != VSIZENOTSET
534 		    && (*vpp)->v_writesize != VSIZENOTSET);
535 #endif /* DIAGNOSTIC */
536 	return error;
537 }
538 
539 const int vop_open_vp_offsets[] = {
540 	VOPARG_OFFSETOF(struct vop_open_args,a_vp),
541 	VDESC_NO_OFFSET
542 };
543 const struct vnodeop_desc vop_open_desc = {
544 	VOP_OPEN_DESCOFFSET,
545 	"vop_open",
546 	0,
547 	vop_open_vp_offsets,
548 	VDESC_NO_OFFSET,
549 	VOPARG_OFFSETOF(struct vop_open_args, a_cred),
550 	VDESC_NO_OFFSET,
551 };
552 int
553 VOP_OPEN(struct vnode *vp,
554     int mode,
555     kauth_cred_t cred)
556 {
557 	int error;
558 	bool mpsafe;
559 	struct vop_open_args a;
560 	struct mount *mp;
561 	a.a_desc = VDESC(vop_open);
562 	a.a_vp = vp;
563 	a.a_mode = mode;
564 	a.a_cred = cred;
565 	assert_vop_locked(vp, "vop_open: vp");
566 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
567 	if (error)
568 		return error;
569 	error = (VCALL(vp, VOFFSET(vop_open), &a));
570 	vop_post(vp, mp, mpsafe, FST_NO);
571 	vop_open_post(&a, error);
572 	return error;
573 }
574 
575 const int vop_close_vp_offsets[] = {
576 	VOPARG_OFFSETOF(struct vop_close_args,a_vp),
577 	VDESC_NO_OFFSET
578 };
579 const struct vnodeop_desc vop_close_desc = {
580 	VOP_CLOSE_DESCOFFSET,
581 	"vop_close",
582 	0,
583 	vop_close_vp_offsets,
584 	VDESC_NO_OFFSET,
585 	VOPARG_OFFSETOF(struct vop_close_args, a_cred),
586 	VDESC_NO_OFFSET,
587 };
588 int
589 VOP_CLOSE(struct vnode *vp,
590     int fflag,
591     kauth_cred_t cred)
592 {
593 	int error;
594 	bool mpsafe;
595 	struct vop_close_args a;
596 	struct mount *mp;
597 	a.a_desc = VDESC(vop_close);
598 	a.a_vp = vp;
599 	a.a_fflag = fflag;
600 	a.a_cred = cred;
601 	assert_vop_locked(vp, "vop_close: vp");
602 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
603 	if (error)
604 		return error;
605 	error = (VCALL(vp, VOFFSET(vop_close), &a));
606 	vop_post(vp, mp, mpsafe, FST_NO);
607 	vop_close_post(&a, error);
608 	return error;
609 }
610 
611 const int vop_access_vp_offsets[] = {
612 	VOPARG_OFFSETOF(struct vop_access_args,a_vp),
613 	VDESC_NO_OFFSET
614 };
615 const struct vnodeop_desc vop_access_desc = {
616 	VOP_ACCESS_DESCOFFSET,
617 	"vop_access",
618 	0,
619 	vop_access_vp_offsets,
620 	VDESC_NO_OFFSET,
621 	VOPARG_OFFSETOF(struct vop_access_args, a_cred),
622 	VDESC_NO_OFFSET,
623 };
624 int
625 VOP_ACCESS(struct vnode *vp,
626     accmode_t accmode,
627     kauth_cred_t cred)
628 {
629 	int error;
630 	bool mpsafe;
631 	struct vop_access_args a;
632 	struct mount *mp;
633 	a.a_desc = VDESC(vop_access);
634 	a.a_vp = vp;
635 	a.a_accmode = accmode;
636 	a.a_cred = cred;
637 	assert_vop_locked(vp, "vop_access: vp");
638 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
639 	if (error)
640 		return error;
641 	error = (VCALL(vp, VOFFSET(vop_access), &a));
642 	vop_post(vp, mp, mpsafe, FST_NO);
643 	return error;
644 }
645 
646 const int vop_accessx_vp_offsets[] = {
647 	VOPARG_OFFSETOF(struct vop_accessx_args,a_vp),
648 	VDESC_NO_OFFSET
649 };
650 const struct vnodeop_desc vop_accessx_desc = {
651 	VOP_ACCESSX_DESCOFFSET,
652 	"vop_accessx",
653 	0,
654 	vop_accessx_vp_offsets,
655 	VDESC_NO_OFFSET,
656 	VOPARG_OFFSETOF(struct vop_accessx_args, a_cred),
657 	VDESC_NO_OFFSET,
658 };
659 int
660 VOP_ACCESSX(struct vnode *vp,
661     accmode_t accmode,
662     kauth_cred_t cred)
663 {
664 	int error;
665 	bool mpsafe;
666 	struct vop_accessx_args a;
667 	struct mount *mp;
668 	a.a_desc = VDESC(vop_accessx);
669 	a.a_vp = vp;
670 	a.a_accmode = accmode;
671 	a.a_cred = cred;
672 	assert_vop_locked(vp, "vop_accessx: vp");
673 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
674 	if (error)
675 		return error;
676 	error = (VCALL(vp, VOFFSET(vop_accessx), &a));
677 	vop_post(vp, mp, mpsafe, FST_NO);
678 	return error;
679 }
680 
681 const int vop_getattr_vp_offsets[] = {
682 	VOPARG_OFFSETOF(struct vop_getattr_args,a_vp),
683 	VDESC_NO_OFFSET
684 };
685 const struct vnodeop_desc vop_getattr_desc = {
686 	VOP_GETATTR_DESCOFFSET,
687 	"vop_getattr",
688 	0,
689 	vop_getattr_vp_offsets,
690 	VDESC_NO_OFFSET,
691 	VOPARG_OFFSETOF(struct vop_getattr_args, a_cred),
692 	VDESC_NO_OFFSET,
693 };
694 int
695 VOP_GETATTR(struct vnode *vp,
696     struct vattr *vap,
697     kauth_cred_t cred)
698 {
699 	int error;
700 	bool mpsafe;
701 	struct vop_getattr_args a;
702 	struct mount *mp;
703 	a.a_desc = VDESC(vop_getattr);
704 	a.a_vp = vp;
705 	a.a_vap = vap;
706 	a.a_cred = cred;
707 	assert_vop_locked(vp, "vop_getattr: vp");
708 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
709 	if (error)
710 		return error;
711 	error = (VCALL(vp, VOFFSET(vop_getattr), &a));
712 	vop_post(vp, mp, mpsafe, FST_NO);
713 	return error;
714 }
715 
716 const int vop_setattr_vp_offsets[] = {
717 	VOPARG_OFFSETOF(struct vop_setattr_args,a_vp),
718 	VDESC_NO_OFFSET
719 };
720 const struct vnodeop_desc vop_setattr_desc = {
721 	VOP_SETATTR_DESCOFFSET,
722 	"vop_setattr",
723 	0,
724 	vop_setattr_vp_offsets,
725 	VDESC_NO_OFFSET,
726 	VOPARG_OFFSETOF(struct vop_setattr_args, a_cred),
727 	VDESC_NO_OFFSET,
728 };
729 int
730 VOP_SETATTR(struct vnode *vp,
731     struct vattr *vap,
732     kauth_cred_t cred)
733 {
734 	int error;
735 	bool mpsafe;
736 	struct vop_setattr_args a;
737 	struct mount *mp;
738 	a.a_desc = VDESC(vop_setattr);
739 	a.a_vp = vp;
740 	a.a_vap = vap;
741 	a.a_cred = cred;
742 	assert_vop_elocked(vp, "vop_setattr: vp");
743 	vop_setattr_pre(&a);
744 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
745 	if (error)
746 		return error;
747 	error = (VCALL(vp, VOFFSET(vop_setattr), &a));
748 	vop_post(vp, mp, mpsafe, FST_NO);
749 	vop_setattr_post(&a, error);
750 	return error;
751 }
752 
753 const int vop_read_vp_offsets[] = {
754 	VOPARG_OFFSETOF(struct vop_read_args,a_vp),
755 	VDESC_NO_OFFSET
756 };
757 const struct vnodeop_desc vop_read_desc = {
758 	VOP_READ_DESCOFFSET,
759 	"vop_read",
760 	0,
761 	vop_read_vp_offsets,
762 	VDESC_NO_OFFSET,
763 	VOPARG_OFFSETOF(struct vop_read_args, a_cred),
764 	VDESC_NO_OFFSET,
765 };
766 int
767 VOP_READ(struct vnode *vp,
768     struct uio *uio,
769     int ioflag,
770     kauth_cred_t cred)
771 {
772 	int error;
773 	bool mpsafe;
774 	struct vop_read_args a;
775 	struct mount *mp;
776 	a.a_desc = VDESC(vop_read);
777 	a.a_vp = vp;
778 	a.a_uio = uio;
779 	a.a_ioflag = ioflag;
780 	a.a_cred = cred;
781 	assert_vop_locked(vp, "vop_read: vp");
782 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
783 	if (error)
784 		return error;
785 	error = (VCALL(vp, VOFFSET(vop_read), &a));
786 	vop_post(vp, mp, mpsafe, FST_NO);
787 	vop_read_post(&a, error);
788 	return error;
789 }
790 
791 const int vop_write_vp_offsets[] = {
792 	VOPARG_OFFSETOF(struct vop_write_args,a_vp),
793 	VDESC_NO_OFFSET
794 };
795 const struct vnodeop_desc vop_write_desc = {
796 	VOP_WRITE_DESCOFFSET,
797 	"vop_write",
798 	0,
799 	vop_write_vp_offsets,
800 	VDESC_NO_OFFSET,
801 	VOPARG_OFFSETOF(struct vop_write_args, a_cred),
802 	VDESC_NO_OFFSET,
803 };
804 int
805 VOP_WRITE(struct vnode *vp,
806     struct uio *uio,
807     int ioflag,
808     kauth_cred_t cred)
809 {
810 	int error;
811 	bool mpsafe;
812 	struct vop_write_args a;
813 	struct mount *mp;
814 	a.a_desc = VDESC(vop_write);
815 	a.a_vp = vp;
816 	a.a_uio = uio;
817 	a.a_ioflag = ioflag;
818 	a.a_cred = cred;
819 	assert_vop_locked(vp, "vop_write: vp");
820 	vop_write_pre(&a);
821 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
822 	if (error)
823 		return error;
824 	error = (VCALL(vp, VOFFSET(vop_write), &a));
825 	vop_post(vp, mp, mpsafe, FST_NO);
826 	vop_write_post(&a, error);
827 	return error;
828 }
829 
830 const int vop_fallocate_vp_offsets[] = {
831 	VOPARG_OFFSETOF(struct vop_fallocate_args,a_vp),
832 	VDESC_NO_OFFSET
833 };
834 const struct vnodeop_desc vop_fallocate_desc = {
835 	VOP_FALLOCATE_DESCOFFSET,
836 	"vop_fallocate",
837 	0,
838 	vop_fallocate_vp_offsets,
839 	VDESC_NO_OFFSET,
840 	VDESC_NO_OFFSET,
841 	VDESC_NO_OFFSET,
842 };
843 int
844 VOP_FALLOCATE(struct vnode *vp,
845     off_t pos,
846     off_t len)
847 {
848 	int error;
849 	bool mpsafe;
850 	struct vop_fallocate_args a;
851 	struct mount *mp;
852 	a.a_desc = VDESC(vop_fallocate);
853 	a.a_vp = vp;
854 	a.a_pos = pos;
855 	a.a_len = len;
856 	assert_vop_locked(vp, "vop_fallocate: vp");
857 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
858 	if (error)
859 		return error;
860 	error = (VCALL(vp, VOFFSET(vop_fallocate), &a));
861 	vop_post(vp, mp, mpsafe, FST_NO);
862 	return error;
863 }
864 
865 const int vop_fdiscard_vp_offsets[] = {
866 	VOPARG_OFFSETOF(struct vop_fdiscard_args,a_vp),
867 	VDESC_NO_OFFSET
868 };
869 const struct vnodeop_desc vop_fdiscard_desc = {
870 	VOP_FDISCARD_DESCOFFSET,
871 	"vop_fdiscard",
872 	0,
873 	vop_fdiscard_vp_offsets,
874 	VDESC_NO_OFFSET,
875 	VDESC_NO_OFFSET,
876 	VDESC_NO_OFFSET,
877 };
878 int
879 VOP_FDISCARD(struct vnode *vp,
880     off_t pos,
881     off_t len)
882 {
883 	int error;
884 	bool mpsafe;
885 	struct vop_fdiscard_args a;
886 	struct mount *mp;
887 	a.a_desc = VDESC(vop_fdiscard);
888 	a.a_vp = vp;
889 	a.a_pos = pos;
890 	a.a_len = len;
891 	assert_vop_locked(vp, "vop_fdiscard: vp");
892 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
893 	if (error)
894 		return error;
895 	error = (VCALL(vp, VOFFSET(vop_fdiscard), &a));
896 	vop_post(vp, mp, mpsafe, FST_NO);
897 	return error;
898 }
899 
900 const int vop_ioctl_vp_offsets[] = {
901 	VOPARG_OFFSETOF(struct vop_ioctl_args,a_vp),
902 	VDESC_NO_OFFSET
903 };
904 const struct vnodeop_desc vop_ioctl_desc = {
905 	VOP_IOCTL_DESCOFFSET,
906 	"vop_ioctl",
907 	0,
908 	vop_ioctl_vp_offsets,
909 	VDESC_NO_OFFSET,
910 	VOPARG_OFFSETOF(struct vop_ioctl_args, a_cred),
911 	VDESC_NO_OFFSET,
912 };
913 int
914 VOP_IOCTL(struct vnode *vp,
915     u_long command,
916     void *data,
917     int fflag,
918     kauth_cred_t cred)
919 {
920 	int error;
921 	bool mpsafe;
922 	struct vop_ioctl_args a;
923 	struct mount *mp;
924 	a.a_desc = VDESC(vop_ioctl);
925 	a.a_vp = vp;
926 	a.a_command = command;
927 	a.a_data = data;
928 	a.a_fflag = fflag;
929 	a.a_cred = cred;
930 	assert_vop_unlocked(vp, "vop_ioctl: vp");
931 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
932 	if (error)
933 		return error;
934 	error = (VCALL(vp, VOFFSET(vop_ioctl), &a));
935 	vop_post(vp, mp, mpsafe, FST_NO);
936 	return error;
937 }
938 
939 const int vop_fcntl_vp_offsets[] = {
940 	VOPARG_OFFSETOF(struct vop_fcntl_args,a_vp),
941 	VDESC_NO_OFFSET
942 };
943 const struct vnodeop_desc vop_fcntl_desc = {
944 	VOP_FCNTL_DESCOFFSET,
945 	"vop_fcntl",
946 	0,
947 	vop_fcntl_vp_offsets,
948 	VDESC_NO_OFFSET,
949 	VOPARG_OFFSETOF(struct vop_fcntl_args, a_cred),
950 	VDESC_NO_OFFSET,
951 };
952 int
953 VOP_FCNTL(struct vnode *vp,
954     u_int command,
955     void *data,
956     int fflag,
957     kauth_cred_t cred)
958 {
959 	int error;
960 	bool mpsafe;
961 	struct vop_fcntl_args a;
962 	struct mount *mp;
963 	a.a_desc = VDESC(vop_fcntl);
964 	a.a_vp = vp;
965 	a.a_command = command;
966 	a.a_data = data;
967 	a.a_fflag = fflag;
968 	a.a_cred = cred;
969 	assert_vop_unlocked(vp, "vop_fcntl: vp");
970 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
971 	if (error)
972 		return error;
973 	error = (VCALL(vp, VOFFSET(vop_fcntl), &a));
974 	vop_post(vp, mp, mpsafe, FST_NO);
975 	return error;
976 }
977 
978 const int vop_poll_vp_offsets[] = {
979 	VOPARG_OFFSETOF(struct vop_poll_args,a_vp),
980 	VDESC_NO_OFFSET
981 };
982 const struct vnodeop_desc vop_poll_desc = {
983 	VOP_POLL_DESCOFFSET,
984 	"vop_poll",
985 	0,
986 	vop_poll_vp_offsets,
987 	VDESC_NO_OFFSET,
988 	VDESC_NO_OFFSET,
989 	VDESC_NO_OFFSET,
990 };
991 int
992 VOP_POLL(struct vnode *vp,
993     int events)
994 {
995 	int error;
996 	bool mpsafe;
997 	struct vop_poll_args a;
998 	struct mount *mp;
999 	a.a_desc = VDESC(vop_poll);
1000 	a.a_vp = vp;
1001 	a.a_events = events;
1002 	assert_vop_unlocked(vp, "vop_poll: vp");
1003 	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
1004 	if (error)
1005 		return error;
1006 	error = (VCALL(vp, VOFFSET(vop_poll), &a));
1007 	vop_post(vp, mp, mpsafe, FST_YES);
1008 	return error;
1009 }
1010 
1011 const int vop_kqfilter_vp_offsets[] = {
1012 	VOPARG_OFFSETOF(struct vop_kqfilter_args,a_vp),
1013 	VDESC_NO_OFFSET
1014 };
1015 const struct vnodeop_desc vop_kqfilter_desc = {
1016 	VOP_KQFILTER_DESCOFFSET,
1017 	"vop_kqfilter",
1018 	0,
1019 	vop_kqfilter_vp_offsets,
1020 	VDESC_NO_OFFSET,
1021 	VDESC_NO_OFFSET,
1022 	VDESC_NO_OFFSET,
1023 };
1024 int
1025 VOP_KQFILTER(struct vnode *vp,
1026     struct knote *kn)
1027 {
1028 	int error;
1029 	bool mpsafe;
1030 	struct vop_kqfilter_args a;
1031 	struct mount *mp;
1032 	a.a_desc = VDESC(vop_kqfilter);
1033 	a.a_vp = vp;
1034 	a.a_kn = kn;
1035 	assert_vop_unlocked(vp, "vop_kqfilter: vp");
1036 	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
1037 	if (error)
1038 		return error;
1039 	error = (VCALL(vp, VOFFSET(vop_kqfilter), &a));
1040 	vop_post(vp, mp, mpsafe, FST_YES);
1041 	return error;
1042 }
1043 
1044 const int vop_revoke_vp_offsets[] = {
1045 	VOPARG_OFFSETOF(struct vop_revoke_args,a_vp),
1046 	VDESC_NO_OFFSET
1047 };
1048 const struct vnodeop_desc vop_revoke_desc = {
1049 	VOP_REVOKE_DESCOFFSET,
1050 	"vop_revoke",
1051 	0,
1052 	vop_revoke_vp_offsets,
1053 	VDESC_NO_OFFSET,
1054 	VDESC_NO_OFFSET,
1055 	VDESC_NO_OFFSET,
1056 };
1057 int
1058 VOP_REVOKE(struct vnode *vp,
1059     int flags)
1060 {
1061 	int error;
1062 	bool mpsafe;
1063 	struct vop_revoke_args a;
1064 	struct mount *mp;
1065 	a.a_desc = VDESC(vop_revoke);
1066 	a.a_vp = vp;
1067 	a.a_flags = flags;
1068 	assert_vop_unlocked(vp, "vop_revoke: vp");
1069 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1070 	if (error)
1071 		return error;
1072 	error = (VCALL(vp, VOFFSET(vop_revoke), &a));
1073 	vop_post(vp, mp, mpsafe, FST_NO);
1074 	return error;
1075 }
1076 
1077 const int vop_mmap_vp_offsets[] = {
1078 	VOPARG_OFFSETOF(struct vop_mmap_args,a_vp),
1079 	VDESC_NO_OFFSET
1080 };
1081 const struct vnodeop_desc vop_mmap_desc = {
1082 	VOP_MMAP_DESCOFFSET,
1083 	"vop_mmap",
1084 	0,
1085 	vop_mmap_vp_offsets,
1086 	VDESC_NO_OFFSET,
1087 	VOPARG_OFFSETOF(struct vop_mmap_args, a_cred),
1088 	VDESC_NO_OFFSET,
1089 };
1090 int
1091 VOP_MMAP(struct vnode *vp,
1092     vm_prot_t prot,
1093     kauth_cred_t cred)
1094 {
1095 	int error;
1096 	bool mpsafe;
1097 	struct vop_mmap_args a;
1098 	struct mount *mp;
1099 	a.a_desc = VDESC(vop_mmap);
1100 	a.a_vp = vp;
1101 	a.a_prot = prot;
1102 	a.a_cred = cred;
1103 	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
1104 	if (error)
1105 		return error;
1106 	error = (VCALL(vp, VOFFSET(vop_mmap), &a));
1107 	vop_post(vp, mp, mpsafe, FST_YES);
1108 	return error;
1109 }
1110 
1111 const int vop_fsync_vp_offsets[] = {
1112 	VOPARG_OFFSETOF(struct vop_fsync_args,a_vp),
1113 	VDESC_NO_OFFSET
1114 };
1115 const struct vnodeop_desc vop_fsync_desc = {
1116 	VOP_FSYNC_DESCOFFSET,
1117 	"vop_fsync",
1118 	0,
1119 	vop_fsync_vp_offsets,
1120 	VDESC_NO_OFFSET,
1121 	VOPARG_OFFSETOF(struct vop_fsync_args, a_cred),
1122 	VDESC_NO_OFFSET,
1123 };
1124 int
1125 VOP_FSYNC(struct vnode *vp,
1126     kauth_cred_t cred,
1127     int flags,
1128     off_t offlo,
1129     off_t offhi)
1130 {
1131 	int error;
1132 	bool mpsafe;
1133 	struct vop_fsync_args a;
1134 	struct mount *mp;
1135 	a.a_desc = VDESC(vop_fsync);
1136 	a.a_vp = vp;
1137 	a.a_cred = cred;
1138 	a.a_flags = flags;
1139 	a.a_offlo = offlo;
1140 	a.a_offhi = offhi;
1141 	assert_vop_locked(vp, "vop_fsync: vp");
1142 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1143 	if (error)
1144 		return error;
1145 	error = (VCALL(vp, VOFFSET(vop_fsync), &a));
1146 	vop_post(vp, mp, mpsafe, FST_NO);
1147 	return error;
1148 }
1149 
1150 const int vop_seek_vp_offsets[] = {
1151 	VOPARG_OFFSETOF(struct vop_seek_args,a_vp),
1152 	VDESC_NO_OFFSET
1153 };
1154 const struct vnodeop_desc vop_seek_desc = {
1155 	VOP_SEEK_DESCOFFSET,
1156 	"vop_seek",
1157 	0,
1158 	vop_seek_vp_offsets,
1159 	VDESC_NO_OFFSET,
1160 	VOPARG_OFFSETOF(struct vop_seek_args, a_cred),
1161 	VDESC_NO_OFFSET,
1162 };
1163 int
1164 VOP_SEEK(struct vnode *vp,
1165     off_t oldoff,
1166     off_t newoff,
1167     kauth_cred_t cred)
1168 {
1169 	int error;
1170 	bool mpsafe;
1171 	struct vop_seek_args a;
1172 	struct mount *mp;
1173 	a.a_desc = VDESC(vop_seek);
1174 	a.a_vp = vp;
1175 	a.a_oldoff = oldoff;
1176 	a.a_newoff = newoff;
1177 	a.a_cred = cred;
1178 	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
1179 	if (error)
1180 		return error;
1181 	error = (VCALL(vp, VOFFSET(vop_seek), &a));
1182 	vop_post(vp, mp, mpsafe, FST_YES);
1183 	return error;
1184 }
1185 
1186 const int vop_remove_vp_offsets[] = {
1187 	VOPARG_OFFSETOF(struct vop_remove_v3_args,a_dvp),
1188 	VOPARG_OFFSETOF(struct vop_remove_v3_args,a_vp),
1189 	VDESC_NO_OFFSET
1190 };
1191 const struct vnodeop_desc vop_remove_desc = {
1192 	VOP_REMOVE_DESCOFFSET,
1193 	"vop_remove",
1194 	0 | VDESC_VP1_WILLPUT,
1195 	vop_remove_vp_offsets,
1196 	VDESC_NO_OFFSET,
1197 	VDESC_NO_OFFSET,
1198 	VOPARG_OFFSETOF(struct vop_remove_v3_args, a_cnp),
1199 };
1200 int
1201 VOP_REMOVE(struct vnode *dvp,
1202     struct vnode *vp,
1203     struct componentname *cnp)
1204 {
1205 	int error;
1206 	bool mpsafe;
1207 	struct vop_remove_v3_args a;
1208 	struct mount *mp;
1209 	a.a_desc = VDESC(vop_remove);
1210 	a.a_dvp = dvp;
1211 	a.a_vp = vp;
1212 	a.a_cnp = cnp;
1213 	assert_vop_elocked(dvp, "vop_remove: dvp");
1214 	assert_vop_locked(vp, "vop_remove: vp");
1215 	vop_remove_pre(&a);
1216 	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
1217 	if (error)
1218 		return error;
1219 	error = (VCALL(dvp, VOFFSET(vop_remove), &a));
1220 	vop_post(dvp, mp, mpsafe, FST_NO);
1221 	vop_remove_post(&a, error);
1222 	return error;
1223 }
1224 
1225 const int vop_link_vp_offsets[] = {
1226 	VOPARG_OFFSETOF(struct vop_link_v2_args,a_dvp),
1227 	VOPARG_OFFSETOF(struct vop_link_v2_args,a_vp),
1228 	VDESC_NO_OFFSET
1229 };
1230 const struct vnodeop_desc vop_link_desc = {
1231 	VOP_LINK_DESCOFFSET,
1232 	"vop_link",
1233 	0,
1234 	vop_link_vp_offsets,
1235 	VDESC_NO_OFFSET,
1236 	VDESC_NO_OFFSET,
1237 	VOPARG_OFFSETOF(struct vop_link_v2_args, a_cnp),
1238 };
1239 int
1240 VOP_LINK(struct vnode *dvp,
1241     struct vnode *vp,
1242     struct componentname *cnp)
1243 {
1244 	int error;
1245 	bool mpsafe;
1246 	struct vop_link_v2_args a;
1247 	struct mount *mp;
1248 	a.a_desc = VDESC(vop_link);
1249 	a.a_dvp = dvp;
1250 	a.a_vp = vp;
1251 	a.a_cnp = cnp;
1252 	assert_vop_elocked(dvp, "vop_link: dvp");
1253 	assert_vop_unlocked(vp, "vop_link: vp");
1254 	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
1255 	if (error)
1256 		return error;
1257 	error = (VCALL(dvp, VOFFSET(vop_link), &a));
1258 	vop_post(dvp, mp, mpsafe, FST_NO);
1259 	vop_link_post(&a, error);
1260 	return error;
1261 }
1262 
1263 const int vop_rename_vp_offsets[] = {
1264 	VOPARG_OFFSETOF(struct vop_rename_args,a_fdvp),
1265 	VOPARG_OFFSETOF(struct vop_rename_args,a_fvp),
1266 	VOPARG_OFFSETOF(struct vop_rename_args,a_tdvp),
1267 	VOPARG_OFFSETOF(struct vop_rename_args,a_tvp),
1268 	VDESC_NO_OFFSET
1269 };
1270 const struct vnodeop_desc vop_rename_desc = {
1271 	VOP_RENAME_DESCOFFSET,
1272 	"vop_rename",
1273 	0 | VDESC_VP0_WILLRELE | VDESC_VP1_WILLRELE | VDESC_VP2_WILLPUT | VDESC_VP3_WILLPUT,
1274 	vop_rename_vp_offsets,
1275 	VDESC_NO_OFFSET,
1276 	VDESC_NO_OFFSET,
1277 	VOPARG_OFFSETOF(struct vop_rename_args, a_fcnp),
1278 };
1279 int
1280 VOP_RENAME(struct vnode *fdvp,
1281     struct vnode *fvp,
1282     struct componentname *fcnp,
1283     struct vnode *tdvp,
1284     struct vnode *tvp,
1285     struct componentname *tcnp)
1286 {
1287 	int error;
1288 	bool mpsafe;
1289 	struct vop_rename_args a;
1290 	struct mount *mp;
1291 	a.a_desc = VDESC(vop_rename);
1292 	a.a_fdvp = fdvp;
1293 	a.a_fvp = fvp;
1294 	a.a_fcnp = fcnp;
1295 	a.a_tdvp = tdvp;
1296 	a.a_tvp = tvp;
1297 	a.a_tcnp = tcnp;
1298 	assert_vop_locked(tdvp, "vop_rename: tdvp");
1299 	error = vop_pre(fdvp, &mp, &mpsafe, FST_YES);
1300 	if (error)
1301 		return error;
1302 	error = (VCALL(fdvp, VOFFSET(vop_rename), &a));
1303 	vop_post(fdvp, mp, mpsafe, FST_YES);
1304 	return error;
1305 }
1306 
1307 const int vop_mkdir_vp_offsets[] = {
1308 	VOPARG_OFFSETOF(struct vop_mkdir_v3_args,a_dvp),
1309 	VDESC_NO_OFFSET
1310 };
1311 const struct vnodeop_desc vop_mkdir_desc = {
1312 	VOP_MKDIR_DESCOFFSET,
1313 	"vop_mkdir",
1314 	0,
1315 	vop_mkdir_vp_offsets,
1316 	VOPARG_OFFSETOF(struct vop_mkdir_v3_args, a_vpp),
1317 	VDESC_NO_OFFSET,
1318 	VOPARG_OFFSETOF(struct vop_mkdir_v3_args, a_cnp),
1319 };
1320 int
1321 VOP_MKDIR(struct vnode *dvp,
1322     struct vnode **vpp,
1323     struct componentname *cnp,
1324     struct vattr *vap)
1325 {
1326 	int error;
1327 	bool mpsafe;
1328 	struct vop_mkdir_v3_args a;
1329 	struct mount *mp;
1330 	a.a_desc = VDESC(vop_mkdir);
1331 	a.a_dvp = dvp;
1332 	a.a_vpp = vpp;
1333 	a.a_cnp = cnp;
1334 	a.a_vap = vap;
1335 	assert_vop_elocked(dvp, "vop_mkdir: dvp");
1336 	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
1337 	if (error)
1338 		return error;
1339 	error = (VCALL(dvp, VOFFSET(vop_mkdir), &a));
1340 	vop_post(dvp, mp, mpsafe, FST_NO);
1341 	vop_mkdir_post(&a, error);
1342 #ifdef DIAGNOSTIC
1343 	if (error == 0)
1344 		KASSERT((*vpp)->v_size != VSIZENOTSET
1345 		    && (*vpp)->v_writesize != VSIZENOTSET);
1346 #endif /* DIAGNOSTIC */
1347 	return error;
1348 }
1349 
1350 const int vop_rmdir_vp_offsets[] = {
1351 	VOPARG_OFFSETOF(struct vop_rmdir_v2_args,a_dvp),
1352 	VOPARG_OFFSETOF(struct vop_rmdir_v2_args,a_vp),
1353 	VDESC_NO_OFFSET
1354 };
1355 const struct vnodeop_desc vop_rmdir_desc = {
1356 	VOP_RMDIR_DESCOFFSET,
1357 	"vop_rmdir",
1358 	0 | VDESC_VP1_WILLPUT,
1359 	vop_rmdir_vp_offsets,
1360 	VDESC_NO_OFFSET,
1361 	VDESC_NO_OFFSET,
1362 	VOPARG_OFFSETOF(struct vop_rmdir_v2_args, a_cnp),
1363 };
1364 int
1365 VOP_RMDIR(struct vnode *dvp,
1366     struct vnode *vp,
1367     struct componentname *cnp)
1368 {
1369 	int error;
1370 	bool mpsafe;
1371 	struct vop_rmdir_v2_args a;
1372 	struct mount *mp;
1373 	a.a_desc = VDESC(vop_rmdir);
1374 	a.a_dvp = dvp;
1375 	a.a_vp = vp;
1376 	a.a_cnp = cnp;
1377 	assert_vop_elocked(dvp, "vop_rmdir: dvp");
1378 	assert_vop_elocked(vp, "vop_rmdir: vp");
1379 	vop_rmdir_pre(&a);
1380 	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
1381 	if (error)
1382 		return error;
1383 	error = (VCALL(dvp, VOFFSET(vop_rmdir), &a));
1384 	vop_post(dvp, mp, mpsafe, FST_NO);
1385 	vop_rmdir_post(&a, error);
1386 	return error;
1387 }
1388 
1389 const int vop_symlink_vp_offsets[] = {
1390 	VOPARG_OFFSETOF(struct vop_symlink_v3_args,a_dvp),
1391 	VDESC_NO_OFFSET
1392 };
1393 const struct vnodeop_desc vop_symlink_desc = {
1394 	VOP_SYMLINK_DESCOFFSET,
1395 	"vop_symlink",
1396 	0,
1397 	vop_symlink_vp_offsets,
1398 	VOPARG_OFFSETOF(struct vop_symlink_v3_args, a_vpp),
1399 	VDESC_NO_OFFSET,
1400 	VOPARG_OFFSETOF(struct vop_symlink_v3_args, a_cnp),
1401 };
1402 int
1403 VOP_SYMLINK(struct vnode *dvp,
1404     struct vnode **vpp,
1405     struct componentname *cnp,
1406     struct vattr *vap,
1407     char *target)
1408 {
1409 	int error;
1410 	bool mpsafe;
1411 	struct vop_symlink_v3_args a;
1412 	struct mount *mp;
1413 	a.a_desc = VDESC(vop_symlink);
1414 	a.a_dvp = dvp;
1415 	a.a_vpp = vpp;
1416 	a.a_cnp = cnp;
1417 	a.a_vap = vap;
1418 	a.a_target = target;
1419 	assert_vop_elocked(dvp, "vop_symlink: dvp");
1420 	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
1421 	if (error)
1422 		return error;
1423 	error = (VCALL(dvp, VOFFSET(vop_symlink), &a));
1424 	vop_post(dvp, mp, mpsafe, FST_NO);
1425 	vop_symlink_post(&a, error);
1426 #ifdef DIAGNOSTIC
1427 	if (error == 0)
1428 		KASSERT((*vpp)->v_size != VSIZENOTSET
1429 		    && (*vpp)->v_writesize != VSIZENOTSET);
1430 #endif /* DIAGNOSTIC */
1431 	return error;
1432 }
1433 
1434 const int vop_readdir_vp_offsets[] = {
1435 	VOPARG_OFFSETOF(struct vop_readdir_args,a_vp),
1436 	VDESC_NO_OFFSET
1437 };
1438 const struct vnodeop_desc vop_readdir_desc = {
1439 	VOP_READDIR_DESCOFFSET,
1440 	"vop_readdir",
1441 	0,
1442 	vop_readdir_vp_offsets,
1443 	VDESC_NO_OFFSET,
1444 	VOPARG_OFFSETOF(struct vop_readdir_args, a_cred),
1445 	VDESC_NO_OFFSET,
1446 };
1447 int
1448 VOP_READDIR(struct vnode *vp,
1449     struct uio *uio,
1450     kauth_cred_t cred,
1451     int *eofflag,
1452     off_t **cookies,
1453     int *ncookies)
1454 {
1455 	int error;
1456 	bool mpsafe;
1457 	struct vop_readdir_args a;
1458 	struct mount *mp;
1459 	a.a_desc = VDESC(vop_readdir);
1460 	a.a_vp = vp;
1461 	a.a_uio = uio;
1462 	a.a_cred = cred;
1463 	a.a_eofflag = eofflag;
1464 	a.a_cookies = cookies;
1465 	a.a_ncookies = ncookies;
1466 	assert_vop_locked(vp, "vop_readdir: vp");
1467 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1468 	if (error)
1469 		return error;
1470 	error = (VCALL(vp, VOFFSET(vop_readdir), &a));
1471 	vop_post(vp, mp, mpsafe, FST_NO);
1472 	return error;
1473 }
1474 
1475 const int vop_readlink_vp_offsets[] = {
1476 	VOPARG_OFFSETOF(struct vop_readlink_args,a_vp),
1477 	VDESC_NO_OFFSET
1478 };
1479 const struct vnodeop_desc vop_readlink_desc = {
1480 	VOP_READLINK_DESCOFFSET,
1481 	"vop_readlink",
1482 	0,
1483 	vop_readlink_vp_offsets,
1484 	VDESC_NO_OFFSET,
1485 	VOPARG_OFFSETOF(struct vop_readlink_args, a_cred),
1486 	VDESC_NO_OFFSET,
1487 };
1488 int
1489 VOP_READLINK(struct vnode *vp,
1490     struct uio *uio,
1491     kauth_cred_t cred)
1492 {
1493 	int error;
1494 	bool mpsafe;
1495 	struct vop_readlink_args a;
1496 	struct mount *mp;
1497 	a.a_desc = VDESC(vop_readlink);
1498 	a.a_vp = vp;
1499 	a.a_uio = uio;
1500 	a.a_cred = cred;
1501 	assert_vop_locked(vp, "vop_readlink: vp");
1502 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1503 	if (error)
1504 		return error;
1505 	error = (VCALL(vp, VOFFSET(vop_readlink), &a));
1506 	vop_post(vp, mp, mpsafe, FST_NO);
1507 	return error;
1508 }
1509 
1510 const int vop_abortop_vp_offsets[] = {
1511 	VOPARG_OFFSETOF(struct vop_abortop_args,a_dvp),
1512 	VDESC_NO_OFFSET
1513 };
1514 const struct vnodeop_desc vop_abortop_desc = {
1515 	VOP_ABORTOP_DESCOFFSET,
1516 	"vop_abortop",
1517 	0,
1518 	vop_abortop_vp_offsets,
1519 	VDESC_NO_OFFSET,
1520 	VDESC_NO_OFFSET,
1521 	VOPARG_OFFSETOF(struct vop_abortop_args, a_cnp),
1522 };
1523 int
1524 VOP_ABORTOP(struct vnode *dvp,
1525     struct componentname *cnp)
1526 {
1527 	int error;
1528 	bool mpsafe;
1529 	struct vop_abortop_args a;
1530 	struct mount *mp;
1531 	a.a_desc = VDESC(vop_abortop);
1532 	a.a_dvp = dvp;
1533 	a.a_cnp = cnp;
1534 	error = vop_pre(dvp, &mp, &mpsafe, FST_YES);
1535 	if (error)
1536 		return error;
1537 	error = (VCALL(dvp, VOFFSET(vop_abortop), &a));
1538 	vop_post(dvp, mp, mpsafe, FST_YES);
1539 	return error;
1540 }
1541 
1542 const int vop_inactive_vp_offsets[] = {
1543 	VOPARG_OFFSETOF(struct vop_inactive_v2_args,a_vp),
1544 	VDESC_NO_OFFSET
1545 };
1546 const struct vnodeop_desc vop_inactive_desc = {
1547 	VOP_INACTIVE_DESCOFFSET,
1548 	"vop_inactive",
1549 	0,
1550 	vop_inactive_vp_offsets,
1551 	VDESC_NO_OFFSET,
1552 	VDESC_NO_OFFSET,
1553 	VDESC_NO_OFFSET,
1554 };
1555 int
1556 VOP_INACTIVE(struct vnode *vp,
1557     bool *recycle)
1558 {
1559 	int error;
1560 	bool mpsafe;
1561 	struct vop_inactive_v2_args a;
1562 	struct mount *mp;
1563 	a.a_desc = VDESC(vop_inactive);
1564 	a.a_vp = vp;
1565 	a.a_recycle = recycle;
1566 	assert_vop_elocked(vp, "vop_inactive: vp");
1567 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1568 	if (error)
1569 		return error;
1570 	error = (VCALL(vp, VOFFSET(vop_inactive), &a));
1571 	vop_post(vp, mp, mpsafe, FST_NO);
1572 	return error;
1573 }
1574 
1575 const int vop_reclaim_vp_offsets[] = {
1576 	VOPARG_OFFSETOF(struct vop_reclaim_v2_args,a_vp),
1577 	VDESC_NO_OFFSET
1578 };
1579 const struct vnodeop_desc vop_reclaim_desc = {
1580 	VOP_RECLAIM_DESCOFFSET,
1581 	"vop_reclaim",
1582 	0,
1583 	vop_reclaim_vp_offsets,
1584 	VDESC_NO_OFFSET,
1585 	VDESC_NO_OFFSET,
1586 	VDESC_NO_OFFSET,
1587 };
1588 int
1589 VOP_RECLAIM(struct vnode *vp)
1590 {
1591 	int error;
1592 	bool mpsafe;
1593 	struct vop_reclaim_v2_args a;
1594 	struct mount *mp;
1595 	a.a_desc = VDESC(vop_reclaim);
1596 	a.a_vp = vp;
1597 	assert_vop_elocked(vp, "vop_reclaim: vp");
1598 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1599 	if (error)
1600 		return error;
1601 	error = (VCALL(vp, VOFFSET(vop_reclaim), &a));
1602 	vop_post(vp, mp, mpsafe, FST_NO);
1603 	return error;
1604 }
1605 
1606 const int vop_lock_vp_offsets[] = {
1607 	VOPARG_OFFSETOF(struct vop_lock_args,a_vp),
1608 	VDESC_NO_OFFSET
1609 };
1610 const struct vnodeop_desc vop_lock_desc = {
1611 	VOP_LOCK_DESCOFFSET,
1612 	"vop_lock",
1613 	0,
1614 	vop_lock_vp_offsets,
1615 	VDESC_NO_OFFSET,
1616 	VDESC_NO_OFFSET,
1617 	VDESC_NO_OFFSET,
1618 };
1619 int
1620 VOP_LOCK(struct vnode *vp,
1621     int flags)
1622 {
1623 	int error;
1624 	bool mpsafe;
1625 	struct vop_lock_args a;
1626 	struct mount *mp;
1627 	a.a_desc = VDESC(vop_lock);
1628 	a.a_vp = vp;
1629 	a.a_flags = flags;
1630 	error = vop_pre(vp, &mp, &mpsafe, (!(flags & (LK_SHARED|LK_EXCLUSIVE)) ? FST_NO : (flags & LK_NOWAIT ? FST_TRY : FST_YES)));
1631 	if (error)
1632 		return error;
1633 	error = (VCALL(vp, VOFFSET(vop_lock), &a));
1634 	vop_post(vp, mp, mpsafe, (flags & (LK_UPGRADE|LK_DOWNGRADE) ? FST_NO : (error ? FST_YES : FST_NO)));
1635 	return error;
1636 }
1637 
1638 const int vop_unlock_vp_offsets[] = {
1639 	VOPARG_OFFSETOF(struct vop_unlock_args,a_vp),
1640 	VDESC_NO_OFFSET
1641 };
1642 const struct vnodeop_desc vop_unlock_desc = {
1643 	VOP_UNLOCK_DESCOFFSET,
1644 	"vop_unlock",
1645 	0,
1646 	vop_unlock_vp_offsets,
1647 	VDESC_NO_OFFSET,
1648 	VDESC_NO_OFFSET,
1649 	VDESC_NO_OFFSET,
1650 };
1651 int
1652 VOP_UNLOCK(struct vnode *vp)
1653 {
1654 	int error;
1655 	bool mpsafe;
1656 	struct vop_unlock_args a;
1657 	struct mount *mp;
1658 	a.a_desc = VDESC(vop_unlock);
1659 	a.a_vp = vp;
1660 	assert_vop_locked(vp, "vop_unlock: vp");
1661 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1662 	if (error)
1663 		return error;
1664 	error = (VCALL(vp, VOFFSET(vop_unlock), &a));
1665 	vop_post(vp, mp, mpsafe, FST_YES);
1666 	return error;
1667 }
1668 
1669 const int vop_bmap_vp_offsets[] = {
1670 	VOPARG_OFFSETOF(struct vop_bmap_args,a_vp),
1671 	VDESC_NO_OFFSET
1672 };
1673 const struct vnodeop_desc vop_bmap_desc = {
1674 	VOP_BMAP_DESCOFFSET,
1675 	"vop_bmap",
1676 	0,
1677 	vop_bmap_vp_offsets,
1678 	VOPARG_OFFSETOF(struct vop_bmap_args, a_vpp),
1679 	VDESC_NO_OFFSET,
1680 	VDESC_NO_OFFSET,
1681 };
1682 int
1683 VOP_BMAP(struct vnode *vp,
1684     daddr_t bn,
1685     struct vnode **vpp,
1686     daddr_t *bnp,
1687     int *runp)
1688 {
1689 	int error;
1690 	bool mpsafe;
1691 	struct vop_bmap_args a;
1692 	struct mount *mp;
1693 	a.a_desc = VDESC(vop_bmap);
1694 	a.a_vp = vp;
1695 	a.a_bn = bn;
1696 	a.a_vpp = vpp;
1697 	a.a_bnp = bnp;
1698 	a.a_runp = runp;
1699 	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
1700 	if (error)
1701 		return error;
1702 	error = (VCALL(vp, VOFFSET(vop_bmap), &a));
1703 	vop_post(vp, mp, mpsafe, FST_YES);
1704 	return error;
1705 }
1706 
1707 const int vop_strategy_vp_offsets[] = {
1708 	VOPARG_OFFSETOF(struct vop_strategy_args,a_vp),
1709 	VDESC_NO_OFFSET
1710 };
1711 const struct vnodeop_desc vop_strategy_desc = {
1712 	VOP_STRATEGY_DESCOFFSET,
1713 	"vop_strategy",
1714 	0,
1715 	vop_strategy_vp_offsets,
1716 	VDESC_NO_OFFSET,
1717 	VDESC_NO_OFFSET,
1718 	VDESC_NO_OFFSET,
1719 };
1720 int
1721 VOP_STRATEGY(struct vnode *vp,
1722     struct buf *bp)
1723 {
1724 	int error;
1725 	bool mpsafe;
1726 	struct vop_strategy_args a;
1727 	struct mount *mp;
1728 	a.a_desc = VDESC(vop_strategy);
1729 	a.a_vp = vp;
1730 	a.a_bp = bp;
1731 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1732 	if (error)
1733 		return error;
1734 	error = (VCALL(vp, VOFFSET(vop_strategy), &a));
1735 	vop_post(vp, mp, mpsafe, FST_NO);
1736 	return error;
1737 }
1738 
1739 const int vop_print_vp_offsets[] = {
1740 	VOPARG_OFFSETOF(struct vop_print_args,a_vp),
1741 	VDESC_NO_OFFSET
1742 };
1743 const struct vnodeop_desc vop_print_desc = {
1744 	VOP_PRINT_DESCOFFSET,
1745 	"vop_print",
1746 	0,
1747 	vop_print_vp_offsets,
1748 	VDESC_NO_OFFSET,
1749 	VDESC_NO_OFFSET,
1750 	VDESC_NO_OFFSET,
1751 };
1752 int
1753 VOP_PRINT(struct vnode *vp)
1754 {
1755 	int error;
1756 	bool mpsafe;
1757 	struct vop_print_args a;
1758 	struct mount *mp;
1759 	a.a_desc = VDESC(vop_print);
1760 	a.a_vp = vp;
1761 	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
1762 	if (error)
1763 		return error;
1764 	error = (VCALL(vp, VOFFSET(vop_print), &a));
1765 	vop_post(vp, mp, mpsafe, FST_YES);
1766 	return error;
1767 }
1768 
1769 const int vop_islocked_vp_offsets[] = {
1770 	VOPARG_OFFSETOF(struct vop_islocked_args,a_vp),
1771 	VDESC_NO_OFFSET
1772 };
1773 const struct vnodeop_desc vop_islocked_desc = {
1774 	VOP_ISLOCKED_DESCOFFSET,
1775 	"vop_islocked",
1776 	0,
1777 	vop_islocked_vp_offsets,
1778 	VDESC_NO_OFFSET,
1779 	VDESC_NO_OFFSET,
1780 	VDESC_NO_OFFSET,
1781 };
1782 int
1783 VOP_ISLOCKED(struct vnode *vp)
1784 {
1785 	int error;
1786 	bool mpsafe;
1787 	struct vop_islocked_args a;
1788 	struct mount *mp;
1789 	a.a_desc = VDESC(vop_islocked);
1790 	a.a_vp = vp;
1791 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1792 	if (error)
1793 		return error;
1794 	error = (VCALL(vp, VOFFSET(vop_islocked), &a));
1795 	vop_post(vp, mp, mpsafe, FST_NO);
1796 	return error;
1797 }
1798 
1799 const int vop_pathconf_vp_offsets[] = {
1800 	VOPARG_OFFSETOF(struct vop_pathconf_args,a_vp),
1801 	VDESC_NO_OFFSET
1802 };
1803 const struct vnodeop_desc vop_pathconf_desc = {
1804 	VOP_PATHCONF_DESCOFFSET,
1805 	"vop_pathconf",
1806 	0,
1807 	vop_pathconf_vp_offsets,
1808 	VDESC_NO_OFFSET,
1809 	VDESC_NO_OFFSET,
1810 	VDESC_NO_OFFSET,
1811 };
1812 int
1813 VOP_PATHCONF(struct vnode *vp,
1814     int name,
1815     register_t *retval)
1816 {
1817 	int error;
1818 	bool mpsafe;
1819 	struct vop_pathconf_args a;
1820 	struct mount *mp;
1821 	a.a_desc = VDESC(vop_pathconf);
1822 	a.a_vp = vp;
1823 	a.a_name = name;
1824 	a.a_retval = retval;
1825 	assert_vop_locked(vp, "vop_pathconf: vp");
1826 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1827 	if (error)
1828 		return error;
1829 	error = (VCALL(vp, VOFFSET(vop_pathconf), &a));
1830 	vop_post(vp, mp, mpsafe, FST_NO);
1831 	return error;
1832 }
1833 
1834 const int vop_advlock_vp_offsets[] = {
1835 	VOPARG_OFFSETOF(struct vop_advlock_args,a_vp),
1836 	VDESC_NO_OFFSET
1837 };
1838 const struct vnodeop_desc vop_advlock_desc = {
1839 	VOP_ADVLOCK_DESCOFFSET,
1840 	"vop_advlock",
1841 	0,
1842 	vop_advlock_vp_offsets,
1843 	VDESC_NO_OFFSET,
1844 	VDESC_NO_OFFSET,
1845 	VDESC_NO_OFFSET,
1846 };
1847 int
1848 VOP_ADVLOCK(struct vnode *vp,
1849     void *id,
1850     int op,
1851     struct flock *fl,
1852     int flags)
1853 {
1854 	int error;
1855 	bool mpsafe;
1856 	struct vop_advlock_args a;
1857 	struct mount *mp;
1858 	a.a_desc = VDESC(vop_advlock);
1859 	a.a_vp = vp;
1860 	a.a_id = id;
1861 	a.a_op = op;
1862 	a.a_fl = fl;
1863 	a.a_flags = flags;
1864 	assert_vop_unlocked(vp, "vop_advlock: vp");
1865 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1866 	if (error)
1867 		return error;
1868 	error = (VCALL(vp, VOFFSET(vop_advlock), &a));
1869 	vop_post(vp, mp, mpsafe, FST_NO);
1870 	return error;
1871 }
1872 
1873 const int vop_whiteout_vp_offsets[] = {
1874 	VOPARG_OFFSETOF(struct vop_whiteout_args,a_dvp),
1875 	VDESC_NO_OFFSET
1876 };
1877 const struct vnodeop_desc vop_whiteout_desc = {
1878 	VOP_WHITEOUT_DESCOFFSET,
1879 	"vop_whiteout",
1880 	0,
1881 	vop_whiteout_vp_offsets,
1882 	VDESC_NO_OFFSET,
1883 	VDESC_NO_OFFSET,
1884 	VOPARG_OFFSETOF(struct vop_whiteout_args, a_cnp),
1885 };
1886 int
1887 VOP_WHITEOUT(struct vnode *dvp,
1888     struct componentname *cnp,
1889     int flags)
1890 {
1891 	int error;
1892 	bool mpsafe;
1893 	struct vop_whiteout_args a;
1894 	struct mount *mp;
1895 	a.a_desc = VDESC(vop_whiteout);
1896 	a.a_dvp = dvp;
1897 	a.a_cnp = cnp;
1898 	a.a_flags = flags;
1899 	assert_vop_elocked(dvp, "vop_whiteout: dvp");
1900 	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
1901 	if (error)
1902 		return error;
1903 	error = (VCALL(dvp, VOFFSET(vop_whiteout), &a));
1904 	vop_post(dvp, mp, mpsafe, FST_NO);
1905 	return error;
1906 }
1907 
1908 const int vop_getpages_vp_offsets[] = {
1909 	VOPARG_OFFSETOF(struct vop_getpages_args,a_vp),
1910 	VDESC_NO_OFFSET
1911 };
1912 const struct vnodeop_desc vop_getpages_desc = {
1913 	VOP_GETPAGES_DESCOFFSET,
1914 	"vop_getpages",
1915 	0,
1916 	vop_getpages_vp_offsets,
1917 	VDESC_NO_OFFSET,
1918 	VDESC_NO_OFFSET,
1919 	VDESC_NO_OFFSET,
1920 };
1921 int
1922 VOP_GETPAGES(struct vnode *vp,
1923     voff_t offset,
1924     struct vm_page **m,
1925     int *count,
1926     int centeridx,
1927     vm_prot_t access_type,
1928     int advice,
1929     int flags)
1930 {
1931 	int error;
1932 	bool mpsafe;
1933 	struct vop_getpages_args a;
1934 	struct mount *mp;
1935 	a.a_desc = VDESC(vop_getpages);
1936 	a.a_vp = vp;
1937 	a.a_offset = offset;
1938 	a.a_m = m;
1939 	a.a_count = count;
1940 	a.a_centeridx = centeridx;
1941 	a.a_access_type = access_type;
1942 	a.a_advice = advice;
1943 	a.a_flags = flags;
1944 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1945 	if (error)
1946 		return error;
1947 	error = (VCALL(vp, VOFFSET(vop_getpages), &a));
1948 	vop_post(vp, mp, mpsafe, FST_NO);
1949 	return error;
1950 }
1951 
1952 const int vop_putpages_vp_offsets[] = {
1953 	VOPARG_OFFSETOF(struct vop_putpages_args,a_vp),
1954 	VDESC_NO_OFFSET
1955 };
1956 const struct vnodeop_desc vop_putpages_desc = {
1957 	VOP_PUTPAGES_DESCOFFSET,
1958 	"vop_putpages",
1959 	0,
1960 	vop_putpages_vp_offsets,
1961 	VDESC_NO_OFFSET,
1962 	VDESC_NO_OFFSET,
1963 	VDESC_NO_OFFSET,
1964 };
1965 int
1966 VOP_PUTPAGES(struct vnode *vp,
1967     voff_t offlo,
1968     voff_t offhi,
1969     int flags)
1970 {
1971 	int error;
1972 	bool mpsafe;
1973 	struct vop_putpages_args a;
1974 	struct mount *mp;
1975 	a.a_desc = VDESC(vop_putpages);
1976 	a.a_vp = vp;
1977 	a.a_offlo = offlo;
1978 	a.a_offhi = offhi;
1979 	a.a_flags = flags;
1980 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
1981 	if (error)
1982 		return error;
1983 	error = (VCALL(vp, VOFFSET(vop_putpages), &a));
1984 	vop_post(vp, mp, mpsafe, FST_NO);
1985 	return error;
1986 }
1987 
1988 const int vop_getacl_vp_offsets[] = {
1989 	VOPARG_OFFSETOF(struct vop_getacl_args,a_vp),
1990 	VDESC_NO_OFFSET
1991 };
1992 const struct vnodeop_desc vop_getacl_desc = {
1993 	VOP_GETACL_DESCOFFSET,
1994 	"vop_getacl",
1995 	0,
1996 	vop_getacl_vp_offsets,
1997 	VDESC_NO_OFFSET,
1998 	VOPARG_OFFSETOF(struct vop_getacl_args, a_cred),
1999 	VDESC_NO_OFFSET,
2000 };
2001 int
2002 VOP_GETACL(struct vnode *vp,
2003     acl_type_t type,
2004     struct acl *aclp,
2005     kauth_cred_t cred)
2006 {
2007 	int error;
2008 	bool mpsafe;
2009 	struct vop_getacl_args a;
2010 	struct mount *mp;
2011 	a.a_desc = VDESC(vop_getacl);
2012 	a.a_vp = vp;
2013 	a.a_type = type;
2014 	a.a_aclp = aclp;
2015 	a.a_cred = cred;
2016 	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
2017 	if (error)
2018 		return error;
2019 	error = (VCALL(vp, VOFFSET(vop_getacl), &a));
2020 	vop_post(vp, mp, mpsafe, FST_YES);
2021 	return error;
2022 }
2023 
2024 const int vop_setacl_vp_offsets[] = {
2025 	VOPARG_OFFSETOF(struct vop_setacl_args,a_vp),
2026 	VDESC_NO_OFFSET
2027 };
2028 const struct vnodeop_desc vop_setacl_desc = {
2029 	VOP_SETACL_DESCOFFSET,
2030 	"vop_setacl",
2031 	0,
2032 	vop_setacl_vp_offsets,
2033 	VDESC_NO_OFFSET,
2034 	VOPARG_OFFSETOF(struct vop_setacl_args, a_cred),
2035 	VDESC_NO_OFFSET,
2036 };
2037 int
2038 VOP_SETACL(struct vnode *vp,
2039     acl_type_t type,
2040     struct acl *aclp,
2041     kauth_cred_t cred)
2042 {
2043 	int error;
2044 	bool mpsafe;
2045 	struct vop_setacl_args a;
2046 	struct mount *mp;
2047 	a.a_desc = VDESC(vop_setacl);
2048 	a.a_vp = vp;
2049 	a.a_type = type;
2050 	a.a_aclp = aclp;
2051 	a.a_cred = cred;
2052 	assert_vop_elocked(vp, "vop_setacl: vp");
2053 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
2054 	if (error)
2055 		return error;
2056 	error = (VCALL(vp, VOFFSET(vop_setacl), &a));
2057 	vop_post(vp, mp, mpsafe, FST_NO);
2058 	vop_setacl_post(&a, error);
2059 	return error;
2060 }
2061 
2062 const int vop_aclcheck_vp_offsets[] = {
2063 	VOPARG_OFFSETOF(struct vop_aclcheck_args,a_vp),
2064 	VDESC_NO_OFFSET
2065 };
2066 const struct vnodeop_desc vop_aclcheck_desc = {
2067 	VOP_ACLCHECK_DESCOFFSET,
2068 	"vop_aclcheck",
2069 	0,
2070 	vop_aclcheck_vp_offsets,
2071 	VDESC_NO_OFFSET,
2072 	VOPARG_OFFSETOF(struct vop_aclcheck_args, a_cred),
2073 	VDESC_NO_OFFSET,
2074 };
2075 int
2076 VOP_ACLCHECK(struct vnode *vp,
2077     acl_type_t type,
2078     struct acl *aclp,
2079     kauth_cred_t cred)
2080 {
2081 	int error;
2082 	bool mpsafe;
2083 	struct vop_aclcheck_args a;
2084 	struct mount *mp;
2085 	a.a_desc = VDESC(vop_aclcheck);
2086 	a.a_vp = vp;
2087 	a.a_type = type;
2088 	a.a_aclp = aclp;
2089 	a.a_cred = cred;
2090 	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
2091 	if (error)
2092 		return error;
2093 	error = (VCALL(vp, VOFFSET(vop_aclcheck), &a));
2094 	vop_post(vp, mp, mpsafe, FST_YES);
2095 	return error;
2096 }
2097 
2098 const int vop_closeextattr_vp_offsets[] = {
2099 	VOPARG_OFFSETOF(struct vop_closeextattr_args,a_vp),
2100 	VDESC_NO_OFFSET
2101 };
2102 const struct vnodeop_desc vop_closeextattr_desc = {
2103 	VOP_CLOSEEXTATTR_DESCOFFSET,
2104 	"vop_closeextattr",
2105 	0,
2106 	vop_closeextattr_vp_offsets,
2107 	VDESC_NO_OFFSET,
2108 	VOPARG_OFFSETOF(struct vop_closeextattr_args, a_cred),
2109 	VDESC_NO_OFFSET,
2110 };
2111 int
2112 VOP_CLOSEEXTATTR(struct vnode *vp,
2113     int commit,
2114     kauth_cred_t cred)
2115 {
2116 	int error;
2117 	bool mpsafe;
2118 	struct vop_closeextattr_args a;
2119 	struct mount *mp;
2120 	a.a_desc = VDESC(vop_closeextattr);
2121 	a.a_vp = vp;
2122 	a.a_commit = commit;
2123 	a.a_cred = cred;
2124 	assert_vop_locked(vp, "vop_closeextattr: vp");
2125 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
2126 	if (error)
2127 		return error;
2128 	error = (VCALL(vp, VOFFSET(vop_closeextattr), &a));
2129 	vop_post(vp, mp, mpsafe, FST_NO);
2130 	return error;
2131 }
2132 
2133 const int vop_getextattr_vp_offsets[] = {
2134 	VOPARG_OFFSETOF(struct vop_getextattr_args,a_vp),
2135 	VDESC_NO_OFFSET
2136 };
2137 const struct vnodeop_desc vop_getextattr_desc = {
2138 	VOP_GETEXTATTR_DESCOFFSET,
2139 	"vop_getextattr",
2140 	0,
2141 	vop_getextattr_vp_offsets,
2142 	VDESC_NO_OFFSET,
2143 	VOPARG_OFFSETOF(struct vop_getextattr_args, a_cred),
2144 	VDESC_NO_OFFSET,
2145 };
2146 int
2147 VOP_GETEXTATTR(struct vnode *vp,
2148     int attrnamespace,
2149     const char *name,
2150     struct uio *uio,
2151     size_t *size,
2152     kauth_cred_t cred)
2153 {
2154 	int error;
2155 	bool mpsafe;
2156 	struct vop_getextattr_args a;
2157 	struct mount *mp;
2158 	a.a_desc = VDESC(vop_getextattr);
2159 	a.a_vp = vp;
2160 	a.a_attrnamespace = attrnamespace;
2161 	a.a_name = name;
2162 	a.a_uio = uio;
2163 	a.a_size = size;
2164 	a.a_cred = cred;
2165 	assert_vop_locked(vp, "vop_getextattr: vp");
2166 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
2167 	if (error)
2168 		return error;
2169 	error = (VCALL(vp, VOFFSET(vop_getextattr), &a));
2170 	vop_post(vp, mp, mpsafe, FST_NO);
2171 	return error;
2172 }
2173 
2174 const int vop_listextattr_vp_offsets[] = {
2175 	VOPARG_OFFSETOF(struct vop_listextattr_args,a_vp),
2176 	VDESC_NO_OFFSET
2177 };
2178 const struct vnodeop_desc vop_listextattr_desc = {
2179 	VOP_LISTEXTATTR_DESCOFFSET,
2180 	"vop_listextattr",
2181 	0,
2182 	vop_listextattr_vp_offsets,
2183 	VDESC_NO_OFFSET,
2184 	VOPARG_OFFSETOF(struct vop_listextattr_args, a_cred),
2185 	VDESC_NO_OFFSET,
2186 };
2187 int
2188 VOP_LISTEXTATTR(struct vnode *vp,
2189     int attrnamespace,
2190     struct uio *uio,
2191     size_t *size,
2192     int flag,
2193     kauth_cred_t cred)
2194 {
2195 	int error;
2196 	bool mpsafe;
2197 	struct vop_listextattr_args a;
2198 	struct mount *mp;
2199 	a.a_desc = VDESC(vop_listextattr);
2200 	a.a_vp = vp;
2201 	a.a_attrnamespace = attrnamespace;
2202 	a.a_uio = uio;
2203 	a.a_size = size;
2204 	a.a_flag = flag;
2205 	a.a_cred = cred;
2206 	assert_vop_locked(vp, "vop_listextattr: vp");
2207 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
2208 	if (error)
2209 		return error;
2210 	error = (VCALL(vp, VOFFSET(vop_listextattr), &a));
2211 	vop_post(vp, mp, mpsafe, FST_NO);
2212 	return error;
2213 }
2214 
2215 const int vop_openextattr_vp_offsets[] = {
2216 	VOPARG_OFFSETOF(struct vop_openextattr_args,a_vp),
2217 	VDESC_NO_OFFSET
2218 };
2219 const struct vnodeop_desc vop_openextattr_desc = {
2220 	VOP_OPENEXTATTR_DESCOFFSET,
2221 	"vop_openextattr",
2222 	0,
2223 	vop_openextattr_vp_offsets,
2224 	VDESC_NO_OFFSET,
2225 	VOPARG_OFFSETOF(struct vop_openextattr_args, a_cred),
2226 	VDESC_NO_OFFSET,
2227 };
2228 int
2229 VOP_OPENEXTATTR(struct vnode *vp,
2230     kauth_cred_t cred)
2231 {
2232 	int error;
2233 	bool mpsafe;
2234 	struct vop_openextattr_args a;
2235 	struct mount *mp;
2236 	a.a_desc = VDESC(vop_openextattr);
2237 	a.a_vp = vp;
2238 	a.a_cred = cred;
2239 	assert_vop_locked(vp, "vop_openextattr: vp");
2240 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
2241 	if (error)
2242 		return error;
2243 	error = (VCALL(vp, VOFFSET(vop_openextattr), &a));
2244 	vop_post(vp, mp, mpsafe, FST_NO);
2245 	return error;
2246 }
2247 
2248 const int vop_deleteextattr_vp_offsets[] = {
2249 	VOPARG_OFFSETOF(struct vop_deleteextattr_args,a_vp),
2250 	VDESC_NO_OFFSET
2251 };
2252 const struct vnodeop_desc vop_deleteextattr_desc = {
2253 	VOP_DELETEEXTATTR_DESCOFFSET,
2254 	"vop_deleteextattr",
2255 	0,
2256 	vop_deleteextattr_vp_offsets,
2257 	VDESC_NO_OFFSET,
2258 	VOPARG_OFFSETOF(struct vop_deleteextattr_args, a_cred),
2259 	VDESC_NO_OFFSET,
2260 };
2261 int
2262 VOP_DELETEEXTATTR(struct vnode *vp,
2263     int attrnamespace,
2264     const char *name,
2265     kauth_cred_t cred)
2266 {
2267 	int error;
2268 	bool mpsafe;
2269 	struct vop_deleteextattr_args a;
2270 	struct mount *mp;
2271 	a.a_desc = VDESC(vop_deleteextattr);
2272 	a.a_vp = vp;
2273 	a.a_attrnamespace = attrnamespace;
2274 	a.a_name = name;
2275 	a.a_cred = cred;
2276 	assert_vop_elocked(vp, "vop_deleteextattr: vp");
2277 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
2278 	if (error)
2279 		return error;
2280 	error = (VCALL(vp, VOFFSET(vop_deleteextattr), &a));
2281 	vop_post(vp, mp, mpsafe, FST_NO);
2282 	return error;
2283 }
2284 
2285 const int vop_setextattr_vp_offsets[] = {
2286 	VOPARG_OFFSETOF(struct vop_setextattr_args,a_vp),
2287 	VDESC_NO_OFFSET
2288 };
2289 const struct vnodeop_desc vop_setextattr_desc = {
2290 	VOP_SETEXTATTR_DESCOFFSET,
2291 	"vop_setextattr",
2292 	0,
2293 	vop_setextattr_vp_offsets,
2294 	VDESC_NO_OFFSET,
2295 	VOPARG_OFFSETOF(struct vop_setextattr_args, a_cred),
2296 	VDESC_NO_OFFSET,
2297 };
2298 int
2299 VOP_SETEXTATTR(struct vnode *vp,
2300     int attrnamespace,
2301     const char *name,
2302     struct uio *uio,
2303     kauth_cred_t cred)
2304 {
2305 	int error;
2306 	bool mpsafe;
2307 	struct vop_setextattr_args a;
2308 	struct mount *mp;
2309 	a.a_desc = VDESC(vop_setextattr);
2310 	a.a_vp = vp;
2311 	a.a_attrnamespace = attrnamespace;
2312 	a.a_name = name;
2313 	a.a_uio = uio;
2314 	a.a_cred = cred;
2315 	assert_vop_elocked(vp, "vop_setextattr: vp");
2316 	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
2317 	if (error)
2318 		return error;
2319 	error = (VCALL(vp, VOFFSET(vop_setextattr), &a));
2320 	vop_post(vp, mp, mpsafe, FST_NO);
2321 	return error;
2322 }
2323 
2324 const struct vnodeop_desc * const vfs_op_descs[] = {
2325 	&vop_default_desc,	/* MUST BE FIRST */
2326 
2327 	&vop_bwrite_desc,
2328 	&vop_parsepath_desc,
2329 	&vop_lookup_desc,
2330 	&vop_create_desc,
2331 	&vop_mknod_desc,
2332 	&vop_open_desc,
2333 	&vop_close_desc,
2334 	&vop_access_desc,
2335 	&vop_accessx_desc,
2336 	&vop_getattr_desc,
2337 	&vop_setattr_desc,
2338 	&vop_read_desc,
2339 	&vop_write_desc,
2340 	&vop_fallocate_desc,
2341 	&vop_fdiscard_desc,
2342 	&vop_ioctl_desc,
2343 	&vop_fcntl_desc,
2344 	&vop_poll_desc,
2345 	&vop_kqfilter_desc,
2346 	&vop_revoke_desc,
2347 	&vop_mmap_desc,
2348 	&vop_fsync_desc,
2349 	&vop_seek_desc,
2350 	&vop_remove_desc,
2351 	&vop_link_desc,
2352 	&vop_rename_desc,
2353 	&vop_mkdir_desc,
2354 	&vop_rmdir_desc,
2355 	&vop_symlink_desc,
2356 	&vop_readdir_desc,
2357 	&vop_readlink_desc,
2358 	&vop_abortop_desc,
2359 	&vop_inactive_desc,
2360 	&vop_reclaim_desc,
2361 	&vop_lock_desc,
2362 	&vop_unlock_desc,
2363 	&vop_bmap_desc,
2364 	&vop_strategy_desc,
2365 	&vop_print_desc,
2366 	&vop_islocked_desc,
2367 	&vop_pathconf_desc,
2368 	&vop_advlock_desc,
2369 	&vop_whiteout_desc,
2370 	&vop_getpages_desc,
2371 	&vop_putpages_desc,
2372 	&vop_getacl_desc,
2373 	&vop_setacl_desc,
2374 	&vop_aclcheck_desc,
2375 	&vop_closeextattr_desc,
2376 	&vop_getextattr_desc,
2377 	&vop_listextattr_desc,
2378 	&vop_openextattr_desc,
2379 	&vop_deleteextattr_desc,
2380 	&vop_setextattr_desc,
2381 	NULL
2382 };
2383