1*53846Spendry /*
2*53846Spendry  * Copyright (c) 1992 The Regents of the University of California
3*53846Spendry  * Copyright (c) 1990, 1992 Jan-Simon Pendry
4*53846Spendry  * All rights reserved.
5*53846Spendry  *
6*53846Spendry  * This code is derived from software donated to Berkeley by
7*53846Spendry  * Jan-Simon Pendry.
8*53846Spendry  *
9*53846Spendry  * %sccs.include.redist.c%
10*53846Spendry  *
11*53846Spendry  *	@(#)portal_vnops.c	1.1 (Berkeley) 06/03/92
12*53846Spendry  *
13*53846Spendry  * $Id: portal_vnops.c,v 1.4 1992/05/30 10:05:24 jsp Exp jsp $
14*53846Spendry  */
15*53846Spendry 
16*53846Spendry /*
17*53846Spendry  * Portal Filesystem
18*53846Spendry  */
19*53846Spendry 
20*53846Spendry #include <sys/param.h>
21*53846Spendry #include <sys/systm.h>
22*53846Spendry #include <sys/kernel.h>
23*53846Spendry #include <sys/types.h>
24*53846Spendry #include <sys/time.h>
25*53846Spendry #include <sys/proc.h>
26*53846Spendry /*#include <sys/resourcevar.h>*/
27*53846Spendry #include <sys/filedesc.h>
28*53846Spendry #include <sys/vnode.h>
29*53846Spendry #include <sys/file.h>
30*53846Spendry #include <sys/stat.h>
31*53846Spendry #include <sys/mount.h>
32*53846Spendry #include <sys/malloc.h>
33*53846Spendry #include <sys/namei.h>
34*53846Spendry /*#include <sys/buf.h>*/
35*53846Spendry #include <sys/mbuf.h>
36*53846Spendry #include <sys/socket.h>
37*53846Spendry #include <sys/socketvar.h>
38*53846Spendry #include <sys/un.h>
39*53846Spendry #include <sys/unpcb.h>
40*53846Spendry #include <portal/portal.h>
41*53846Spendry 
42*53846Spendry static int portal_fileid = PORTAL_ROOTFILEID+1;
43*53846Spendry 
44*53846Spendry static void
45*53846Spendry portal_closefd(p, fd)
46*53846Spendry 	struct proc *p;
47*53846Spendry 	int fd;
48*53846Spendry {
49*53846Spendry 	int error;
50*53846Spendry 	struct {
51*53846Spendry 		int fd;
52*53846Spendry 	} ua;
53*53846Spendry 	int rc;
54*53846Spendry 
55*53846Spendry 	ua.fd = fd;
56*53846Spendry 	error = close(p, &ua, &rc);
57*53846Spendry 	/*
58*53846Spendry 	 * We should never get an error, and there isn't anything
59*53846Spendry 	 * we could do if we got one, so just print a message.
60*53846Spendry 	 */
61*53846Spendry 	if (error)
62*53846Spendry 		printf("portal_closefd: error = %d\n", error);
63*53846Spendry }
64*53846Spendry 
65*53846Spendry /*
66*53846Spendry  * vp is the current namei directory
67*53846Spendry  * cnp is the name to locate in that directory...
68*53846Spendry  */
69*53846Spendry portal_lookup (ap)
70*53846Spendry 	struct vop_lookup_args *ap;
71*53846Spendry {
72*53846Spendry 	/*USES_VOP_LOCK;*/
73*53846Spendry 	char *pname = ap->a_cnp->cn_nameptr;
74*53846Spendry 	struct portalnode *pt;
75*53846Spendry 	int error;
76*53846Spendry 	struct vnode *fvp = 0;
77*53846Spendry 	char *path;
78*53846Spendry 	int size;
79*53846Spendry 
80*53846Spendry #ifdef PORTAL_DIAGNOSTIC
81*53846Spendry 	printf("portal_lookup(%s)\n", pname);
82*53846Spendry #endif
83*53846Spendry 	if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
84*53846Spendry 		*ap->a_vpp = ap->a_dvp;
85*53846Spendry 		VREF(ap->a_dvp);
86*53846Spendry 		/*VOP_LOCK(ap->a_dvp);*/
87*53846Spendry 		return (0);
88*53846Spendry 	}
89*53846Spendry 
90*53846Spendry 
91*53846Spendry #ifdef PORTAL_DIAGNOSTIC
92*53846Spendry 	printf("portal_lookup: allocate new vnode\n");
93*53846Spendry #endif
94*53846Spendry 	error = getnewvnode(VT_UFS, ap->a_dvp->v_mount, portal_vnodeop_p, &fvp);
95*53846Spendry 	if (error)
96*53846Spendry 		goto bad;
97*53846Spendry 	fvp->v_type = VREG;
98*53846Spendry 	MALLOC(fvp->v_data, void *, sizeof(struct portalnode),
99*53846Spendry 		M_TEMP, M_WAITOK);
100*53846Spendry 
101*53846Spendry 	pt = VTOPORTAL(fvp);
102*53846Spendry 	/*
103*53846Spendry 	 * Save all of the remaining pathname and
104*53846Spendry 	 * advance the namei next pointer to the end
105*53846Spendry 	 * of the string.
106*53846Spendry 	 */
107*53846Spendry #ifdef notyet
108*53846Spendry 	for (size = 0, path = pname; *path; path++)
109*53846Spendry 		size++;
110*53846Spendry 	ndp->ni_next = path;
111*53846Spendry 	ndp->ni_pathlen -= size - ndp->ni_namelen;
112*53846Spendry #endif
113*53846Spendry 	pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK);
114*53846Spendry 	pt->pt_size = size+1;
115*53846Spendry 	bcopy(pname, pt->pt_arg, pt->pt_size);
116*53846Spendry 	pt->pt_fileid = portal_fileid++;
117*53846Spendry 
118*53846Spendry 	*ap->a_vpp = fvp;
119*53846Spendry 	/*VOP_LOCK(fvp);*/
120*53846Spendry #ifdef PORTAL_DIAGNOSTIC
121*53846Spendry 	printf("portal_lookup: newvp = %x\n", fvp);
122*53846Spendry #endif
123*53846Spendry 	return (0);
124*53846Spendry 
125*53846Spendry bad:;
126*53846Spendry 	if (fvp) {
127*53846Spendry #ifdef PORTAL_DIAGNOSTIC
128*53846Spendry 		printf("portal_lookup: vrele(%x)\n", fvp);
129*53846Spendry #endif
130*53846Spendry 		vrele(fvp);
131*53846Spendry 	}
132*53846Spendry 	*ap->a_vpp = NULL;
133*53846Spendry #ifdef PORTAL_DIAGNOSTIC
134*53846Spendry 	printf("portal_lookup: error = %d\n", error);
135*53846Spendry #endif
136*53846Spendry 	return (error);
137*53846Spendry }
138*53846Spendry 
139*53846Spendry static int
140*53846Spendry portal_connect(so, so2)
141*53846Spendry 	struct socket *so;
142*53846Spendry 	struct socket *so2;
143*53846Spendry {
144*53846Spendry 	/* from unp_connect, bypassing the namei stuff... */
145*53846Spendry 
146*53846Spendry 	struct socket *so3;
147*53846Spendry 	struct unpcb *unp2;
148*53846Spendry 	struct unpcb *unp3;
149*53846Spendry 
150*53846Spendry #ifdef PORTAL_DIAGNOSTIC
151*53846Spendry 	printf("portal_connect\n");
152*53846Spendry #endif
153*53846Spendry 
154*53846Spendry 	if (so2 == 0)
155*53846Spendry 		return (ECONNREFUSED);
156*53846Spendry 
157*53846Spendry 	if (so->so_type != so2->so_type)
158*53846Spendry 		return (EPROTOTYPE);
159*53846Spendry 
160*53846Spendry 	if ((so2->so_options & SO_ACCEPTCONN) == 0)
161*53846Spendry 		return (ECONNREFUSED);
162*53846Spendry 
163*53846Spendry #ifdef PORTAL_DIAGNOSTIC
164*53846Spendry 	printf("portal_connect: calling sonewconn\n");
165*53846Spendry #endif
166*53846Spendry 
167*53846Spendry 	if ((so3 = sonewconn(so2, 0)) == 0)
168*53846Spendry 		return (ECONNREFUSED);
169*53846Spendry 
170*53846Spendry 	unp2 = sotounpcb(so2);
171*53846Spendry 	unp3 = sotounpcb(so3);
172*53846Spendry 	if (unp2->unp_addr)
173*53846Spendry 		unp3->unp_addr = m_copy(unp2->unp_addr, 0, (int)M_COPYALL);
174*53846Spendry 
175*53846Spendry 	so2 = so3;
176*53846Spendry 
177*53846Spendry #ifdef PORTAL_DIAGNOSTIC
178*53846Spendry 	printf("portal_connect: calling unp_connect2\n");
179*53846Spendry #endif
180*53846Spendry 
181*53846Spendry 	return (unp_connect2(so, so2));
182*53846Spendry }
183*53846Spendry 
184*53846Spendry portal_open (ap)
185*53846Spendry 	struct vop_open_args *ap;
186*53846Spendry {
187*53846Spendry 	struct socket *so = 0;
188*53846Spendry 	struct portalnode *pt;
189*53846Spendry 	int s;
190*53846Spendry 	struct uio auio;
191*53846Spendry 	struct iovec aiov[2];
192*53846Spendry 	int res;
193*53846Spendry 	struct mbuf *cm = 0;
194*53846Spendry 	struct cmsghdr *cmsg;
195*53846Spendry 	int newfds;
196*53846Spendry 	int *ip;
197*53846Spendry 	int fd;
198*53846Spendry 	int error;
199*53846Spendry 	int len;
200*53846Spendry 	struct portalmount *fmp;
201*53846Spendry 	struct file *fp;
202*53846Spendry 	struct portal_cred pcred;
203*53846Spendry 
204*53846Spendry 	/*
205*53846Spendry 	 * Nothing to do when opening the root node.
206*53846Spendry 	 */
207*53846Spendry 	if (ap->a_vp->v_flag & VROOT)
208*53846Spendry 		return (0);
209*53846Spendry 
210*53846Spendry #ifdef PORTAL_DIAGNOSTIC
211*53846Spendry 	printf("portal_open(%x)\n", ap->a_vp);
212*53846Spendry #endif
213*53846Spendry 
214*53846Spendry 	/*
215*53846Spendry 	 * Can't be opened unless the caller is set up
216*53846Spendry 	 * to deal with the side effects.  Check for this
217*53846Spendry 	 * by testing whether the p_dupfd has been set.
218*53846Spendry 	 */
219*53846Spendry 	if (ap->a_p->p_dupfd >= 0)
220*53846Spendry 		return (ENODEV);
221*53846Spendry 
222*53846Spendry 	pt = VTOPORTAL(ap->a_vp);
223*53846Spendry 	fmp = VFSTOPORTAL(ap->a_vp->v_mount);
224*53846Spendry 
225*53846Spendry 	/*
226*53846Spendry 	 * Create a new socket.
227*53846Spendry 	 */
228*53846Spendry 	error = socreate(AF_UNIX, &so, SOCK_STREAM, 0);
229*53846Spendry 	if (error)
230*53846Spendry 		goto bad;
231*53846Spendry 
232*53846Spendry 	/*
233*53846Spendry 	 * Reserve some buffer space
234*53846Spendry 	 */
235*53846Spendry #ifdef PORTAL_DIAGNOSTIC
236*53846Spendry 	printf("portal_open: calling soreserve\n");
237*53846Spendry #endif
238*53846Spendry 	res = max(512, pt->pt_size + 128);
239*53846Spendry 	error = soreserve(so, res, res);
240*53846Spendry 	if (error)
241*53846Spendry 		goto bad;
242*53846Spendry 
243*53846Spendry 	/*
244*53846Spendry 	 * Kick off connection
245*53846Spendry 	 */
246*53846Spendry #ifdef PORTAL_DIAGNOSTIC
247*53846Spendry 	printf("portal_open: calling portal_connect\n");
248*53846Spendry #endif
249*53846Spendry 	error = portal_connect(so, (struct socket *)fmp->pm_server->f_data);
250*53846Spendry 	if (error)
251*53846Spendry 		goto bad;
252*53846Spendry 
253*53846Spendry 	/*
254*53846Spendry 	 * Wait for connection to complete
255*53846Spendry 	 */
256*53846Spendry #ifdef PORTAL_DIAGNOSTIC
257*53846Spendry 	printf("portal_open: waiting for connect\n");
258*53846Spendry #endif
259*53846Spendry 	/*
260*53846Spendry 	 * XXX: Since the mount point is holding a reference on the
261*53846Spendry 	 * underlying server socket, it is not easy to find out whether
262*53846Spendry 	 * the server process is still running.  To handle this problem
263*53846Spendry 	 * we loop waiting for the new socket to be connected (something
264*53846Spendry 	 * which will only happen if the server is still running) or for
265*53846Spendry 	 * the reference count on the server socket to drop to 1, which
266*53846Spendry 	 * will happen if the server dies.  Sleep for 5 second intervals
267*53846Spendry 	 * and keep polling the reference count.   XXX.
268*53846Spendry 	 */
269*53846Spendry 	s = splnet();
270*53846Spendry 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
271*53846Spendry 		if (fmp->pm_server->f_count == 1) {
272*53846Spendry 			error = ECONNREFUSED;
273*53846Spendry 			splx(s);
274*53846Spendry #ifdef PORTAL_DIAGNOSTIC
275*53846Spendry 			printf("portal_open: server process has gone away\n");
276*53846Spendry #endif
277*53846Spendry 			goto bad;
278*53846Spendry 		}
279*53846Spendry 		(void) tsleep((caddr_t) &so->so_timeo, PSOCK, "portalcon", 5 * hz);
280*53846Spendry 	}
281*53846Spendry 	splx(s);
282*53846Spendry 
283*53846Spendry 	if (so->so_error) {
284*53846Spendry 		error = so->so_error;
285*53846Spendry 		goto bad;
286*53846Spendry 	}
287*53846Spendry 
288*53846Spendry 	/*
289*53846Spendry 	 * Set miscellaneous flags
290*53846Spendry 	 */
291*53846Spendry 	so->so_rcv.sb_timeo = 0;
292*53846Spendry 	so->so_snd.sb_timeo = 0;
293*53846Spendry 	so->so_rcv.sb_flags |= SB_NOINTR;
294*53846Spendry 	so->so_snd.sb_flags |= SB_NOINTR;
295*53846Spendry 
296*53846Spendry #ifdef PORTAL_DIAGNOSTIC
297*53846Spendry 	printf("portal_open: constructing data uio\n");
298*53846Spendry #endif
299*53846Spendry 
300*53846Spendry 	pcred.pcr_uid = ap->a_cred->cr_uid;
301*53846Spendry 	pcred.pcr_gid = ap->a_cred->cr_gid;
302*53846Spendry 	aiov[0].iov_base = (caddr_t) &pcred;
303*53846Spendry 	aiov[0].iov_len = sizeof(pcred);
304*53846Spendry 	aiov[1].iov_base = pt->pt_arg;
305*53846Spendry 	aiov[1].iov_len = pt->pt_size;
306*53846Spendry 	auio.uio_iov = aiov;
307*53846Spendry 	auio.uio_iovcnt = 2;
308*53846Spendry 	auio.uio_rw = UIO_WRITE;
309*53846Spendry 	auio.uio_segflg = UIO_SYSSPACE;
310*53846Spendry 	auio.uio_procp = ap->a_p;
311*53846Spendry 	auio.uio_offset = 0;
312*53846Spendry 	auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len;
313*53846Spendry 
314*53846Spendry #ifdef PORTAL_DIAGNOSTIC
315*53846Spendry 	printf("portal_open: sending data to server\n");
316*53846Spendry #endif
317*53846Spendry 	error = sosend(so, (struct sockaddr *) 0, &auio,
318*53846Spendry 			(struct mbuf *) 0, (struct mbuf *) 0, 0);
319*53846Spendry 	if (error)
320*53846Spendry 		goto bad;
321*53846Spendry 
322*53846Spendry 	len = auio.uio_resid = sizeof(int);
323*53846Spendry 	do {
324*53846Spendry 		struct mbuf *m = 0;
325*53846Spendry 		int flags = MSG_WAITALL;
326*53846Spendry #ifdef PORTAL_DIAGNOSTIC
327*53846Spendry 		printf("portal_open: receiving data from server\n");
328*53846Spendry 		printf("portal_open: so = %x, cm = %x, resid = %d\n",
329*53846Spendry 				so, cm, auio.uio_resid);
330*53846Spendry 		printf("portal_open, uio=%x, mp0=%x, controlp=%x\n", &auio, &cm);
331*53846Spendry #endif
332*53846Spendry 		error = soreceive(so, (struct mbuf **) 0, &auio,
333*53846Spendry 					&m, &cm, &flags);
334*53846Spendry #ifdef PORTAL_DIAGNOSTIC
335*53846Spendry 		printf("portal_open: after receiving data\n");
336*53846Spendry 		printf("portal_open: so = %x, cm = %x, resid = %d\n",
337*53846Spendry 				so, cm, auio.uio_resid);
338*53846Spendry #endif
339*53846Spendry 		if (error)
340*53846Spendry 			goto bad;
341*53846Spendry 
342*53846Spendry 		/*
343*53846Spendry 		 * Grab an error code from the mbuf.
344*53846Spendry 		 */
345*53846Spendry 		if (m) {
346*53846Spendry 			m = m_pullup(m, sizeof(int));	/* Needed? */
347*53846Spendry 			if (m) {
348*53846Spendry 				error = *(mtod(m, int *));
349*53846Spendry 				m_freem(m);
350*53846Spendry 			} else {
351*53846Spendry 				error = EINVAL;
352*53846Spendry 			}
353*53846Spendry #ifdef PORTAL_DIAGNOSTIC
354*53846Spendry 			printf("portal_open: error returned is %d\n", error);
355*53846Spendry #endif
356*53846Spendry 		} else {
357*53846Spendry 			if (cm == 0) {
358*53846Spendry #ifdef PORTAL_DIAGNOSTIC
359*53846Spendry 				printf("portal_open: no rights received\n");
360*53846Spendry #endif
361*53846Spendry 				error = ECONNRESET;	 /* XXX */
362*53846Spendry #ifdef notdef
363*53846Spendry 				break;
364*53846Spendry #endif
365*53846Spendry 			}
366*53846Spendry 		}
367*53846Spendry 	} while (cm == 0 && auio.uio_resid == len && !error);
368*53846Spendry 
369*53846Spendry 	if (cm == 0)
370*53846Spendry 		goto bad;
371*53846Spendry 
372*53846Spendry 	if (auio.uio_resid) {
373*53846Spendry #ifdef PORTAL_DIAGNOSTIC
374*53846Spendry 		printf("portal_open: still need another %d bytes\n", auio.uio_resid);
375*53846Spendry #endif
376*53846Spendry 		error = 0;
377*53846Spendry #ifdef notdef
378*53846Spendry 		error = EMSGSIZE;
379*53846Spendry 		goto bad;
380*53846Spendry #endif
381*53846Spendry 	}
382*53846Spendry 
383*53846Spendry 	/*
384*53846Spendry 	 * XXX: Break apart the control message, and retrieve the
385*53846Spendry 	 * received file descriptor.  Note that more than one descriptor
386*53846Spendry 	 * may have been received, or that the rights chain may have more
387*53846Spendry 	 * than a single mbuf in it.  What to do?
388*53846Spendry 	 */
389*53846Spendry #ifdef PORTAL_DIAGNOSTIC
390*53846Spendry 	printf("portal_open: about to break apart control message\n");
391*53846Spendry #endif
392*53846Spendry 	cmsg = mtod(cm, struct cmsghdr *);
393*53846Spendry 	newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int);
394*53846Spendry 	if (newfds == 0) {
395*53846Spendry #ifdef PORTAL_DIAGNOSTIC
396*53846Spendry 		printf("portal_open: received no fds\n");
397*53846Spendry #endif
398*53846Spendry 		error = ECONNREFUSED;
399*53846Spendry 		goto bad;
400*53846Spendry 	}
401*53846Spendry 	/*
402*53846Spendry 	 * At this point the rights message consists of a control message
403*53846Spendry 	 * header, followed by a data region containing a vector of
404*53846Spendry 	 * integer file descriptors.  The fds were allocated by the action
405*53846Spendry 	 * of receiving the control message.
406*53846Spendry 	 */
407*53846Spendry 	ip = (int *) (cmsg + 1);
408*53846Spendry 	fd = *ip++;
409*53846Spendry 	if (newfds > 1) {
410*53846Spendry 		/*
411*53846Spendry 		 * Close extra fds.
412*53846Spendry 		 */
413*53846Spendry 		int i;
414*53846Spendry 		printf("portal_open: %d extra fds\n", newfds - 1);
415*53846Spendry 		for (i = 1; i < newfds; i++) {
416*53846Spendry 			portal_closefd(ap->a_p, *ip);
417*53846Spendry 			ip++;
418*53846Spendry 		}
419*53846Spendry 	}
420*53846Spendry 
421*53846Spendry 	/*
422*53846Spendry 	 * Check that the ap->a_mode the file is being opened for is a subset
423*53846Spendry 	 * of the ap->a_mode of the existing descriptor.
424*53846Spendry 	 */
425*53846Spendry #ifdef PORTAL_DIAGNOSTIC
426*53846Spendry 	printf("portal_open: checking file flags, fd = %d\n", fd);
427*53846Spendry #endif
428*53846Spendry  	fp = ap->a_p->p_fd->fd_ofiles[fd];
429*53846Spendry 	if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
430*53846Spendry 		portal_closefd(ap->a_p, fd);
431*53846Spendry 		error = EACCES;
432*53846Spendry 		goto bad;
433*53846Spendry 	}
434*53846Spendry 
435*53846Spendry #ifdef PORTAL_DIAGNOSTIC
436*53846Spendry 	printf("portal_open: got fd = %d\n", fd);
437*53846Spendry #endif
438*53846Spendry 	/*
439*53846Spendry 	 * Save the dup fd in the proc structure then return the
440*53846Spendry 	 * special error code (ENXIO) which causes magic things to
441*53846Spendry 	 * happen in vn_open.  The whole concept is, well, hmmm.
442*53846Spendry 	 */
443*53846Spendry 	ap->a_p->p_dupfd = fd;
444*53846Spendry 	error = ENXIO;
445*53846Spendry 
446*53846Spendry bad:;
447*53846Spendry 	/*
448*53846Spendry 	 * And discard the control message.
449*53846Spendry 	 */
450*53846Spendry 	if (cm) {
451*53846Spendry #ifdef PORTAL_DIAGNOSTIC
452*53846Spendry 		printf("portal_open: free'ing control message\n");
453*53846Spendry #endif
454*53846Spendry 		m_freem(cm);
455*53846Spendry 	}
456*53846Spendry 
457*53846Spendry 	if (so) {
458*53846Spendry #ifdef PORTAL_DIAGNOSTIC
459*53846Spendry 		printf("portal_open: calling soshutdown\n");
460*53846Spendry #endif
461*53846Spendry 		soshutdown(so, 2);
462*53846Spendry #ifdef PORTAL_DIAGNOSTIC
463*53846Spendry 		printf("portal_open: calling soclose\n");
464*53846Spendry #endif
465*53846Spendry 		soclose(so);
466*53846Spendry 	}
467*53846Spendry #ifdef PORTAL_DIAGNOSTIC
468*53846Spendry 	if (error != ENODEV)
469*53846Spendry 		printf("portal_open: error = %d\n", error);
470*53846Spendry #endif
471*53846Spendry 	return (error);
472*53846Spendry }
473*53846Spendry 
474*53846Spendry portal_getattr (ap)
475*53846Spendry 	struct vop_getattr_args *ap;
476*53846Spendry {
477*53846Spendry 	unsigned fd;
478*53846Spendry 	int error;
479*53846Spendry 
480*53846Spendry 	bzero((caddr_t) ap->a_vap, sizeof(*ap->a_vap));
481*53846Spendry 	vattr_null(ap->a_vap);
482*53846Spendry 	ap->a_vap->va_uid = 0;
483*53846Spendry 	ap->a_vap->va_gid = 0;
484*53846Spendry 	ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
485*53846Spendry 	ap->a_vap->va_size = DEV_BSIZE;
486*53846Spendry 	ap->a_vap->va_blocksize = DEV_BSIZE;
487*53846Spendry 	microtime(&ap->a_vap->va_atime);
488*53846Spendry 	ap->a_vap->va_mtime = ap->a_vap->va_atime;
489*53846Spendry 	ap->a_vap->va_ctime = ap->a_vap->va_ctime;
490*53846Spendry 	ap->a_vap->va_gen = 0;
491*53846Spendry 	ap->a_vap->va_flags = 0;
492*53846Spendry 	ap->a_vap->va_rdev = 0;
493*53846Spendry 	/* ap->a_vap->va_qbytes = 0; */
494*53846Spendry 	ap->a_vap->va_bytes = 0;
495*53846Spendry 	/* ap->a_vap->va_qsize = 0; */
496*53846Spendry 	if (ap->a_vp->v_flag & VROOT) {
497*53846Spendry #ifdef PORTAL_DIAGNOSTIC
498*53846Spendry 		printf("portal_getattr: stat rootdir\n");
499*53846Spendry #endif
500*53846Spendry 		ap->a_vap->va_type = VDIR;
501*53846Spendry 		ap->a_vap->va_mode = S_IRUSR|S_IWUSR|S_IXUSR|
502*53846Spendry 				S_IRGRP|S_IWGRP|S_IXGRP|
503*53846Spendry 				S_IROTH|S_IWOTH|S_IXOTH;
504*53846Spendry 		ap->a_vap->va_nlink = 2;
505*53846Spendry 		ap->a_vap->va_fileid = 2;
506*53846Spendry 	} else {
507*53846Spendry #ifdef PORTAL_DIAGNOSTIC
508*53846Spendry 		printf("portal_getattr: stat portal\n");
509*53846Spendry #endif
510*53846Spendry 		ap->a_vap->va_type = VREG;
511*53846Spendry 		ap->a_vap->va_mode = S_IRUSR|S_IWUSR|
512*53846Spendry 				S_IRGRP|S_IWGRP|
513*53846Spendry 				S_IROTH|S_IWOTH;
514*53846Spendry 		ap->a_vap->va_nlink = 1;
515*53846Spendry 		ap->a_vap->va_fileid = VTOPORTAL(ap->a_vp)->pt_fileid;
516*53846Spendry 	}
517*53846Spendry 	return (0);
518*53846Spendry }
519*53846Spendry 
520*53846Spendry portal_setattr (ap)
521*53846Spendry 	struct vop_setattr_args *ap;
522*53846Spendry {
523*53846Spendry 	/*
524*53846Spendry 	 * Can't mess with the root vnode
525*53846Spendry 	 */
526*53846Spendry 	if (ap->a_vp->v_flag & VROOT)
527*53846Spendry 		return (EACCES);
528*53846Spendry 
529*53846Spendry 	return (0);
530*53846Spendry }
531*53846Spendry 
532*53846Spendry /*
533*53846Spendry  * Fake readdir, just return empty directory.
534*53846Spendry  * It is hard to deal with '.' and '..' so don't bother.
535*53846Spendry  */
536*53846Spendry portal_readdir (ap)
537*53846Spendry 	struct vop_readdir_args *ap;
538*53846Spendry {
539*53846Spendry 	*ap->a_eofflagp = 1;
540*53846Spendry 	return (0);
541*53846Spendry }
542*53846Spendry 
543*53846Spendry portal_inactive (ap)
544*53846Spendry 	struct vop_inactive_args *ap;
545*53846Spendry {
546*53846Spendry #ifdef PORTAL_DIAGNOSTIC
547*53846Spendry 	if (VTOPORTAL(ap->a_vp)->pt_arg)
548*53846Spendry 		printf("portal_inactive(%x, %s)\n", ap->a_vp, VTOPORTAL(ap->a_vp)->pt_arg);
549*53846Spendry 	else
550*53846Spendry 		printf("portal_inactive(%x)\n", ap->a_vp);
551*53846Spendry #endif
552*53846Spendry 	/*vgone(ap->a_vp);*/
553*53846Spendry 	return (0);
554*53846Spendry }
555*53846Spendry 
556*53846Spendry portal_reclaim (ap)
557*53846Spendry 	struct vop_reclaim_args *ap;
558*53846Spendry {
559*53846Spendry 	struct portalnode *pt = VTOPORTAL(ap->a_vp);
560*53846Spendry #ifdef PORTAL_DIAGOISTIC
561*53846Spendry 	printf("portal_reclaim(%x)\n", ap->a_vp);
562*53846Spendry #endif
563*53846Spendry 	if (pt->pt_arg) {
564*53846Spendry 		free((caddr_t) pt->pt_arg, M_TEMP);
565*53846Spendry 		pt->pt_arg = 0;
566*53846Spendry 	}
567*53846Spendry 	FREE(pt, M_TEMP);
568*53846Spendry 	return (0);
569*53846Spendry }
570*53846Spendry 
571*53846Spendry /*
572*53846Spendry  * Print out the contents of a Portal vnode.
573*53846Spendry  */
574*53846Spendry /* ARGSUSED */
575*53846Spendry portal_print (ap)
576*53846Spendry 	struct vop_print_args *ap;
577*53846Spendry {
578*53846Spendry 	printf("tag VT_PORTAL, portal vnode\n");
579*53846Spendry }
580*53846Spendry 
581*53846Spendry /*void*/
582*53846Spendry portal_vfree (ap)
583*53846Spendry 	struct vop_vfree_args *ap;
584*53846Spendry {
585*53846Spendry 	return;
586*53846Spendry }
587*53846Spendry 
588*53846Spendry 
589*53846Spendry /*
590*53846Spendry  * Portal vnode unsupported operation
591*53846Spendry  */
592*53846Spendry portal_enotsupp()
593*53846Spendry {
594*53846Spendry 	return (EOPNOTSUPP);
595*53846Spendry }
596*53846Spendry 
597*53846Spendry /*
598*53846Spendry  * Portal "should never get here" operation
599*53846Spendry  */
600*53846Spendry portal_badop()
601*53846Spendry {
602*53846Spendry 	panic("portal: bad op");
603*53846Spendry 	/* NOTREACHED */
604*53846Spendry }
605*53846Spendry 
606*53846Spendry /*
607*53846Spendry  * Portal vnode null operation
608*53846Spendry  */
609*53846Spendry portal_nullop()
610*53846Spendry {
611*53846Spendry 	return (0);
612*53846Spendry }
613*53846Spendry 
614*53846Spendry #define portal_create ((int (*) __P((struct  vop_create_args *)))portal_enotsupp)
615*53846Spendry #define portal_mknod ((int (*) __P((struct  vop_mknod_args *)))portal_enotsupp)
616*53846Spendry #define portal_close ((int (*) __P((struct  vop_close_args *)))nullop)
617*53846Spendry #define portal_access ((int (*) __P((struct  vop_access_args *)))nullop)
618*53846Spendry #define portal_read ((int (*) __P((struct  vop_read_args *)))portal_enotsupp)
619*53846Spendry #define portal_write ((int (*) __P((struct  vop_write_args *)))portal_enotsupp)
620*53846Spendry #define portal_ioctl ((int (*) __P((struct  vop_ioctl_args *)))portal_enotsupp)
621*53846Spendry #define portal_select ((int (*) __P((struct  vop_select_args *)))portal_enotsupp)
622*53846Spendry #define portal_mmap ((int (*) __P((struct  vop_mmap_args *)))portal_enotsupp)
623*53846Spendry #define portal_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
624*53846Spendry #define portal_seek ((int (*) __P((struct  vop_seek_args *)))nullop)
625*53846Spendry #define portal_remove ((int (*) __P((struct  vop_remove_args *)))portal_enotsupp)
626*53846Spendry #define portal_link ((int (*) __P((struct  vop_link_args *)))portal_enotsupp)
627*53846Spendry #define portal_rename ((int (*) __P((struct  vop_rename_args *)))portal_enotsupp)
628*53846Spendry #define portal_mkdir ((int (*) __P((struct  vop_mkdir_args *)))portal_enotsupp)
629*53846Spendry #define portal_rmdir ((int (*) __P((struct  vop_rmdir_args *)))portal_enotsupp)
630*53846Spendry #define portal_symlink ((int (*) __P((struct  vop_symlink_args *)))portal_enotsupp)
631*53846Spendry #define portal_readlink ((int (*) __P((struct  vop_readlink_args *)))portal_enotsupp)
632*53846Spendry #define portal_abortop ((int (*) __P((struct  vop_abortop_args *)))nullop)
633*53846Spendry #define portal_lock ((int (*) __P((struct  vop_lock_args *)))nullop)
634*53846Spendry #define portal_unlock ((int (*) __P((struct  vop_unlock_args *)))nullop)
635*53846Spendry #define portal_bmap ((int (*) __P((struct  vop_bmap_args *)))portal_badop)
636*53846Spendry #define portal_strategy ((int (*) __P((struct  vop_strategy_args *)))portal_badop)
637*53846Spendry #define portal_islocked ((int (*) __P((struct  vop_islocked_args *)))nullop)
638*53846Spendry #define portal_advlock ((int (*) __P((struct  vop_advlock_args *)))portal_enotsupp)
639*53846Spendry #define portal_blkatoff ((int (*) __P((struct  vop_blkatoff_args *)))portal_enotsupp)
640*53846Spendry #define portal_vget ((int (*) __P((struct  vop_vget_args *)))portal_enotsupp)
641*53846Spendry #define portal_valloc ((int(*) __P(( \
642*53846Spendry 		struct vnode *pvp, \
643*53846Spendry 		int mode, \
644*53846Spendry 		struct ucred *cred, \
645*53846Spendry 		struct vnode **vpp))) portal_enotsupp)
646*53846Spendry #define portal_truncate ((int (*) __P((struct  vop_truncate_args *)))portal_enotsupp)
647*53846Spendry #define portal_update ((int (*) __P((struct  vop_update_args *)))portal_enotsupp)
648*53846Spendry #define portal_bwrite ((int (*) __P((struct  vop_bwrite_args *)))portal_enotsupp)
649*53846Spendry 
650*53846Spendry int (**portal_vnodeop_p)();
651*53846Spendry struct vnodeopv_entry_desc portal_vnodeop_entries[] = {
652*53846Spendry 	{ &vop_default_desc, vn_default_error },
653*53846Spendry 	{ &vop_lookup_desc, portal_lookup },		/* lookup */
654*53846Spendry 	{ &vop_create_desc, portal_create },		/* create */
655*53846Spendry 	{ &vop_mknod_desc, portal_mknod },		/* mknod */
656*53846Spendry 	{ &vop_open_desc, portal_open },		/* open */
657*53846Spendry 	{ &vop_close_desc, portal_close },		/* close */
658*53846Spendry 	{ &vop_access_desc, portal_access },		/* access */
659*53846Spendry 	{ &vop_getattr_desc, portal_getattr },		/* getattr */
660*53846Spendry 	{ &vop_setattr_desc, portal_setattr },		/* setattr */
661*53846Spendry 	{ &vop_read_desc, portal_read },		/* read */
662*53846Spendry 	{ &vop_write_desc, portal_write },		/* write */
663*53846Spendry 	{ &vop_ioctl_desc, portal_ioctl },		/* ioctl */
664*53846Spendry 	{ &vop_select_desc, portal_select },		/* select */
665*53846Spendry 	{ &vop_mmap_desc, portal_mmap },		/* mmap */
666*53846Spendry 	{ &vop_fsync_desc, portal_fsync },		/* fsync */
667*53846Spendry 	{ &vop_seek_desc, portal_seek },		/* seek */
668*53846Spendry 	{ &vop_remove_desc, portal_remove },		/* remove */
669*53846Spendry 	{ &vop_link_desc, portal_link },		/* link */
670*53846Spendry 	{ &vop_rename_desc, portal_rename },		/* rename */
671*53846Spendry 	{ &vop_mkdir_desc, portal_mkdir },		/* mkdir */
672*53846Spendry 	{ &vop_rmdir_desc, portal_rmdir },		/* rmdir */
673*53846Spendry 	{ &vop_symlink_desc, portal_symlink },		/* symlink */
674*53846Spendry 	{ &vop_readdir_desc, portal_readdir },		/* readdir */
675*53846Spendry 	{ &vop_readlink_desc, portal_readlink },	/* readlink */
676*53846Spendry 	{ &vop_abortop_desc, portal_abortop },		/* abortop */
677*53846Spendry 	{ &vop_inactive_desc, portal_inactive },	/* inactive */
678*53846Spendry 	{ &vop_reclaim_desc, portal_reclaim },		/* reclaim */
679*53846Spendry 	{ &vop_lock_desc, portal_lock },		/* lock */
680*53846Spendry 	{ &vop_unlock_desc, portal_unlock },		/* unlock */
681*53846Spendry 	{ &vop_bmap_desc, portal_bmap },		/* bmap */
682*53846Spendry 	{ &vop_strategy_desc, portal_strategy },	/* strategy */
683*53846Spendry 	{ &vop_print_desc, portal_print },		/* print */
684*53846Spendry 	{ &vop_islocked_desc, portal_islocked },	/* islocked */
685*53846Spendry 	{ &vop_advlock_desc, portal_advlock },		/* advlock */
686*53846Spendry 	{ &vop_blkatoff_desc, portal_blkatoff },	/* blkatoff */
687*53846Spendry 	{ &vop_vget_desc, portal_vget },		/* vget */
688*53846Spendry 	{ &vop_valloc_desc, portal_valloc },		/* valloc */
689*53846Spendry 	{ &vop_vfree_desc, portal_vfree },		/* vfree */
690*53846Spendry 	{ &vop_truncate_desc, portal_truncate },	/* truncate */
691*53846Spendry 	{ &vop_update_desc, portal_update },		/* update */
692*53846Spendry 	{ &vop_bwrite_desc, portal_bwrite },		/* bwrite */
693*53846Spendry 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
694*53846Spendry };
695*53846Spendry struct vnodeopv_desc portal_vnodeop_opv_desc =
696*53846Spendry 	{ &portal_vnodeop_p, portal_vnodeop_entries };
697