153842Spendry /*
263237Sbostic  * Copyright (c) 1992, 1993
363237Sbostic  *	The Regents of the University of California.  All rights reserved.
453842Spendry  *
553842Spendry  * This code is derived from software donated to Berkeley by
653842Spendry  * Jan-Simon Pendry.
753842Spendry  *
853842Spendry  * %sccs.include.redist.c%
953842Spendry  *
10*65803Sbostic  *	@(#)lofs_vnops.c	8.4 (Berkeley) 01/21/94
1153842Spendry  *
1253842Spendry  * $Id: lofs_vnops.c,v 1.11 1992/05/30 10:05:43 jsp Exp jsp $
1353842Spendry  */
1453842Spendry 
1553842Spendry /*
1653842Spendry  * Loopback Filesystem
1753842Spendry  */
1853842Spendry 
1953842Spendry #include <sys/param.h>
2053842Spendry #include <sys/systm.h>
2153842Spendry #include <sys/proc.h>
2253842Spendry #include <sys/time.h>
2353842Spendry #include <sys/types.h>
2453842Spendry #include <sys/vnode.h>
2553842Spendry #include <sys/mount.h>
2653842Spendry #include <sys/namei.h>
2753842Spendry #include <sys/malloc.h>
2853842Spendry #include <sys/buf.h>
2955022Smckusick #include <miscfs/lofs/lofs.h>
3053842Spendry 
3153842Spendry /*
3253842Spendry  * Basic strategy: as usual, do as little work as possible.
3353842Spendry  * Nothing is ever locked in the lofs'ed filesystem, all
3453842Spendry  * locks are held in the underlying filesystems.
3553842Spendry  */
3653842Spendry 
3753842Spendry /*
3853842Spendry  * Save a vnode and replace with
3953842Spendry  * the lofs'ed one
4053842Spendry  */
4153842Spendry #define PUSHREF(v, nd) \
4253842Spendry { \
4353842Spendry 	struct { struct vnode *vnp; } v; \
4453842Spendry 	v.vnp = (nd); \
4553842Spendry 	(nd) = LOFSVP(v.vnp)
4653842Spendry 
4753842Spendry /*
4853842Spendry  * Undo the PUSHREF
4953842Spendry  */
5053842Spendry #define POP(v, nd) \
5153842Spendry 	\
5253842Spendry 	(nd) = v.vnp; \
5353842Spendry }
5453842Spendry 
5553842Spendry /*
5653842Spendry  * vp is the current namei directory
5753842Spendry  * ndp is the name to locate in that directory...
5853842Spendry  */
5965518Spendry int
lofs_lookup(ap)6055022Smckusick lofs_lookup(ap)
6155022Smckusick 	struct vop_lookup_args /* {
6255022Smckusick 		struct vnode * a_dvp;
6355022Smckusick 		struct vnode ** a_vpp;
6455022Smckusick 		struct componentname * a_cnp;
6555022Smckusick 	} */ *ap;
6653842Spendry {
6754052Spendry 	struct vnode *dvp = ap->a_dvp;
6853842Spendry 	struct vnode *newvp;
6953842Spendry 	struct vnode *targetdvp;
7053842Spendry 	int error;
7153842Spendry 	int flag = ap->a_cnp->cn_nameiop /*& OPMASK*/;
7253842Spendry 
7353842Spendry 	/*
7453842Spendry 	 * (ap->a_dvp) was locked when passed in, and it will be replaced
7553842Spendry 	 * with the target vnode, BUT that will already have been
7653842Spendry 	 * locked when (ap->a_dvp) was locked [see lofs_lock].  all that
7753842Spendry 	 * must be done here is to keep track of reference counts.
7853842Spendry 	 */
7954052Spendry 	targetdvp = LOFSVP(dvp);
8054052Spendry 	/*VREF(targetdvp);*/
8153842Spendry 
8253842Spendry 	/*
8353842Spendry 	 * Call lookup on the looped vnode
8453842Spendry 	 */
8554052Spendry 	error = VOP_LOOKUP(targetdvp, &newvp, ap->a_cnp);
8654052Spendry 	/*vrele(targetdvp);*/
8753842Spendry 
8853842Spendry 	if (error) {
8953842Spendry 		*ap->a_vpp = NULLVP;
9053842Spendry 		return (error);
9153842Spendry 	}
9253842Spendry 
9354052Spendry 	*ap->a_vpp = newvp;
9453842Spendry 
9553842Spendry 	/*
9653842Spendry 	 * If we just found a directory then make
9753842Spendry 	 * a loopback node for it and return the loopback
9853842Spendry 	 * instead of the real vnode.  Otherwise simply
9953842Spendry 	 * return the aliased directory and vnode.
10053842Spendry 	 */
10153842Spendry 	if (newvp && newvp->v_type == VDIR && flag == LOOKUP) {
10253842Spendry 		/*
10353842Spendry 		 * At this point, newvp is the vnode to be looped.
10453842Spendry 		 * Activate a loopback and return the looped vnode.
10553842Spendry 		 */
10654052Spendry 		return (make_lofs(dvp->v_mount, ap->a_vpp));
10753842Spendry 	}
10853842Spendry 
10953842Spendry 	return (0);
11053842Spendry }
11153842Spendry 
11253842Spendry /*
11353842Spendry  * this = ni_dvp
11453842Spendry  * ni_dvp references the locked directory.
11553842Spendry  * ni_vp is NULL.
11653842Spendry  */
11765518Spendry int
lofs_mknod(ap)11855022Smckusick lofs_mknod(ap)
11955022Smckusick 	struct vop_mknod_args /* {
12055022Smckusick 		struct vnode *a_dvp;
12155022Smckusick 		struct vnode **a_vpp;
12255022Smckusick 		struct componentname *a_cnp;
12355022Smckusick 		struct vattr *a_vap;
12455022Smckusick 	} */ *ap;
12553842Spendry {
12653842Spendry 	int error;
12753842Spendry 
12853842Spendry 	PUSHREF(xdvp, ap->a_dvp);
12953842Spendry 	VREF(ap->a_dvp);
13053842Spendry 
13153842Spendry 	error = VOP_MKNOD(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
13253842Spendry 
13353842Spendry 	POP(xdvp, ap->a_dvp);
13453842Spendry 	vrele(ap->a_dvp);
13553842Spendry 
13653842Spendry 	return (error);
13753842Spendry }
13853842Spendry 
13953842Spendry /*
14053842Spendry  * this = ni_dvp;
14153842Spendry  * ni_dvp references the locked directory
14253842Spendry  * ni_vp is NULL.
14353842Spendry  */
14465518Spendry int
lofs_create(ap)14555022Smckusick lofs_create(ap)
14655022Smckusick 	struct vop_create_args /* {
14755022Smckusick 		struct vnode *a_dvp;
14855022Smckusick 		struct vnode **a_vpp;
14955022Smckusick 		struct componentname *a_cnp;
15055022Smckusick 		struct vattr *a_vap;
15155022Smckusick 	} */ *ap;
15253842Spendry {
15353842Spendry 	int error;
15453842Spendry 
15553842Spendry 	PUSHREF(xdvp, ap->a_dvp);
15653842Spendry 	VREF(ap->a_dvp);
15753842Spendry 
15853842Spendry 	error = VOP_CREATE(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
15953842Spendry 
16053842Spendry 	POP(xdvp, ap->a_dvp);
16153842Spendry 	vrele(ap->a_dvp);
16253842Spendry 
16353842Spendry 	return (error);
16453842Spendry }
16553842Spendry 
16665518Spendry int
lofs_open(ap)16755022Smckusick lofs_open(ap)
16855022Smckusick 	struct vop_open_args /* {
16955022Smckusick 		struct vnode *a_vp;
17055022Smckusick 		int  a_mode;
17155022Smckusick 		struct ucred *a_cred;
17255022Smckusick 		struct proc *a_p;
17355022Smckusick 	} */ *ap;
17453842Spendry {
17555022Smckusick 
17665518Spendry 	return (VOP_OPEN(LOFSVP(ap->a_vp), ap->a_mode, ap->a_cred, ap->a_p));
17753842Spendry }
17853842Spendry 
17965518Spendry int
lofs_close(ap)18055022Smckusick lofs_close(ap)
18155022Smckusick 	struct vop_close_args /* {
18255022Smckusick 		struct vnode *a_vp;
18355022Smckusick 		int  a_fflag;
18455022Smckusick 		struct ucred *a_cred;
18555022Smckusick 		struct proc *a_p;
18655022Smckusick 	} */ *ap;
18753842Spendry {
18855022Smckusick 
18965518Spendry 	return (VOP_CLOSE(LOFSVP(ap->a_vp), ap->a_fflag, ap->a_cred, ap->a_p));
19053842Spendry }
19153842Spendry 
19265518Spendry int
lofs_access(ap)19355022Smckusick lofs_access(ap)
19455022Smckusick 	struct vop_access_args /* {
19555022Smckusick 		struct vnode *a_vp;
19655022Smckusick 		int  a_mode;
19755022Smckusick 		struct ucred *a_cred;
19855022Smckusick 		struct proc *a_p;
19955022Smckusick 	} */ *ap;
20053842Spendry {
20155022Smckusick 
20265518Spendry 	return (VOP_ACCESS(LOFSVP(ap->a_vp), ap->a_mode, ap->a_cred, ap->a_p));
20353842Spendry }
20453842Spendry 
20565518Spendry int
lofs_getattr(ap)20655022Smckusick lofs_getattr(ap)
20755022Smckusick 	struct vop_getattr_args /* {
20855022Smckusick 		struct vnode *a_vp;
20955022Smckusick 		struct vattr *a_vap;
21055022Smckusick 		struct ucred *a_cred;
21155022Smckusick 		struct proc *a_p;
21255022Smckusick 	} */ *ap;
21353842Spendry {
21453842Spendry 	int error;
21553842Spendry 
21653842Spendry 	/*
21753842Spendry 	 * Get the stats from the underlying filesystem
21853842Spendry 	 */
21953842Spendry 	error = VOP_GETATTR(LOFSVP(ap->a_vp), ap->a_vap, ap->a_cred, ap->a_p);
22053842Spendry 	if (error)
22153842Spendry 		return (error);
22253842Spendry 	/*
22353842Spendry 	 * and replace the fsid field with the loopback number
22453842Spendry 	 * to preserve the namespace.
22553842Spendry 	 */
22653842Spendry 	ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
22753842Spendry 	return (0);
22853842Spendry }
22953842Spendry 
23065518Spendry int
lofs_setattr(ap)23155022Smckusick lofs_setattr(ap)
23255022Smckusick 	struct vop_setattr_args /* {
23355022Smckusick 		struct vnode *a_vp;
23455022Smckusick 		struct vattr *a_vap;
23555022Smckusick 		struct ucred *a_cred;
23655022Smckusick 		struct proc *a_p;
23755022Smckusick 	} */ *ap;
23853842Spendry {
23955022Smckusick 
24065518Spendry 	return (VOP_SETATTR(LOFSVP(ap->a_vp), ap->a_vap, ap->a_cred, ap->a_p));
24153842Spendry }
24253842Spendry 
24365518Spendry int
lofs_read(ap)24455022Smckusick lofs_read(ap)
24555022Smckusick 	struct vop_read_args /* {
24655022Smckusick 		struct vnode *a_vp;
24755022Smckusick 		struct uio *a_uio;
24855022Smckusick 		int  a_ioflag;
24955022Smckusick 		struct ucred *a_cred;
25055022Smckusick 	} */ *ap;
25153842Spendry {
25255022Smckusick 
25365518Spendry 	return (VOP_READ(LOFSVP(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred));
25453842Spendry }
25553842Spendry 
25665518Spendry int
lofs_write(ap)25755022Smckusick lofs_write(ap)
25855022Smckusick 	struct vop_write_args /* {
25955022Smckusick 		struct vnode *a_vp;
26055022Smckusick 		struct uio *a_uio;
26155022Smckusick 		int  a_ioflag;
26255022Smckusick 		struct ucred *a_cred;
26355022Smckusick 	} */ *ap;
26453842Spendry {
26555022Smckusick 
26665518Spendry 	return (VOP_WRITE(LOFSVP(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred));
26753842Spendry }
26853842Spendry 
26965518Spendry int
lofs_ioctl(ap)27055022Smckusick lofs_ioctl(ap)
27155022Smckusick 	struct vop_ioctl_args /* {
27255022Smckusick 		struct vnode *a_vp;
27355022Smckusick 		int  a_command;
27455022Smckusick 		caddr_t  a_data;
27555022Smckusick 		int  a_fflag;
27655022Smckusick 		struct ucred *a_cred;
27755022Smckusick 		struct proc *a_p;
27855022Smckusick 	} */ *ap;
27953842Spendry {
28055022Smckusick 
28165518Spendry 	return (VOP_IOCTL(LOFSVP(ap->a_vp), ap->a_command, ap->a_data, ap->a_fflag, ap->a_cred, ap->a_p));
28253842Spendry }
28353842Spendry 
28465518Spendry int
lofs_select(ap)28555022Smckusick lofs_select(ap)
28655022Smckusick 	struct vop_select_args /* {
28755022Smckusick 		struct vnode *a_vp;
28855022Smckusick 		int  a_which;
28955022Smckusick 		int  a_fflags;
29055022Smckusick 		struct ucred *a_cred;
29155022Smckusick 		struct proc *a_p;
29255022Smckusick 	} */ *ap;
29353842Spendry {
29455022Smckusick 
29565518Spendry 	return (VOP_SELECT(LOFSVP(ap->a_vp), ap->a_which, ap->a_fflags, ap->a_cred, ap->a_p));
29653842Spendry }
29753842Spendry 
29865518Spendry int
lofs_mmap(ap)29955022Smckusick lofs_mmap(ap)
30055022Smckusick 	struct vop_mmap_args /* {
30155022Smckusick 		struct vnode *a_vp;
30255022Smckusick 		int  a_fflags;
30355022Smckusick 		struct ucred *a_cred;
30455022Smckusick 		struct proc *a_p;
30555022Smckusick 	} */ *ap;
30653842Spendry {
30755022Smckusick 
30865518Spendry 	return (VOP_MMAP(LOFSVP(ap->a_vp), ap->a_fflags, ap->a_cred, ap->a_p));
30953842Spendry }
31053842Spendry 
31165518Spendry int
lofs_fsync(ap)31255022Smckusick lofs_fsync(ap)
31355022Smckusick 	struct vop_fsync_args /* {
31455022Smckusick 		struct vnode *a_vp;
31555022Smckusick 		struct ucred *a_cred;
31655022Smckusick 		int  a_waitfor;
31755022Smckusick 		struct proc *a_p;
31855022Smckusick 	} */ *ap;
31953842Spendry {
32063133Smckusick 	struct vnode *targetvp = LOFSVP(ap->a_vp);
32155022Smckusick 
32263133Smckusick 	if (targetvp)
32365518Spendry 		return (VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, ap->a_p));
32463133Smckusick 	return (0);
32553842Spendry }
32653842Spendry 
32765518Spendry int
lofs_seek(ap)32855022Smckusick lofs_seek(ap)
32955022Smckusick 	struct vop_seek_args /* {
33055022Smckusick 		struct vnode *a_vp;
33155022Smckusick 		off_t  a_oldoff;
33255022Smckusick 		off_t  a_newoff;
33355022Smckusick 		struct ucred *a_cred;
33455022Smckusick 	} */ *ap;
33553842Spendry {
33655022Smckusick 
33765518Spendry 	return (VOP_SEEK(LOFSVP(ap->a_vp), ap->a_oldoff, ap->a_newoff, ap->a_cred));
33853842Spendry }
33953842Spendry 
34065518Spendry int
lofs_remove(ap)34155022Smckusick lofs_remove(ap)
34255022Smckusick 	struct vop_remove_args /* {
34355022Smckusick 		struct vnode *a_dvp;
34455022Smckusick 		struct vnode *a_vp;
34555022Smckusick 		struct componentname *a_cnp;
34655022Smckusick 	} */ *ap;
34753842Spendry {
34853842Spendry 	int error;
34953842Spendry 
35053842Spendry 	PUSHREF(xdvp, ap->a_dvp);
35153842Spendry 	VREF(ap->a_dvp);
35253842Spendry 	PUSHREF(xvp, ap->a_vp);
35353842Spendry 	VREF(ap->a_vp);
35453842Spendry 
35553842Spendry 	error = VOP_REMOVE(ap->a_dvp, ap->a_vp, ap->a_cnp);
35653842Spendry 
35753842Spendry 	POP(xvp, ap->a_vp);
35853842Spendry 	vrele(ap->a_vp);
35953842Spendry 	POP(xdvp, ap->a_dvp);
36053842Spendry 	vrele(ap->a_dvp);
36153842Spendry 
36253842Spendry 	return (error);
36353842Spendry }
36453842Spendry 
36553842Spendry /*
36653842Spendry  * vp is this.
36753842Spendry  * ni_dvp is the locked parent of the target.
36853842Spendry  * ni_vp is NULL.
36953842Spendry  */
37065518Spendry int
lofs_link(ap)37155022Smckusick lofs_link(ap)
37255022Smckusick 	struct vop_link_args /* {
37355022Smckusick 		struct vnode *a_vp;
37455022Smckusick 		struct vnode *a_tdvp;
37555022Smckusick 		struct componentname *a_cnp;
37655022Smckusick 	} */ *ap;
37753842Spendry {
37853842Spendry 	int error;
37953842Spendry 
38053842Spendry 	PUSHREF(xdvp, ap->a_vp);
38153842Spendry 	VREF(ap->a_vp);
38253842Spendry 
38353842Spendry 	error = VOP_LINK(ap->a_vp, LOFSVP(ap->a_tdvp), ap->a_cnp);
38453842Spendry 
38553842Spendry 	POP(xdvp, ap->a_vp);
38653842Spendry 	vrele(ap->a_vp);
38753842Spendry 
38853842Spendry 	return (error);
38953842Spendry }
39053842Spendry 
39165518Spendry int
lofs_rename(ap)39255022Smckusick lofs_rename(ap)
39355022Smckusick 	struct vop_rename_args  /* {
39455022Smckusick 		struct vnode *a_fdvp;
39555022Smckusick 		struct vnode *a_fvp;
39655022Smckusick 		struct componentname *a_fcnp;
39755022Smckusick 		struct vnode *a_tdvp;
39855022Smckusick 		struct vnode *a_tvp;
39955022Smckusick 		struct componentname *a_tcnp;
40055022Smckusick 	} */ *ap;
40153842Spendry {
40253842Spendry 	struct vnode *fvp, *tvp;
40353842Spendry 	struct vnode *tdvp;
40455022Smckusick #ifdef notdef
40553842Spendry 	struct vnode *fsvp, *tsvp;
40653842Spendry #endif
40753842Spendry 	int error;
40853842Spendry 
40953842Spendry 	/*
41053842Spendry 	 * Switch source directory to point to lofsed vnode
41153842Spendry 	 */
41253842Spendry 	PUSHREF(fdvp, ap->a_fdvp);
41353842Spendry 	VREF(ap->a_fdvp);
41453842Spendry 
41553842Spendry 	/*
41653842Spendry 	 * And source object if it is lofsed...
41753842Spendry 	 */
41853842Spendry 	fvp = ap->a_fvp;
41953842Spendry 	if (fvp && fvp->v_op == lofs_vnodeop_p) {
42053842Spendry 		ap->a_fvp = LOFSVP(fvp);
42153842Spendry 		VREF(ap->a_fvp);
42253842Spendry 	} else {
42353842Spendry 		fvp = 0;
42453842Spendry 	}
42553842Spendry 
42655022Smckusick #ifdef notdef
42753842Spendry 	/*
42853842Spendry 	 * And source startdir object if it is lofsed...
42953842Spendry 	 */
43053842Spendry 	fsvp = fndp->ni_startdir;
43153842Spendry 	if (fsvp && fsvp->v_op == lofs_vnodeop_p) {
43253842Spendry 		fndp->ni_startdir = LOFSVP(fsvp);
43353842Spendry 		VREF(fndp->ni_startdir);
43453842Spendry 	} else {
43553842Spendry 		fsvp = 0;
43653842Spendry 	}
43753842Spendry #endif
43853842Spendry 
43953842Spendry 	/*
44053842Spendry  	 * Switch target directory to point to lofsed vnode
44153842Spendry 	 */
44253842Spendry 	tdvp = ap->a_tdvp;
44353842Spendry 	if (tdvp && tdvp->v_op == lofs_vnodeop_p) {
44453842Spendry 		ap->a_tdvp = LOFSVP(tdvp);
44553842Spendry 		VREF(ap->a_tdvp);
44653842Spendry 	} else {
44753842Spendry 		tdvp = 0;
44853842Spendry 	}
44953842Spendry 
45053842Spendry 	/*
45153842Spendry 	 * And target object if it is lofsed...
45253842Spendry 	 */
45353842Spendry 	tvp = ap->a_tvp;
45453842Spendry 	if (tvp && tvp->v_op == lofs_vnodeop_p) {
45553842Spendry 		ap->a_tvp = LOFSVP(tvp);
45653842Spendry 		VREF(ap->a_tvp);
45753842Spendry 	} else {
45853842Spendry 		tvp = 0;
45953842Spendry 	}
46053842Spendry 
46155022Smckusick #ifdef notdef
46253842Spendry 	/*
46353842Spendry 	 * And target startdir object if it is lofsed...
46453842Spendry 	 */
46553842Spendry 	tsvp = tndp->ni_startdir;
46653842Spendry 	if (tsvp && tsvp->v_op == lofs_vnodeop_p) {
46753842Spendry 		tndp->ni_startdir = LOFSVP(fsvp);
46853842Spendry 		VREF(tndp->ni_startdir);
46953842Spendry 	} else {
47053842Spendry 		tsvp = 0;
47153842Spendry 	}
47253842Spendry #endif
47353842Spendry 
47453842Spendry 	error = VOP_RENAME(ap->a_fdvp, ap->a_fvp, ap->a_fcnp, ap->a_tdvp, ap->a_tvp, ap->a_tcnp);
47553842Spendry 
47653842Spendry 	/*
47753842Spendry 	 * Put everything back...
47853842Spendry 	 */
47953842Spendry 
48055022Smckusick #ifdef notdef
48153842Spendry 
48253842Spendry 	if (tsvp) {
48353842Spendry 		if (tndp->ni_startdir)
48453842Spendry 			vrele(tndp->ni_startdir);
48553842Spendry 		tndp->ni_startdir = tsvp;
48653842Spendry 	}
48753842Spendry #endif
48853842Spendry 
48953842Spendry 	if (tvp) {
49053842Spendry 		ap->a_tvp = tvp;
49153842Spendry 		vrele(ap->a_tvp);
49253842Spendry 	}
49353842Spendry 
49453842Spendry 	if (tdvp) {
49553842Spendry 		ap->a_tdvp = tdvp;
49653842Spendry 		vrele(ap->a_tdvp);
49753842Spendry 	}
49853842Spendry 
49955022Smckusick #ifdef notdef
50053842Spendry 
50153842Spendry 	if (fsvp) {
50253842Spendry 		if (fndp->ni_startdir)
50353842Spendry 			vrele(fndp->ni_startdir);
50453842Spendry 		fndp->ni_startdir = fsvp;
50553842Spendry 	}
50653842Spendry #endif
50753842Spendry 
50853842Spendry 	if (fvp) {
50953842Spendry 		ap->a_fvp = fvp;
51053842Spendry 		vrele(ap->a_fvp);
51153842Spendry 	}
51253842Spendry 
51353842Spendry 	POP(fdvp, ap->a_fdvp);
51453842Spendry 	vrele(ap->a_fdvp);
51553842Spendry 
51653842Spendry 	return (error);
51753842Spendry }
51853842Spendry 
51953842Spendry /*
52053842Spendry  * ni_dvp is the locked (alias) parent.
52153842Spendry  * ni_vp is NULL.
52253842Spendry  */
52365518Spendry int
lofs_mkdir(ap)52455022Smckusick lofs_mkdir(ap)
52555022Smckusick 	struct vop_mkdir_args /* {
52655022Smckusick 		struct vnode *a_dvp;
52755022Smckusick 		struct vnode **a_vpp;
52855022Smckusick 		struct componentname *a_cnp;
52955022Smckusick 		struct vattr *a_vap;
53055022Smckusick 	} */ *ap;
53153842Spendry {
53253842Spendry 	int error;
53354052Spendry 	struct vnode *dvp = ap->a_dvp;
53453842Spendry 	struct vnode *xdvp;
53554052Spendry 	struct vnode *newvp;
53653842Spendry 
53754052Spendry 	xdvp = dvp;
53854052Spendry 	dvp = LOFSVP(xdvp);
53955254Spendry 	VREF(dvp);
54053842Spendry 
54154052Spendry 	error = VOP_MKDIR(dvp, &newvp, ap->a_cnp, ap->a_vap);
54253842Spendry 
54353842Spendry 	if (error) {
54454052Spendry 		*ap->a_vpp = NULLVP;
54555254Spendry 		vrele(xdvp);
54653842Spendry 		return (error);
54753842Spendry 	}
54853842Spendry 
54953842Spendry 	/*
55053842Spendry 	 * Make a new lofs node
55153842Spendry 	 */
55254052Spendry 	/*VREF(dvp);*/
55353842Spendry 
55454052Spendry 	error = make_lofs(dvp->v_mount, &newvp);
55553842Spendry 
55654052Spendry 	*ap->a_vpp = newvp;
55753842Spendry 
55853842Spendry 	return (error);
55953842Spendry }
56053842Spendry 
56153842Spendry /*
56253842Spendry  * ni_dvp is the locked parent.
56353842Spendry  * ni_vp is the entry to be removed.
56453842Spendry  */
56565518Spendry int
lofs_rmdir(ap)56655022Smckusick lofs_rmdir(ap)
56755022Smckusick 	struct vop_rmdir_args /* {
56855022Smckusick 		struct vnode *a_dvp;
56955022Smckusick 		struct vnode *a_vp;
57055022Smckusick 		struct componentname *a_cnp;
57155022Smckusick 	} */ *ap;
57253842Spendry {
57354052Spendry 	struct vnode *vp = ap->a_vp;
57454052Spendry 	struct vnode *dvp = ap->a_dvp;
57553842Spendry 	int error;
57653842Spendry 
57754052Spendry 	PUSHREF(xdvp, dvp);
57854052Spendry 	VREF(dvp);
57954052Spendry 	PUSHREF(xvp, vp);
58054052Spendry 	VREF(vp);
58153842Spendry 
58254052Spendry 	error = VOP_RMDIR(dvp, vp, ap->a_cnp);
58353842Spendry 
58454052Spendry 	POP(xvp, vp);
58554052Spendry 	vrele(vp);
58654052Spendry 	POP(xdvp, dvp);
58754052Spendry 	vrele(dvp);
58853842Spendry 
58953842Spendry 	return (error);
59053842Spendry }
59153842Spendry 
59253842Spendry /*
59353842Spendry  * ni_dvp is the locked parent.
59453842Spendry  * ni_vp is NULL.
59553842Spendry  */
59665518Spendry int
lofs_symlink(ap)59755022Smckusick lofs_symlink(ap)
59855022Smckusick 	struct vop_symlink_args /* {
59955022Smckusick 		struct vnode *a_dvp;
60055022Smckusick 		struct vnode **a_vpp;
60155022Smckusick 		struct componentname *a_cnp;
60255022Smckusick 		struct vattr *a_vap;
60355022Smckusick 		char *a_target;
60455022Smckusick 	} */ *ap;
60553842Spendry {
60653842Spendry 	int error;
60753842Spendry 
60853842Spendry 	PUSHREF(xdvp, ap->a_dvp);
60953842Spendry 	VREF(ap->a_dvp);
61053842Spendry 
61153842Spendry 	error = VOP_SYMLINK(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap, ap->a_target);
61253842Spendry 
61353842Spendry 	POP(xdvp, ap->a_dvp);
61453842Spendry 	vrele(ap->a_dvp);
61553842Spendry 
61653842Spendry 	return (error);
61753842Spendry }
61853842Spendry 
61965518Spendry int
lofs_readdir(ap)62055022Smckusick lofs_readdir(ap)
62155022Smckusick 	struct vop_readdir_args /* {
62255022Smckusick 		struct vnode *a_vp;
62355022Smckusick 		struct uio *a_uio;
62455022Smckusick 		struct ucred *a_cred;
62555022Smckusick 	} */ *ap;
62653842Spendry {
62755022Smckusick 
62865518Spendry 	return (VOP_READDIR(LOFSVP(ap->a_vp), ap->a_uio, ap->a_cred));
62953842Spendry }
63053842Spendry 
63165518Spendry int
lofs_readlink(ap)63255022Smckusick lofs_readlink(ap)
63355022Smckusick 	struct vop_readlink_args /* {
63455022Smckusick 		struct vnode *a_vp;
63555022Smckusick 		struct uio *a_uio;
63655022Smckusick 		struct ucred *a_cred;
63755022Smckusick 	} */ *ap;
63853842Spendry {
63955022Smckusick 
64065518Spendry 	return (VOP_READLINK(LOFSVP(ap->a_vp), ap->a_uio, ap->a_cred));
64153842Spendry }
64253842Spendry 
64353842Spendry /*
64453842Spendry  * Anyone's guess...
64553842Spendry  */
64665518Spendry int
lofs_abortop(ap)64755022Smckusick lofs_abortop(ap)
64855022Smckusick 	struct vop_abortop_args /* {
64955022Smckusick 		struct vnode *a_dvp;
65055022Smckusick 		struct componentname *a_cnp;
65155022Smckusick 	} */ *ap;
65253842Spendry {
65353842Spendry 	int error;
65453842Spendry 
65553842Spendry 	PUSHREF(xdvp, ap->a_dvp);
65653842Spendry 
65753842Spendry 	error = VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
65853842Spendry 
65953842Spendry 	POP(xdvp, ap->a_dvp);
66053842Spendry 
66153842Spendry 	return (error);
66253842Spendry }
66353842Spendry 
66465518Spendry int
lofs_inactive(ap)66555022Smckusick lofs_inactive(ap)
66655022Smckusick 	struct vop_inactive_args /* {
66755022Smckusick 		struct vnode *a_vp;
66855022Smckusick 	} */ *ap;
66953842Spendry {
67053842Spendry 	struct vnode *targetvp = LOFSVP(ap->a_vp);
67155022Smckusick 
67253842Spendry #ifdef DIAGNOSTIC
67353842Spendry 	{ extern int prtactive;
67453842Spendry 	if (prtactive && ap->a_vp->v_usecount != 0)
67553842Spendry 		vprint("lofs_inactive: pushing active", ap->a_vp);
67653842Spendry 	}
67753842Spendry #endif
67853842Spendry 
67953842Spendry 	if (targetvp) {
68053842Spendry 		vrele(targetvp);
68153842Spendry 		LOFSP(ap->a_vp)->a_lofsvp = 0;
68253842Spendry 	}
68353842Spendry }
68453842Spendry 
68565518Spendry int
lofs_reclaim(ap)68655022Smckusick lofs_reclaim(ap)
68755022Smckusick 	struct vop_reclaim_args /* {
68855022Smckusick 		struct vnode *a_vp;
68955022Smckusick 	} */ *ap;
69053842Spendry {
69153842Spendry 	struct vnode *targetvp;
69255022Smckusick 
69353842Spendry 	remque(LOFSP(ap->a_vp));
69453842Spendry 	targetvp = LOFSVP(ap->a_vp);
69553842Spendry 	if (targetvp) {
69653842Spendry 		printf("lofs: delayed vrele of %x\n", targetvp);
69753842Spendry 		vrele(targetvp);	/* XXX should never happen */
69853842Spendry 	}
69953842Spendry 	FREE(ap->a_vp->v_data, M_TEMP);
70053842Spendry 	ap->a_vp->v_data = 0;
70153842Spendry 	return (0);
70253842Spendry }
70353842Spendry 
70465518Spendry int
lofs_lock(ap)70555022Smckusick lofs_lock(ap)
70655022Smckusick 	struct vop_lock_args /* {
70755022Smckusick 		struct vnode *a_vp;
70855022Smckusick 	} */ *ap;
70953842Spendry {
71053842Spendry 	int error;
71156807Smckusick 	register struct vnode *vp = ap->a_vp;
71256807Smckusick 	struct vnode *targetvp;
71353842Spendry 
71456807Smckusick 	while (vp->v_flag & VXLOCK) {
71556807Smckusick 		vp->v_flag |= VXWANT;
71656807Smckusick 		sleep((caddr_t)vp, PINOD);
71756807Smckusick 	}
71856807Smckusick 	if (vp->v_tag == VT_NON)
71956807Smckusick 		return (ENOENT);
72056807Smckusick 	targetvp = LOFSVP(ap->a_vp);
72156807Smckusick 
72256807Smckusick 	if (targetvp && (error = VOP_LOCK(targetvp)))
72356807Smckusick 		return (error);
72453842Spendry 	return (0);
72553842Spendry }
72653842Spendry 
72765518Spendry int
lofs_unlock(ap)72855022Smckusick lofs_unlock(ap)
72955022Smckusick 	struct vop_unlock_args /* {
73055022Smckusick 		struct vnode *a_vp;
73155022Smckusick 	} */ *ap;
73253842Spendry {
73353842Spendry 	struct vnode *targetvp = LOFSVP(ap->a_vp);
73453842Spendry 
73553842Spendry 	if (targetvp)
73653842Spendry 		return (VOP_UNLOCK(targetvp));
73753842Spendry 	return (0);
73853842Spendry }
73953842Spendry 
74065518Spendry int
lofs_bmap(ap)74155022Smckusick lofs_bmap(ap)
74255022Smckusick 	struct vop_bmap_args /* {
74355022Smckusick 		struct vnode *a_vp;
74455022Smckusick 		daddr_t  a_bn;
74555022Smckusick 		struct vnode **a_vpp;
74655022Smckusick 		daddr_t *a_bnp;
74756455Smargo 		int *a_runp;
74855022Smckusick 	} */ *ap;
74953842Spendry {
75055022Smckusick 
75165518Spendry 	return (VOP_BMAP(LOFSVP(ap->a_vp), ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp));
75253842Spendry }
75353842Spendry 
75465518Spendry int
lofs_strategy(ap)75555022Smckusick lofs_strategy(ap)
75655022Smckusick 	struct vop_strategy_args /* {
75755022Smckusick 		struct buf *a_bp;
75855022Smckusick 	} */ *ap;
75953842Spendry {
76053842Spendry 	int error;
76153842Spendry 
76253842Spendry 	PUSHREF(vp, ap->a_bp->b_vp);
76353842Spendry 
76453842Spendry 	error = VOP_STRATEGY(ap->a_bp);
76553842Spendry 
76653842Spendry 	POP(vp, ap->a_bp->b_vp);
76753842Spendry 
76853842Spendry 	return (error);
76953842Spendry }
77053842Spendry 
77165518Spendry int
lofs_print(ap)77255022Smckusick lofs_print(ap)
77355022Smckusick 	struct vop_print_args /* {
77455022Smckusick 		struct vnode *a_vp;
77555022Smckusick 	} */ *ap;
77653842Spendry {
77755022Smckusick 
77853842Spendry 	struct vnode *targetvp = LOFSVP(ap->a_vp);
77953842Spendry 	printf("tag VT_LOFS ref ");
78053842Spendry 	if (targetvp)
78153842Spendry 		return (VOP_PRINT(targetvp));
78253842Spendry 	printf("NULLVP\n");
78353842Spendry 	return (0);
78453842Spendry }
78553842Spendry 
78665518Spendry int
lofs_islocked(ap)78755022Smckusick lofs_islocked(ap)
78855022Smckusick 	struct vop_islocked_args /* {
78955022Smckusick 		struct vnode *a_vp;
79055022Smckusick 	} */ *ap;
79153842Spendry {
79255022Smckusick 
79353842Spendry 	struct vnode *targetvp = LOFSVP(ap->a_vp);
79453842Spendry 	if (targetvp)
79553842Spendry 		return (VOP_ISLOCKED(targetvp));
79653842Spendry 	return (0);
79753842Spendry }
79853842Spendry 
79965518Spendry int
lofs_pathconf(ap)80065743Spendry lofs_pathconf(ap)
80165743Spendry 	struct vop_pathconf_args *ap;
80265743Spendry {
80365743Spendry 
80465743Spendry 	return (VOP_PATHCONF(LOFSVP(ap->a_vp), ap->a_name, ap->a_retval));
80565743Spendry }
80665743Spendry 
80765743Spendry int
lofs_advlock(ap)80855022Smckusick lofs_advlock(ap)
80955022Smckusick 	struct vop_advlock_args /* {
81055022Smckusick 		struct vnode *a_vp;
81155022Smckusick 		caddr_t  a_id;
81255022Smckusick 		int  a_op;
81355022Smckusick 		struct flock *a_fl;
81455022Smckusick 		int  a_flags;
81555022Smckusick 	} */ *ap;
81653842Spendry {
81755022Smckusick 
81865518Spendry 	return (VOP_ADVLOCK(LOFSVP(ap->a_vp), ap->a_id, ap->a_op, ap->a_fl, ap->a_flags));
81953842Spendry }
82053842Spendry 
82153842Spendry /*
82253842Spendry  * LOFS directory offset lookup.
82353842Spendry  * Currently unsupported.
82453842Spendry  */
82565518Spendry int
lofs_blkatoff(ap)82655022Smckusick lofs_blkatoff(ap)
82755022Smckusick 	struct vop_blkatoff_args /* {
82855022Smckusick 		struct vnode *a_vp;
82955022Smckusick 		off_t a_offset;
83055022Smckusick 		char **a_res;
83155022Smckusick 		struct buf **a_bpp;
83255022Smckusick 	} */ *ap;
83353842Spendry {
83453842Spendry 
83553842Spendry 	return (EOPNOTSUPP);
83653842Spendry }
83753842Spendry 
83853842Spendry /*
83953842Spendry  * LOFS flat namespace allocation.
84053842Spendry  * Currently unsupported.
84153842Spendry  */
84265518Spendry int
lofs_valloc(ap)84355022Smckusick lofs_valloc(ap)
84455022Smckusick 	struct vop_valloc_args /* {
84555022Smckusick 		struct vnode *a_pvp;
84655022Smckusick 		int a_mode;
84755022Smckusick 		struct ucred *a_cred;
84855022Smckusick 		struct vnode **a_vpp;
84955022Smckusick 	} */ *ap;
85053842Spendry {
85153842Spendry 
85253842Spendry 	return (EOPNOTSUPP);
85353842Spendry }
85453842Spendry 
85553842Spendry /*
85653842Spendry  * LOFS flat namespace free.
85753842Spendry  * Currently unsupported.
85853842Spendry  */
85953842Spendry /*void*/
86065518Spendry int
lofs_vfree(ap)86155022Smckusick lofs_vfree(ap)
86255022Smckusick 	struct vop_vfree_args /* {
86355022Smckusick 		struct vnode *a_pvp;
86455022Smckusick 		ino_t a_ino;
86555022Smckusick 		int a_mode;
86655022Smckusick 	} */ *ap;
86753842Spendry {
86853842Spendry 
86955022Smckusick 	return (0);
87053842Spendry }
87153842Spendry 
87253842Spendry /*
87353842Spendry  * LOFS file truncation.
87453842Spendry  */
87565518Spendry int
lofs_truncate(ap)87655022Smckusick lofs_truncate(ap)
87755022Smckusick 	struct vop_truncate_args /* {
87855022Smckusick 		struct vnode *a_vp;
87955022Smckusick 		off_t a_length;
88055022Smckusick 		int a_flags;
88155022Smckusick 		struct ucred *a_cred;
88255022Smckusick 		struct proc *a_p;
88355022Smckusick 	} */ *ap;
88453842Spendry {
88553842Spendry 
88653842Spendry 	/* Use lofs_setattr */
88753842Spendry 	printf("lofs_truncate: need to implement!!");
88853842Spendry 	return (EOPNOTSUPP);
88953842Spendry }
89053842Spendry 
89153842Spendry /*
89253842Spendry  * LOFS update.
89353842Spendry  */
89465518Spendry int
lofs_update(ap)89555022Smckusick lofs_update(ap)
89655022Smckusick 	struct vop_update_args /* {
89755022Smckusick 		struct vnode *a_vp;
89855022Smckusick 		struct timeval *a_ta;
89955022Smckusick 		struct timeval *a_tm;
90055022Smckusick 		int a_waitfor;
90155022Smckusick 	} */ *ap;
90253842Spendry {
90353842Spendry 
90453842Spendry 	/* Use lofs_setattr */
90553842Spendry 	printf("lofs_update: need to implement!!");
90653842Spendry 	return (EOPNOTSUPP);
90753842Spendry }
90853842Spendry 
90953842Spendry /*
91053842Spendry  * LOFS bwrite
91153842Spendry  */
91265518Spendry int
lofs_bwrite(ap)91355022Smckusick lofs_bwrite(ap)
91455022Smckusick 	struct vop_bwrite_args /* {
91555022Smckusick 		struct buf *a_bp;
91655022Smckusick 	} */ *ap;
91753842Spendry {
91855022Smckusick 
91953842Spendry 	return (EOPNOTSUPP);
92053842Spendry }
92153842Spendry 
92253842Spendry /*
92353842Spendry  * Global vfs data structures for ufs
92453842Spendry  */
92553842Spendry int (**lofs_vnodeop_p)();
92653842Spendry struct vnodeopv_entry_desc lofs_vnodeop_entries[] = {
92753842Spendry 	{ &vop_default_desc, vn_default_error },
92853842Spendry 	{ &vop_lookup_desc, lofs_lookup },		/* lookup */
92953842Spendry 	{ &vop_create_desc, lofs_create },		/* create */
93053842Spendry 	{ &vop_mknod_desc, lofs_mknod },		/* mknod */
93165743Spendry 	{ &vop_open_desc, lofs_open },			/* open */
93253842Spendry 	{ &vop_close_desc, lofs_close },		/* close */
93353842Spendry 	{ &vop_access_desc, lofs_access },		/* access */
93453842Spendry 	{ &vop_getattr_desc, lofs_getattr },		/* getattr */
93553842Spendry 	{ &vop_setattr_desc, lofs_setattr },		/* setattr */
93665743Spendry 	{ &vop_read_desc, lofs_read },			/* read */
93753842Spendry 	{ &vop_write_desc, lofs_write },		/* write */
93853842Spendry 	{ &vop_ioctl_desc, lofs_ioctl },		/* ioctl */
93953842Spendry 	{ &vop_select_desc, lofs_select },		/* select */
94065743Spendry 	{ &vop_mmap_desc, lofs_mmap },			/* mmap */
94153842Spendry 	{ &vop_fsync_desc, lofs_fsync },		/* fsync */
94265743Spendry 	{ &vop_seek_desc, lofs_seek },			/* seek */
94353842Spendry 	{ &vop_remove_desc, lofs_remove },		/* remove */
94465743Spendry 	{ &vop_link_desc, lofs_link },			/* link */
94553842Spendry 	{ &vop_rename_desc, lofs_rename },		/* rename */
94653842Spendry 	{ &vop_mkdir_desc, lofs_mkdir },		/* mkdir */
94753842Spendry 	{ &vop_rmdir_desc, lofs_rmdir },		/* rmdir */
94853842Spendry 	{ &vop_symlink_desc, lofs_symlink },		/* symlink */
94953842Spendry 	{ &vop_readdir_desc, lofs_readdir },		/* readdir */
95053842Spendry 	{ &vop_readlink_desc, lofs_readlink },		/* readlink */
95153842Spendry 	{ &vop_abortop_desc, lofs_abortop },		/* abortop */
95253842Spendry 	{ &vop_inactive_desc, lofs_inactive },		/* inactive */
95353842Spendry 	{ &vop_reclaim_desc, lofs_reclaim },		/* reclaim */
95465743Spendry 	{ &vop_lock_desc, lofs_lock },			/* lock */
95553842Spendry 	{ &vop_unlock_desc, lofs_unlock },		/* unlock */
95665743Spendry 	{ &vop_bmap_desc, lofs_bmap },			/* bmap */
95753842Spendry 	{ &vop_strategy_desc, lofs_strategy },		/* strategy */
95853842Spendry 	{ &vop_print_desc, lofs_print },		/* print */
95953842Spendry 	{ &vop_islocked_desc, lofs_islocked },		/* islocked */
96065743Spendry 	{ &vop_pathconf_desc, lofs_pathconf },		/* pathconf */
96153842Spendry 	{ &vop_advlock_desc, lofs_advlock },		/* advlock */
96253842Spendry 	{ &vop_blkatoff_desc, lofs_blkatoff },		/* blkatoff */
96353842Spendry 	{ &vop_valloc_desc, lofs_valloc },		/* valloc */
96453842Spendry 	{ &vop_vfree_desc, lofs_vfree },		/* vfree */
96553842Spendry 	{ &vop_truncate_desc, lofs_truncate },		/* truncate */
96653842Spendry 	{ &vop_update_desc, lofs_update },		/* update */
96753842Spendry 	{ &vop_bwrite_desc, lofs_bwrite },		/* bwrite */
96853842Spendry 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
96953842Spendry };
97053842Spendry struct vnodeopv_desc lofs_vnodeop_opv_desc =
97153842Spendry 	{ &lofs_vnodeop_p, lofs_vnodeop_entries };
972