8446 uts: pci_check_bios() should check for BIOS
[unleashed.git] / include / sys / vnode_dispatch.h
blob53e7cf9b2d0406c85404482b48e7c74adbc66194
1 /*
2 * Copyright 2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #ifndef _SYS_VNODE_DISPATCH_H
18 #define _SYS_VNODE_DISPATCH_H
20 #include <sys/vnode.h>
21 #include <sys/stdbool.h>
22 #include <sys/fem.h>
23 #include <sys/fs_subr.h>
26 * Ideally these static inlines could be just inline statements in the
27 * corresponding fop_*() functions. Unfortunately, fem gets in the way and
28 * we have to make these to centralize the damage.
30 * Let's use the close vnode op as an example.
32 * fop_close() calls the fop_close_dispatch() static inline defined in this
33 * header. fop_close_dispatch() does one of three things:
35 * (1) checks if fem processing is required, and if so calls vhead_close()
36 * (2) checks if ->vop_close is NULL, and if it is returns not-implemented
37 * errno (i.e., ENOSYS)
38 * (3) calls ->vop_close
40 * The odd bit is because of how fem works. fem calls the first callback on
41 * its list of callbacks. That callback, is allowed to call the second
42 * callback, which is allowed the call the next, and so on. Eventually,
43 * there is no next callback to invoke and the actual vnode op is supposed
44 * to be called. Since the vnode op may be NULL (meaning default action) we
45 * need to do the default behavior checking in fem as well. We accomplish
46 * this by having fem call the dispatch function. The only difference
47 * between the fop_close() and the fem invocation is the value of the
48 * check_fem bool arg. The fem invocation sets it to false to avoid
49 * recursing back into fem.
52 #define FOP_DISPATCH(fname, vopname, vheadname, args, callargs) \
53 static inline int fname args \
54 { \
55 if (check_fem && vnode->v_femhead != NULL) \
56 return vheadname callargs; \
57 if (vnode->v_op->vopname == NULL) \
58 return ENOSYS; \
59 return vnode->v_op->vopname callargs; \
62 /* open takes a struct vnode **, so it is hand-coded */
63 static inline int fop_open_dispatch(struct vnode **vnode, int mode, cred_t *cr,
64 caller_context_t *ct, bool check_fem)
66 if (check_fem && (*vnode)->v_femhead != NULL)
67 return vhead_open(vnode, mode, cr, ct);
69 if ((*vnode)->v_op->vop_open == NULL)
70 return ENOSYS;
72 return (*vnode)->v_op->vop_open(vnode, mode, cr, ct);
75 FOP_DISPATCH(fop_close_dispatch, vop_close, vhead_close,
76 (struct vnode *vnode, int flag, int count, offset_t offset, cred_t *cr,
77 caller_context_t *ct, bool check_fem),
78 (vnode, flag, count, offset, cr, ct))
79 FOP_DISPATCH(fop_read_dispatch, vop_read, vhead_read,
80 (struct vnode *vnode, uio_t *uio, int ioflag, cred_t *cr,
81 caller_context_t *ct, bool check_fem),
82 (vnode, uio, ioflag, cr, ct))
83 FOP_DISPATCH(fop_write_dispatch, vop_write, vhead_write,
84 (struct vnode *vnode, uio_t *uio, int ioflag, cred_t *cr,
85 caller_context_t *ct, bool check_fem),
86 (vnode, uio, ioflag, cr, ct))
87 FOP_DISPATCH(fop_ioctl_dispatch, vop_ioctl, vhead_ioctl,
88 (struct vnode *vnode, int cmd, intptr_t arg, int flag, cred_t *cr,
89 int *rvalp, caller_context_t *ct, bool check_fem),
90 (vnode, cmd, arg, flag, cr, rvalp, ct))
92 /* no-op by default, so it is hand-coded */
93 static inline int fop_setfl_dispatch(struct vnode *vnode, int oflags,
94 int nflags, cred_t *cr,
95 caller_context_t *ct, bool check_fem)
97 if (check_fem && vnode->v_femhead != NULL)
98 return vhead_setfl(vnode, oflags, nflags, cr, ct);
100 if (vnode->v_op->vop_setfl == NULL)
101 return 0;
103 return vnode->v_op->vop_setfl(vnode, oflags, nflags, cr, ct);
106 FOP_DISPATCH(fop_getattr_dispatch, vop_getattr, vhead_getattr,
107 (struct vnode *vnode, vattr_t *vap, int flags, cred_t *cr,
108 caller_context_t *ct, bool check_fem),
109 (vnode, vap, flags, cr, ct))
110 FOP_DISPATCH(fop_setattr_dispatch, vop_setattr, vhead_setattr,
111 (struct vnode *vnode, vattr_t *vap, int flags, cred_t *cr,
112 caller_context_t *ct, bool check_fem),
113 (vnode, vap, flags, cr, ct))
114 FOP_DISPATCH(fop_access_dispatch, vop_access, vhead_access,
115 (struct vnode *vnode, int mode, int flags, cred_t *cr,
116 caller_context_t *ct, bool check_fem),
117 (vnode, mode, flags, cr, ct))
118 FOP_DISPATCH(fop_lookup_dispatch, vop_lookup, vhead_lookup,
119 (struct vnode *vnode, char *nm, struct vnode **vpp, pathname_t *pnp,
120 int flags, struct vnode *rdir, cred_t *cr, caller_context_t *ct,
121 int *direntflags, pathname_t *realpnp, bool check_fem),
122 (vnode, nm, vpp, pnp, flags, rdir, cr, ct, direntflags, realpnp))
123 FOP_DISPATCH(fop_create_dispatch, vop_create, vhead_create,
124 (struct vnode *vnode, char *name, vattr_t *vap, vcexcl_t excl,
125 int mode, struct vnode **vpp, cred_t *cr, int flag, caller_context_t *ct,
126 vsecattr_t *vsecattr, bool check_fem),
127 (vnode, name, vap, excl, mode, vpp, cr, flag, ct, vsecattr))
128 FOP_DISPATCH(fop_remove_dispatch, vop_remove, vhead_remove,
129 (struct vnode *vnode, char *nm, cred_t *cr, caller_context_t *ct,
130 int flags, bool check_fem),
131 (vnode, nm, cr, ct, flags))
132 FOP_DISPATCH(fop_link_dispatch, vop_link, vhead_link,
133 (struct vnode *vnode, struct vnode *svp, char *tnm, cred_t *cr,
134 caller_context_t *ct, int flags, bool check_fem),
135 (vnode, svp, tnm, cr, ct, flags))
136 FOP_DISPATCH(fop_rename_dispatch, vop_rename, vhead_rename,
137 (struct vnode *vnode, char *snm, struct vnode *tdvp, char *tnm,
138 cred_t *cr, caller_context_t *ct, int flags, bool check_fem),
139 (vnode, snm, tdvp, tnm, cr, ct, flags))
140 FOP_DISPATCH(fop_mkdir_dispatch, vop_mkdir, vhead_mkdir,
141 (struct vnode *vnode, char *dirname, vattr_t *vap, struct vnode **vpp,
142 cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp,
143 bool check_fem),
144 (vnode, dirname, vap, vpp, cr, ct, flags, vsecp))
145 FOP_DISPATCH(fop_rmdir_dispatch, vop_rmdir, vhead_rmdir,
146 (struct vnode *vnode, char *nm, struct vnode *cdir, cred_t *cr,
147 caller_context_t *ct, int flags, bool check_fem),
148 (vnode, nm, cdir, cr, ct, flags))
149 FOP_DISPATCH(fop_readdir_dispatch, vop_readdir, vhead_readdir,
150 (struct vnode *vnode, uio_t *uiop, cred_t *cr, int *eofp,
151 caller_context_t *ct, int flags, bool check_fem),
152 (vnode, uiop, cr, eofp, ct, flags))
153 FOP_DISPATCH(fop_symlink_dispatch, vop_symlink, vhead_symlink,
154 (struct vnode *vnode, char *linkname, vattr_t *vap, char *target,
155 cred_t *cr, caller_context_t *ct, int flags, bool check_fem),
156 (vnode, linkname, vap, target, cr, ct, flags))
157 FOP_DISPATCH(fop_readlink_dispatch, vop_readlink, vhead_readlink,
158 (struct vnode *vnode, uio_t *uiop, cred_t *cr, caller_context_t *ct,
159 bool check_fem),
160 (vnode, uiop, cr, ct))
161 FOP_DISPATCH(fop_fsync_dispatch, vop_fsync, vhead_fsync,
162 (struct vnode *vnode, int syncflag, cred_t *cr, caller_context_t *ct,
163 bool check_fem),
164 (vnode, syncflag, cr, ct))
166 /* returns void, so it is hand-coded */
167 static inline void fop_inactive_dispatch(struct vnode *vnode, cred_t *cr,
168 caller_context_t *ct, bool check_fem)
170 if (check_fem && vnode->v_femhead != NULL)
171 vhead_inactive(vnode, cr, ct);
172 else if (vnode->v_op->vop_inactive != NULL)
173 vnode->v_op->vop_inactive(vnode, cr, ct);
176 FOP_DISPATCH(fop_fid_dispatch, vop_fid, vhead_fid,
177 (struct vnode *vnode, fid_t *fidp, caller_context_t *ct, bool check_fem),
178 (vnode, fidp, ct))
180 /* return -1 by default, so it is hand-coded */
181 static inline int fop_rwlock_dispatch(struct vnode *vnode, int write_lock,
182 caller_context_t *ct, bool check_fem)
184 if (check_fem && vnode->v_femhead != NULL)
185 return vhead_rwlock(vnode, write_lock, ct);
187 if (vnode->v_op->vop_rwlock == NULL)
188 return -1;
190 return vnode->v_op->vop_rwlock(vnode, write_lock, ct);
193 /* returns void, so it is hand-coded */
194 static inline void fop_rwunlock_dispatch(struct vnode *vnode, int write_lock,
195 caller_context_t *ct, bool check_fem)
197 if (check_fem && vnode->v_femhead != NULL)
198 vhead_rwunlock(vnode, write_lock, ct);
199 else if (vnode->v_op->vop_rwunlock != NULL)
200 vnode->v_op->vop_rwunlock(vnode, write_lock, ct);
203 FOP_DISPATCH(fop_seek_dispatch, vop_seek, vhead_seek,
204 (struct vnode *vnode, offset_t off, offset_t *noff, caller_context_t *ct,
205 bool check_fem),
206 (vnode, off, noff, ct))
208 /* compares pointers by default, so it is hand-coded */
209 static inline int fop_cmp_dispatch(struct vnode *vnode1, struct vnode *vnode2,
210 caller_context_t *ct, bool check_fem)
212 if (check_fem && vnode1->v_femhead != NULL)
213 return vhead_cmp(vnode1, vnode2, ct);
215 if (vnode1->v_op->vop_cmp == NULL)
216 return vnode1 == vnode2;
218 return vnode1->v_op->vop_cmp(vnode1, vnode2, ct);
221 /* calls fs_frlock by default, so it is hand-coded */
222 static inline int fop_frlock_dispatch(struct vnode *vnode, int cmd,
223 flock64_t *bfp, int flag, offset_t offset,
224 struct flk_callback *flk_cbp, cred_t *cr,
225 caller_context_t *ct, bool check_fem)
227 if (check_fem && vnode->v_femhead != NULL)
228 return vhead_frlock(vnode, cmd, bfp, flag, offset, flk_cbp, cr,
229 ct);
231 if (vnode->v_op->vop_frlock == NULL)
232 return fs_frlock(vnode, cmd, bfp, flag, offset, flk_cbp, cr,
233 ct);
235 return vnode->v_op->vop_frlock(vnode, cmd, bfp, flag, offset,
236 flk_cbp, cr, ct);
239 FOP_DISPATCH(fop_space_dispatch, vop_space, vhead_space,
240 (struct vnode *vnode, int cmd, flock64_t *bfp, int flag, offset_t offset,
241 cred_t *cr, caller_context_t *ct, bool check_fem),
242 (vnode, cmd, bfp, flag, offset, cr, ct))
243 FOP_DISPATCH(fop_realvp_dispatch, vop_realvp, vhead_realvp,
244 (struct vnode *vnode, struct vnode **vpp, caller_context_t *ct,
245 bool check_fem),
246 (vnode, vpp, ct))
247 FOP_DISPATCH(fop_getpage_dispatch, vop_getpage, vhead_getpage,
248 (struct vnode *vnode, offset_t off, size_t len, uint_t *protp,
249 struct page **plarr, size_t plsz, struct seg *seg, caddr_t addr,
250 enum seg_rw rw, cred_t *cr, caller_context_t *ct, bool check_fem),
251 (vnode, off, len, protp, plarr, plsz, seg, addr, rw, cr, ct))
252 FOP_DISPATCH(fop_putpage_dispatch, vop_putpage, vhead_putpage,
253 (struct vnode *vnode, offset_t off, size_t len, int flags, cred_t *cr,
254 caller_context_t *ct, bool check_fem),
255 (vnode, off, len, flags, cr, ct))
256 FOP_DISPATCH(fop_map_dispatch, vop_map, vhead_map,
257 (struct vnode *vnode, offset_t off, struct as *as, caddr_t *addr,
258 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr,
259 caller_context_t *ct, bool check_fem),
260 (vnode, off, as, addr, len, prot, maxprot, flags, cr, ct))
261 FOP_DISPATCH(fop_addmap_dispatch, vop_addmap, vhead_addmap,
262 (struct vnode *vnode, offset_t off, struct as *as, caddr_t addr,
263 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr,
264 caller_context_t *ct, bool check_fem),
265 (vnode, off, as, addr, len, prot, maxprot, flags, cr, ct))
266 FOP_DISPATCH(fop_delmap_dispatch, vop_delmap, vhead_delmap,
267 (struct vnode *vnode, offset_t off, struct as *as, caddr_t addr, size_t len,
268 uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr,
269 caller_context_t *ct, bool check_fem),
270 (vnode, off, as, addr, len, prot, maxprot, flags, cr, ct))
272 /* calls fs_poll by default, so it is hand-coded */
273 static inline int fop_poll_dispatch(struct vnode *vnode, short events,
274 int anyyet, short *reventsp,
275 struct pollhead **phpp,
276 caller_context_t *ct, bool check_fem)
278 if (check_fem && vnode->v_femhead != NULL)
279 return vhead_poll(vnode, events, anyyet, reventsp, phpp, ct);
281 if (vnode->v_op->vop_poll == NULL)
282 return fs_poll(vnode, events, anyyet, reventsp, phpp, ct);
284 return vnode->v_op->vop_poll(vnode, events, anyyet, reventsp, phpp, ct);
287 FOP_DISPATCH(fop_dump_dispatch, vop_dump, vhead_dump,
288 (struct vnode *vnode, caddr_t addr, offset_t lbdn, offset_t dblks,
289 caller_context_t *ct, bool check_fem),
290 (vnode, addr, lbdn, dblks, ct))
292 /* calls fs_pathconf by default, so it is hand-coded */
293 static inline int fop_pathconf_dispatch(struct vnode *vnode, int cmd,
294 ulong_t *valp, cred_t *cr,
295 caller_context_t *ct, bool check_fem)
297 if (check_fem && vnode->v_femhead != NULL)
298 return vhead_pathconf(vnode, cmd, valp, cr, ct);
300 if (vnode->v_op->vop_pathconf == NULL)
301 return fs_pathconf(vnode, cmd, valp, cr, ct);
303 return vnode->v_op->vop_pathconf(vnode, cmd, valp, cr, ct);
306 FOP_DISPATCH(fop_pageio_dispatch, vop_pageio, vhead_pageio,
307 (struct vnode *vnode, struct page *page, uoff_t io_off, size_t io_len,
308 int flags, cred_t *cr, caller_context_t *ct, bool check_fem),
309 (vnode, page, io_off, io_len, flags, cr, ct))
310 FOP_DISPATCH(fop_dumpctl_dispatch, vop_dumpctl, vhead_dumpctl,
311 (struct vnode *vnode, int action, offset_t *blkp,
312 caller_context_t *ct, bool check_fem),
313 (vnode, action, blkp, ct))
315 /* returns void & calls fs_dispose by default, so it is hand-coded */
316 static inline void fop_dispose_dispatch(struct vnode *vnode, struct page *pp,
317 int flag, int dn, cred_t *cr,
318 caller_context_t *ct, bool check_fem)
320 if (check_fem && vnode->v_femhead != NULL)
321 vhead_dispose(vnode, pp, flag, dn, cr, ct);
322 else if (vnode->v_op->vop_dispose == NULL)
323 fs_dispose(vnode, pp, flag, dn, cr, ct);
324 else
325 vnode->v_op->vop_dispose(vnode, pp, flag, dn, cr, ct);
328 FOP_DISPATCH(fop_setsecattr_dispatch, vop_setsecattr, vhead_setsecattr,
329 (struct vnode *vnode, vsecattr_t *vsap, int flag, cred_t *cr,
330 caller_context_t *ct, bool check_fem),
331 (vnode, vsap, flag, cr, ct))
333 /* calls fs_fab_acl by default, so it is hand-coded */
334 static inline int fop_getsecattr_dispatch(struct vnode *vnode, vsecattr_t *vsap,
335 int flag, cred_t *cr,
336 caller_context_t *ct, bool check_fem)
338 if (check_fem && vnode->v_femhead != NULL)
339 return vhead_getsecattr(vnode, vsap, flag, cr, ct);
341 if (vnode->v_op->vop_getsecattr == NULL)
342 return fs_fab_acl(vnode, vsap, flag, cr, ct);
344 return vnode->v_op->vop_getsecattr(vnode, vsap, flag, cr, ct);
347 /* calls fs_shrlock by default, so it is hand-coded */
348 static inline int fop_shrlock_dispatch(struct vnode *vnode, int cmd,
349 struct shrlock *shr, int flag,
350 cred_t *cr, caller_context_t *ct,
351 bool check_fem)
353 if (check_fem && vnode->v_femhead != NULL)
354 return vhead_shrlock(vnode, cmd, shr, flag, cr, ct);
356 if (vnode->v_op->vop_shrlock == NULL)
357 return fs_shrlock(vnode, cmd, shr, flag, cr, ct);
359 return vnode->v_op->vop_shrlock(vnode, cmd, shr, flag, cr, ct);
362 /* returns ENOTSUP by default, so it is hand-coded */
363 static inline int fop_vnevent_dispatch(struct vnode *vnode, vnevent_t vnevent,
364 struct vnode *dvp, char *fnm,
365 caller_context_t *ct, bool check_fem)
367 if (check_fem && vnode->v_femhead != NULL)
368 return vhead_vnevent(vnode, vnevent, dvp, fnm, ct);
370 if (vnode->v_op->vop_vnevent == NULL)
371 return ENOTSUP;
373 return vnode->v_op->vop_vnevent(vnode, vnevent, dvp, fnm, ct);
376 FOP_DISPATCH(fop_reqzcbuf_dispatch, vop_reqzcbuf, vhead_reqzcbuf,
377 (struct vnode *vnode, enum uio_rw ioflag, xuio_t *uio, cred_t *cr,
378 caller_context_t *ct, bool check_fem),
379 (vnode, ioflag, uio, cr, ct))
380 FOP_DISPATCH(fop_retzcbuf_dispatch, vop_retzcbuf, vhead_retzcbuf,
381 (struct vnode *vnode, xuio_t *uio, cred_t *cr, caller_context_t *ct,
382 bool check_fem),
383 (vnode, uio, cr, ct))
385 #undef FOP_DISPATCH
387 #endif