]> git.saurik.com Git - apple/xnu.git/blob - bsd/miscfs/portal/portal_vnops.c
xnu-123.5.tar.gz
[apple/xnu.git] / bsd / miscfs / portal / portal_vnops.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23 /*
24 * Copyright (c) 1992, 1993
25 * The Regents of the University of California. All rights reserved.
26 *
27 * This code is derived from software donated to Berkeley by
28 * Jan-Simon Pendry.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
58 * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95
59 *
60 * @(#)portal_vnops.c 8.8 (Berkeley) 1/21/94
61 */
62
63 /*
64 * Portal Filesystem
65 */
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/kernel.h>
70 #include <sys/types.h>
71 #include <sys/time.h>
72 #include <sys/proc.h>
73 #include <sys/filedesc.h>
74 #include <sys/vnode.h>
75 #include <sys/file.h>
76 #include <sys/stat.h>
77 #include <sys/mount.h>
78 #include <sys/malloc.h>
79 #include <sys/namei.h>
80 #include <sys/mbuf.h>
81 #include <sys/socket.h>
82 #include <sys/socketvar.h>
83 #include <sys/ubc.h>
84 #include <sys/un.h>
85 #include <sys/unpcb.h>
86 #include <miscfs/portal/portal.h>
87 #include <vfs/vfs_support.h>
88
89 static int portal_fileid = PORTAL_ROOTFILEID+1;
90
91 static void
92 portal_closefd(p, fd)
93 struct proc *p;
94 int fd;
95 {
96 int error;
97 struct {
98 int fd;
99 } ua;
100 int rc;
101
102 ua.fd = fd;
103 error = close(p, &ua, &rc);
104 /*
105 * We should never get an error, and there isn't anything
106 * we could do if we got one, so just print a message.
107 */
108 if (error)
109 printf("portal_closefd: error = %d\n", error);
110 }
111
112 /*
113 * vp is the current namei directory
114 * cnp is the name to locate in that directory...
115 */
116 int
117 portal_lookup(ap)
118 struct vop_lookup_args /* {
119 struct vnode * a_dvp;
120 struct vnode ** a_vpp;
121 struct componentname * a_cnp;
122 } */ *ap;
123 {
124 struct componentname *cnp = ap->a_cnp;
125 struct vnode **vpp = ap->a_vpp;
126 struct vnode *dvp = ap->a_dvp;
127 char *pname = cnp->cn_nameptr;
128 struct portalnode *pt;
129 int error;
130 struct vnode *fvp = 0;
131 char *path;
132 int size;
133
134 *vpp = NULLVP;
135
136 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
137 return (EROFS);
138
139 if (cnp->cn_namelen == 1 && *pname == '.') {
140 *vpp = dvp;
141 VREF(dvp);
142 /*VOP_LOCK(dvp);*/
143 return (0);
144 }
145
146 MALLOC(pt, void *, sizeof(struct portalnode), M_TEMP, M_WAITOK);
147 error = getnewvnode(VT_PORTAL, dvp->v_mount, portal_vnodeop_p, &fvp);
148 if (error) {
149 FREE(pt, M_TEMP);
150 goto bad;
151 }
152 fvp->v_type = VREG;
153 ubc_info_init(fvp);
154 fvp->v_data = pt;
155
156 /*
157 * Save all of the remaining pathname and
158 * advance the namei next pointer to the end
159 * of the string.
160 */
161 for (size = 0, path = pname; *path; path++)
162 size++;
163 cnp->cn_consume = size - cnp->cn_namelen;
164
165 MALLOC(pt->pt_arg, caddr_t, size+1, M_TEMP, M_WAITOK);
166 pt->pt_size = size+1;
167 bcopy(pname, pt->pt_arg, pt->pt_size);
168 pt->pt_fileid = portal_fileid++;
169
170 *vpp = fvp;
171 /*VOP_LOCK(fvp);*/
172 return (0);
173
174 bad:
175 if (fvp)
176 vrele(fvp);
177 return (error);
178 }
179
180 /* This should be called only from network funnel */
181 static int
182 portal_connect(so, so2)
183 struct socket *so;
184 struct socket *so2;
185 {
186 /* from unp_connect, bypassing the namei stuff... */
187 struct socket *so3;
188 struct unpcb *unp2;
189 struct unpcb *unp3;
190
191 if (so2 == 0)
192 return (ECONNREFUSED);
193
194 if (so->so_type != so2->so_type)
195 return (EPROTOTYPE);
196
197 if ((so2->so_options & SO_ACCEPTCONN) == 0)
198 return (ECONNREFUSED);
199
200 if ((so3 = sonewconn(so2, 0)) == 0)
201 return (ECONNREFUSED);
202
203 unp2 = sotounpcb(so2);
204 unp3 = sotounpcb(so3);
205 if (unp2->unp_addr)
206 unp3->unp_addr = m_copy(unp2->unp_addr, 0, (int)M_COPYALL);
207
208 so2 = so3;
209
210
211 return (unp_connect2(so, so2));
212 }
213
214 int
215 portal_open(ap)
216 struct vop_open_args /* {
217 struct vnode *a_vp;
218 int a_mode;
219 struct ucred *a_cred;
220 struct proc *a_p;
221 } */ *ap;
222 {
223 struct socket *so = 0;
224 struct portalnode *pt;
225 struct proc *p = ap->a_p;
226 struct vnode *vp = ap->a_vp;
227 int s;
228 struct uio auio;
229 struct iovec aiov[2];
230 int res;
231 struct mbuf *cm = 0;
232 struct cmsghdr *cmsg;
233 int newfds;
234 int *ip;
235 int fd;
236 int error;
237 int len;
238 struct portalmount *fmp;
239 struct file *fp;
240 struct portal_cred pcred;
241
242 /*
243 * Nothing to do when opening the root node.
244 */
245 if (vp->v_flag & VROOT)
246 return (0);
247
248 /*
249 * Can't be opened unless the caller is set up
250 * to deal with the side effects. Check for this
251 * by testing whether the p_dupfd has been set.
252 */
253 if (p->p_dupfd >= 0)
254 return (ENODEV);
255
256 pt = VTOPORTAL(vp);
257 fmp = VFSTOPORTAL(vp->v_mount);
258
259 /*
260 * Create a new socket.
261 */
262 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
263 error = socreate(AF_UNIX, &so, SOCK_STREAM, 0);
264 if (error) {
265 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
266 goto bad;
267 }
268
269 /*
270 * Reserve some buffer space
271 */
272 res = pt->pt_size + sizeof(pcred) + 512; /* XXX */
273 error = soreserve(so, res, res);
274 if (error) {
275 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
276 goto bad;
277 }
278
279 /*
280 * Kick off connection
281 */
282 error = portal_connect(so, (struct socket *)fmp->pm_server->f_data);
283 if (error) {
284 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
285 goto bad;
286 }
287
288 /*
289 * Wait for connection to complete
290 */
291 /*
292 * XXX: Since the mount point is holding a reference on the
293 * underlying server socket, it is not easy to find out whether
294 * the server process is still running. To handle this problem
295 * we loop waiting for the new socket to be connected (something
296 * which will only happen if the server is still running) or for
297 * the reference count on the server socket to drop to 1, which
298 * will happen if the server dies. Sleep for 5 second intervals
299 * and keep polling the reference count. XXX.
300 */
301 s = splnet();
302 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
303 if (fcount(fmp->pm_server) == 1) {
304 error = ECONNREFUSED;
305 splx(s);
306 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
307 goto bad;
308 }
309 (void) tsleep((caddr_t) &so->so_timeo, PSOCK, "portalcon", 5 * hz);
310 }
311 splx(s);
312
313 if (so->so_error) {
314 error = so->so_error;
315 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
316 goto bad;
317 }
318
319 /*
320 * Set miscellaneous flags
321 */
322 so->so_rcv.sb_timeo = 0;
323 so->so_snd.sb_timeo = 0;
324 so->so_rcv.sb_flags |= SB_NOINTR;
325 so->so_snd.sb_flags |= SB_NOINTR;
326
327
328 pcred.pcr_flag = ap->a_mode;
329 pcred.pcr_uid = ap->a_cred->cr_uid;
330 pcred.pcr_ngroups = ap->a_cred->cr_ngroups;
331 bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t));
332 aiov[0].iov_base = (caddr_t) &pcred;
333 aiov[0].iov_len = sizeof(pcred);
334 aiov[1].iov_base = pt->pt_arg;
335 aiov[1].iov_len = pt->pt_size;
336 auio.uio_iov = aiov;
337 auio.uio_iovcnt = 2;
338 auio.uio_rw = UIO_WRITE;
339 auio.uio_segflg = UIO_SYSSPACE;
340 auio.uio_procp = p;
341 auio.uio_offset = 0;
342 auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len;
343
344 error = sosend(so, (struct sockaddr *) 0, &auio,
345 (struct mbuf *) 0, (struct mbuf *) 0, 0);
346 if (error) {
347 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
348 goto bad;
349 }
350
351 len = auio.uio_resid = sizeof(int);
352 do {
353 struct mbuf *m = 0;
354 int flags = MSG_WAITALL;
355 error = soreceive(so, (struct sockaddr **) 0, &auio,
356 &m, &cm, &flags);
357 if (error) {
358 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
359 goto bad;
360 }
361
362 /*
363 * Grab an error code from the mbuf.
364 */
365 if (m) {
366 m = m_pullup(m, sizeof(int)); /* Needed? */
367 if (m) {
368 error = *(mtod(m, int *));
369 m_freem(m);
370 } else {
371 error = EINVAL;
372 }
373 } else {
374 if (cm == 0) {
375 error = ECONNRESET; /* XXX */
376 #ifdef notdef
377 break;
378 #endif
379 }
380 }
381 } while (cm == 0 && auio.uio_resid == len && !error);
382
383 if (cm == 0) {
384 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
385 goto bad;
386 }
387
388 if (auio.uio_resid) {
389 error = 0;
390 #ifdef notdef
391 error = EMSGSIZE;
392 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
393 goto bad;
394 #endif
395 }
396
397 /*
398 * XXX: Break apart the control message, and retrieve the
399 * received file descriptor. Note that more than one descriptor
400 * may have been received, or that the rights chain may have more
401 * than a single mbuf in it. What to do?
402 */
403 cmsg = mtod(cm, struct cmsghdr *);
404 newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int);
405 if (newfds == 0) {
406 error = ECONNREFUSED;
407 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
408 goto bad;
409 }
410 /*
411 * At this point the rights message consists of a control message
412 * header, followed by a data region containing a vector of
413 * integer file descriptors. The fds were allocated by the action
414 * of receiving the control message.
415 */
416 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
417 ip = (int *) (cmsg + 1);
418 fd = *ip++;
419 if (newfds > 1) {
420 /*
421 * Close extra fds.
422 */
423 int i;
424 printf("portal_open: %d extra fds\n", newfds - 1);
425 for (i = 1; i < newfds; i++) {
426 portal_closefd(p, *ip);
427 ip++;
428 }
429 }
430
431 /*
432 * Check that the mode the file is being opened for is a subset
433 * of the mode of the existing descriptor.
434 */
435 fp = *fdfile(p, fd);
436 if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
437 portal_closefd(p, fd);
438 error = EACCES;
439 goto bad;
440 }
441
442 /*
443 * Save the dup fd in the proc structure then return the
444 * special error code (ENXIO) which causes magic things to
445 * happen in vn_open. The whole concept is, well, hmmm.
446 */
447 p->p_dupfd = fd;
448 error = ENXIO;
449
450 bad:;
451 /*
452 * And discard the control message.
453 */
454 if (cm) {
455 m_freem(cm);
456 }
457
458 if (so) {
459 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
460 soshutdown(so, 2);
461 soclose(so);
462 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
463 }
464 return (error);
465 }
466
467 int
468 portal_getattr(ap)
469 struct vop_getattr_args /* {
470 struct vnode *a_vp;
471 struct vattr *a_vap;
472 struct ucred *a_cred;
473 struct proc *a_p;
474 } */ *ap;
475 {
476 struct vnode *vp = ap->a_vp;
477 struct vattr *vap = ap->a_vap;
478 struct timeval tv;
479
480 bzero(vap, sizeof(*vap));
481 vattr_null(vap);
482 vap->va_uid = 0;
483 vap->va_gid = 0;
484 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
485 vap->va_size = DEV_BSIZE;
486 vap->va_blocksize = DEV_BSIZE;
487 microtime(&tv);
488 TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime);
489 vap->va_mtime = vap->va_atime;
490 vap->va_ctime = vap->va_ctime;
491 vap->va_gen = 0;
492 vap->va_flags = 0;
493 vap->va_rdev = 0;
494 /* vap->va_qbytes = 0; */
495 vap->va_bytes = 0;
496 /* vap->va_qsize = 0; */
497 if (vp->v_flag & VROOT) {
498 vap->va_type = VDIR;
499 vap->va_mode = S_IRUSR|S_IWUSR|S_IXUSR|
500 S_IRGRP|S_IWGRP|S_IXGRP|
501 S_IROTH|S_IWOTH|S_IXOTH;
502 vap->va_nlink = 2;
503 vap->va_fileid = 2;
504 } else {
505 vap->va_type = VREG;
506 vap->va_mode = S_IRUSR|S_IWUSR|
507 S_IRGRP|S_IWGRP|
508 S_IROTH|S_IWOTH;
509 vap->va_nlink = 1;
510 vap->va_fileid = VTOPORTAL(vp)->pt_fileid;
511 }
512 return (0);
513 }
514
515 int
516 portal_setattr(ap)
517 struct vop_setattr_args /* {
518 struct vnode *a_vp;
519 struct vattr *a_vap;
520 struct ucred *a_cred;
521 struct proc *a_p;
522 } */ *ap;
523 {
524
525 /*
526 * Can't mess with the root vnode
527 */
528 if (ap->a_vp->v_flag & VROOT)
529 return (EACCES);
530
531 return (0);
532 }
533
534 /*
535 * Fake readdir, just return empty directory.
536 * It is hard to deal with '.' and '..' so don't bother.
537 */
538 int
539 portal_readdir(ap)
540 struct vop_readdir_args /* {
541 struct vnode *a_vp;
542 struct uio *a_uio;
543 struct ucred *a_cred;
544 int *a_eofflag;
545 u_long *a_cookies;
546 int a_ncookies;
547 } */ *ap;
548 {
549
550 /*
551 * We don't allow exporting portal mounts, and currently local
552 * requests do not need cookies.
553 */
554 if (ap->a_ncookies)
555 panic("portal_readdir: not hungry");
556
557 return (0);
558 }
559
560 int
561 portal_inactive(ap)
562 struct vop_inactive_args /* {
563 struct vnode *a_vp;
564 struct proc *a_p;
565 } */ *ap;
566 {
567
568 VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
569 return (0);
570 }
571
572 int
573 portal_reclaim(ap)
574 struct vop_reclaim_args /* {
575 struct vnode *a_vp;
576 } */ *ap;
577 {
578 struct portalnode *pt = VTOPORTAL(ap->a_vp);
579
580 if (pt->pt_arg) {
581 _FREE((caddr_t) pt->pt_arg, M_TEMP);
582 pt->pt_arg = 0;
583 }
584 FREE(ap->a_vp->v_data, M_TEMP);
585 ap->a_vp->v_data = 0;
586
587 return (0);
588 }
589
590 /*
591 * Return POSIX pathconf information applicable to special devices.
592 */
593 portal_pathconf(ap)
594 struct vop_pathconf_args /* {
595 struct vnode *a_vp;
596 int a_name;
597 int *a_retval;
598 } */ *ap;
599 {
600
601 switch (ap->a_name) {
602 case _PC_LINK_MAX:
603 *ap->a_retval = LINK_MAX;
604 return (0);
605 case _PC_MAX_CANON:
606 *ap->a_retval = MAX_CANON;
607 return (0);
608 case _PC_MAX_INPUT:
609 *ap->a_retval = MAX_INPUT;
610 return (0);
611 case _PC_PIPE_BUF:
612 *ap->a_retval = PIPE_BUF;
613 return (0);
614 case _PC_CHOWN_RESTRICTED:
615 *ap->a_retval = 1;
616 return (0);
617 case _PC_VDISABLE:
618 *ap->a_retval = _POSIX_VDISABLE;
619 return (0);
620 default:
621 return (EINVAL);
622 }
623 /* NOTREACHED */
624 }
625
626 /*
627 * Print out the contents of a Portal vnode.
628 */
629 /* ARGSUSED */
630 int
631 portal_print(ap)
632 struct vop_print_args /* {
633 struct vnode *a_vp;
634 } */ *ap;
635 {
636
637 printf("tag VT_PORTAL, portal vnode\n");
638 return (0);
639 }
640
641 /*void*/
642 int
643 portal_vfree(ap)
644 struct vop_vfree_args /* {
645 struct vnode *a_pvp;
646 ino_t a_ino;
647 int a_mode;
648 } */ *ap;
649 {
650
651 return (0);
652 }
653
654
655 /*
656 * Portal vnode unsupported operation
657 */
658 int
659 portal_enotsupp()
660 {
661
662 return (EOPNOTSUPP);
663 }
664
665 /*
666 * Portal "should never get here" operation
667 */
668 int
669 portal_badop()
670 {
671
672 panic("portal: bad op");
673 /* NOTREACHED */
674 }
675
676 /*
677 * Portal vnode null operation
678 */
679 int
680 portal_nullop()
681 {
682
683 return (0);
684 }
685
686 #define portal_create ((int (*) __P((struct vop_create_args *)))portal_enotsupp)
687 #define portal_mknod ((int (*) __P((struct vop_mknod_args *)))portal_enotsupp)
688 #define portal_close ((int (*) __P((struct vop_close_args *)))nullop)
689 #define portal_access ((int (*) __P((struct vop_access_args *)))nullop)
690 #define portal_read ((int (*) __P((struct vop_read_args *)))portal_enotsupp)
691 #define portal_write ((int (*) __P((struct vop_write_args *)))portal_enotsupp)
692 #define portal_ioctl ((int (*) __P((struct vop_ioctl_args *)))portal_enotsupp)
693 #define portal_select ((int (*) __P((struct vop_select_args *)))portal_enotsupp)
694 #define portal_mmap ((int (*) __P((struct vop_mmap_args *)))portal_enotsupp)
695 #define portal_revoke vop_revoke
696 #define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
697 #define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop)
698 #define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp)
699 #define portal_link ((int (*) __P((struct vop_link_args *)))portal_enotsupp)
700 #define portal_rename ((int (*) __P((struct vop_rename_args *)))portal_enotsupp)
701 #define portal_mkdir ((int (*) __P((struct vop_mkdir_args *)))portal_enotsupp)
702 #define portal_rmdir ((int (*) __P((struct vop_rmdir_args *)))portal_enotsupp)
703 #define portal_symlink \
704 ((int (*) __P((struct vop_symlink_args *)))portal_enotsupp)
705 #define portal_readlink \
706 ((int (*) __P((struct vop_readlink_args *)))portal_enotsupp)
707 #define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
708 #define portal_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
709 #define portal_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
710 #define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop)
711 #define portal_strategy \
712 ((int (*) __P((struct vop_strategy_args *)))portal_badop)
713 #define portal_islocked \
714 ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
715 #define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
716 #define portal_advlock \
717 ((int (*) __P((struct vop_advlock_args *)))portal_enotsupp)
718 #define portal_blkatoff \
719 ((int (*) __P((struct vop_blkatoff_args *)))portal_enotsupp)
720 #define portal_valloc ((int(*) __P(( \
721 struct vnode *pvp, \
722 int mode, \
723 struct ucred *cred, \
724 struct vnode **vpp))) portal_enotsupp)
725 #define portal_truncate \
726 ((int (*) __P((struct vop_truncate_args *)))portal_enotsupp)
727 #define portal_update ((int (*) __P((struct vop_update_args *)))portal_enotsupp)
728 #define portal_copyfile ((int (*) __P((struct vop_copyfile *)))err_copyfile)
729 #define portal_bwrite ((int (*) __P((struct vop_bwrite_args *)))portal_enotsupp)
730 #define portal_blktooff \
731 ((int (*) __P((struct vop_blktooff_args *)))portal_enotsupp)
732 #define portal_offtoblk \
733 ((int (*) __P((struct vop_offtoblk_args *)))portal_enotsupp)
734 #define portal_cmap \
735 ((int (*) __P((struct vop_cmap_args *)))portal_enotsupp)
736
737 #define VOPFUNC int (*)(void *)
738
739 int (**portal_vnodeop_p)(void *);
740 struct vnodeopv_entry_desc portal_vnodeop_entries[] = {
741 { &vop_default_desc, (VOPFUNC)vn_default_error },
742 { &vop_lookup_desc, (VOPFUNC)portal_lookup }, /* lookup */
743 { &vop_create_desc, (VOPFUNC)portal_create }, /* create */
744 { &vop_mknod_desc, (VOPFUNC)portal_mknod }, /* mknod */
745 { &vop_open_desc, (VOPFUNC)portal_open }, /* open */
746 { &vop_close_desc, (VOPFUNC)portal_close }, /* close */
747 { &vop_access_desc, (VOPFUNC)portal_access }, /* access */
748 { &vop_getattr_desc, (VOPFUNC)portal_getattr }, /* getattr */
749 { &vop_setattr_desc, (VOPFUNC)portal_setattr }, /* setattr */
750 { &vop_read_desc, (VOPFUNC)portal_read }, /* read */
751 { &vop_write_desc, (VOPFUNC)portal_write }, /* write */
752 { &vop_ioctl_desc, (VOPFUNC)portal_ioctl }, /* ioctl */
753 { &vop_select_desc, (VOPFUNC)portal_select }, /* select */
754 { &vop_mmap_desc, (VOPFUNC)portal_mmap }, /* mmap */
755 { &vop_revoke_desc, (VOPFUNC)portal_revoke }, /* revoke */
756 { &vop_fsync_desc, (VOPFUNC)portal_fsync }, /* fsync */
757 { &vop_seek_desc, (VOPFUNC)portal_seek }, /* seek */
758 { &vop_remove_desc, (VOPFUNC)portal_remove }, /* remove */
759 { &vop_link_desc, (VOPFUNC)portal_link }, /* link */
760 { &vop_rename_desc, (VOPFUNC)portal_rename }, /* rename */
761 { &vop_mkdir_desc, (VOPFUNC)portal_mkdir }, /* mkdir */
762 { &vop_rmdir_desc, (VOPFUNC)portal_rmdir }, /* rmdir */
763 { &vop_symlink_desc, (VOPFUNC)portal_symlink }, /* symlink */
764 { &vop_readdir_desc, (VOPFUNC)portal_readdir }, /* readdir */
765 { &vop_readlink_desc, (VOPFUNC)portal_readlink }, /* readlink */
766 { &vop_abortop_desc, (VOPFUNC)portal_abortop }, /* abortop */
767 { &vop_inactive_desc, (VOPFUNC)portal_inactive }, /* inactive */
768 { &vop_reclaim_desc, (VOPFUNC)portal_reclaim }, /* reclaim */
769 { &vop_lock_desc, (VOPFUNC)portal_lock }, /* lock */
770 { &vop_unlock_desc, (VOPFUNC)portal_unlock }, /* unlock */
771 { &vop_bmap_desc, (VOPFUNC)portal_bmap }, /* bmap */
772 { &vop_strategy_desc, (VOPFUNC)portal_strategy }, /* strategy */
773 { &vop_print_desc, (VOPFUNC)portal_print }, /* print */
774 { &vop_islocked_desc, (VOPFUNC)portal_islocked }, /* islocked */
775 { &vop_pathconf_desc, (VOPFUNC)portal_pathconf }, /* pathconf */
776 { &vop_advlock_desc, (VOPFUNC)portal_advlock }, /* advlock */
777 { &vop_blkatoff_desc, (VOPFUNC)portal_blkatoff }, /* blkatoff */
778 { &vop_valloc_desc, (VOPFUNC)portal_valloc }, /* valloc */
779 { &vop_vfree_desc, (VOPFUNC)portal_vfree }, /* vfree */
780 { &vop_truncate_desc, (VOPFUNC)portal_truncate }, /* truncate */
781 { &vop_update_desc, (VOPFUNC)portal_update }, /* update */
782 { &vop_bwrite_desc, (VOPFUNC)portal_bwrite }, /* bwrite */
783 { &vop_pagein_desc, (VOPFUNC)err_pagein }, /* Pagein */
784 { &vop_pageout_desc, (VOPFUNC)err_pageout }, /* Pageout */
785 { &vop_copyfile_desc, (VOPFUNC)portal_copyfile }, /* Copyfile */
786 { &vop_blktooff_desc, (VOPFUNC)portal_blktooff }, /* blktooff */
787 { &vop_blktooff_desc, (VOPFUNC)portal_offtoblk }, /* offtoblk */
788 { &vop_cmap_desc, (VOPFUNC)portal_cmap }, /* cmap */
789 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
790 };
791 struct vnodeopv_desc portal_vnodeop_opv_desc =
792 { &portal_vnodeop_p, portal_vnodeop_entries };