From 24d9dce33d3d1643866885d9d465ec0d818f927c Mon Sep 17 00:00:00 2001 From: mickey Date: Thu, 2 Jan 1997 12:20:40 +0000 Subject: [PATCH] pulled out the duplicated, conditional code from both kern/vfs_syscalls.c and compat/common/vfs_syscalls_43.c and placed a single copy of that code into miscfs/union/union_subr.c (seemed like a good place to put it, since it's union-fs related). as a side effect you can build unionfs in lkm. (netbsd pr#2950, Paul Goyette ) --- sys/compat/common/vfs_syscalls_43.c | 63 +++++++++-------------------- sys/kern/vfs_syscalls.c | 63 +++++++++-------------------- sys/miscfs/union/union_subr.c | 63 ++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 91 deletions(-) diff --git a/sys/compat/common/vfs_syscalls_43.c b/sys/compat/common/vfs_syscalls_43.c index e111dec6001..d41f44c457d 100644 --- a/sys/compat/common/vfs_syscalls_43.c +++ b/sys/compat/common/vfs_syscalls_43.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls_43.c,v 1.3 1996/09/06 10:37:48 niklas Exp $ */ +/* $OpenBSD: vfs_syscalls_43.c,v 1.4 1997/01/02 12:20:42 mickey Exp $ */ /* $NetBSD: vfs_syscalls_43.c,v 1.4 1996/03/14 19:31:52 christos Exp $ */ /* @@ -69,6 +69,17 @@ static void cvtstat __P((struct stat *, struct ostat *)); +/* + * Redirection info so we don't have to include the union fs routines in + * the kernel directly. This way, we can build unionfs as an LKM. The + * pointer gets replaced later, when we modload the LKM, or when the + * compiled-in unionfs code gets initialized. Initial, stub routine + * value is compiled in from kern/vfs_syscalls.c + */ + +extern int (*union_check_p) __P((struct proc *, struct vnode **, + struct file *, struct uio, int *)); + /* * Convert from an old to a new stat structure. */ @@ -380,7 +391,7 @@ compat_43_sys_getdirentries(p, v, retval) syscallarg(u_int) count; syscallarg(long *) basep; } */ *uap = v; - register struct vnode *vp; + struct vnode *vp; struct file *fp; struct uio auio, kuio; struct iovec aiov, kiov; @@ -461,50 +472,12 @@ unionread: VOP_UNLOCK(vp); if (error) return (error); - -#ifdef UNION -{ - extern int (**union_vnodeop_p) __P((void *)); - extern struct vnode *union_dircache __P((struct vnode *)); - if ((SCARG(uap, count) == auio.uio_resid) && - (vp->v_op == union_vnodeop_p)) { - struct vnode *lvp; - - lvp = union_dircache(vp); - if (lvp != NULLVP) { - struct vattr va; - - /* - * If the directory is opaque, - * then don't show lower entries - */ - error = VOP_GETATTR(vp, &va, fp->f_cred, p); - if (va.va_flags & OPAQUE) { - vput(lvp); - lvp = NULL; - } - } - - if (lvp != NULLVP) { - error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); - VOP_UNLOCK(lvp); - - if (error) { - vrele(lvp); - return (error); - } - fp->f_data = (caddr_t) lvp; - fp->f_offset = 0; - error = vn_close(vp, FREAD, fp->f_cred, p); - if (error) - return (error); - vp = lvp; - goto unionread; - } - } -} -#endif /* UNION */ + union_check_p && + (union_check_p(p, &vp, fp, auio, &error) != 0)) + goto unionread; + if (error) + return (error); if ((SCARG(uap, count) == auio.uio_resid) && (vp->v_flag & VROOT) && diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 8598b025358..e377f948272 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.17 1996/10/27 08:02:32 tholo Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.18 1997/01/02 12:20:40 mickey Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -68,6 +68,17 @@ static int change_dir __P((struct nameidata *, struct proc *)); void checkdirs __P((struct vnode *)); int dounmount __P((struct mount *, int, struct proc *)); +/* + * Redirection info so we don't have to include the union fs routines in + * the kernel directly. This way, we can build unionfs as an LKM. The + * pointer gets filled in later, when we modload the LKM, or when the + * compiled-in unionfs code gets initialized. For now, we just set + * it to a stub routine. + */ + +int (*union_check_p) __P((struct proc *, struct vnode **, + struct file *, struct uio, int *)) = NULL; + /* * Virtual File System System Calls */ @@ -1992,7 +2003,7 @@ sys_getdirentries(p, v, retval) syscallarg(u_int) count; syscallarg(long *) basep; } */ *uap = v; - register struct vnode *vp; + struct vnode *vp; struct file *fp; struct uio auio; struct iovec aiov; @@ -2022,50 +2033,12 @@ unionread: VOP_UNLOCK(vp); if (error) return (error); - -#ifdef UNION -{ - extern int (**union_vnodeop_p) __P((void *)); - extern struct vnode *union_dircache __P((struct vnode *)); - if ((SCARG(uap, count) == auio.uio_resid) && - (vp->v_op == union_vnodeop_p)) { - struct vnode *lvp; - - lvp = union_dircache(vp); - if (lvp != NULLVP) { - struct vattr va; - - /* - * If the directory is opaque, - * then don't show lower entries - */ - error = VOP_GETATTR(vp, &va, fp->f_cred, p); - if (va.va_flags & OPAQUE) { - vput(lvp); - lvp = NULL; - } - } - - if (lvp != NULLVP) { - error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); - VOP_UNLOCK(lvp); - - if (error) { - vrele(lvp); - return (error); - } - fp->f_data = (caddr_t) lvp; - fp->f_offset = 0; - error = vn_close(vp, FREAD, fp->f_cred, p); - if (error) - return (error); - vp = lvp; - goto unionread; - } - } -} -#endif /* UNION */ + union_check_p && + (union_check_p(p, &vp, fp, auio, &error) != 0)) + goto unionread; + if (error) + return (error); if ((SCARG(uap, count) == auio.uio_resid) && (vp->v_flag & VROOT) && diff --git a/sys/miscfs/union/union_subr.c b/sys/miscfs/union/union_subr.c index 408de9951e2..546c1958e2f 100644 --- a/sys/miscfs/union/union_subr.c +++ b/sys/miscfs/union/union_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: union_subr.c,v 1.3 1996/12/07 13:00:16 deraadt Exp $ */ +/* $OpenBSD: union_subr.c,v 1.4 1997/01/02 12:20:43 mickey Exp $ */ /* $NetBSD: union_subr.c,v 1.18 1996/02/09 22:41:10 christos Exp $ */ /* @@ -80,6 +80,66 @@ int union_vn_close __P((struct vnode *, int, struct ucred *, struct proc *)); static void union_dircache_r __P((struct vnode *, struct vnode ***, int *)); struct vnode *union_dircache __P((struct vnode *)); +/* + * This variable is used to hold a pointer to a function + * that is called from vfs_syscalls.c and vfs_syscalls_43.c + * - by keeping a pointer to the function we enable the real + * union filesystem code to replace the stub value provided + * by vfs_syscalls.c and thus vfs_syscalls.c no longer needs + * to know if UNION is built in, lkm'ed, or not even there. + */ +extern +int (*union_check_p) __P((struct proc *, struct vnode **, + struct file *, struct uio, int *)); + +int union_check(struct proc *, struct vnode **, struct file *, + struct uio, int *); + +int union_check(p, vpp, fp, auio, error) + struct proc *p; + struct vnode **vpp; + struct file *fp; + struct uio auio; + int *error; +{ + if ((*vpp)->v_op == union_vnodeop_p) { + struct vnode *lvp; + + lvp = union_dircache(*vpp); + if (lvp != NULLVP) { + struct vattr va; + + /* + * If the directory is opaque, + * then don't show lower entries + */ + *error = VOP_GETATTR(*vpp, &va, fp->f_cred, p); + if (va.va_flags & OPAQUE) { + vput(lvp); + lvp = NULL; + } + } + + if (lvp != NULLVP) { + *error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); + VOP_UNLOCK(lvp); + + if (*error) { + vrele(lvp); + return (0); + } + fp->f_data = (caddr_t) lvp; + fp->f_offset = 0; + *error = vn_close(*vpp, FREAD, fp->f_cred, p); + if (*error) + return (0); + *vpp = lvp; + return (1); + } + } + return (0); +}; + void union_init() { @@ -88,6 +148,7 @@ union_init() for (i = 0; i < NHASH; i++) LIST_INIT(&unhead[i]); bzero((caddr_t) unvplock, sizeof(unvplock)); + union_check_p = union_check; } static int -- 2.20.1