pulled out the duplicated, conditional code from both kern/vfs_syscalls.c
authormickey <mickey@openbsd.org>
Thu, 2 Jan 1997 12:20:40 +0000 (12:20 +0000)
committermickey <mickey@openbsd.org>
Thu, 2 Jan 1997 12:20:40 +0000 (12:20 +0000)
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 <paul@pgoyette.bdt.com>)

sys/compat/common/vfs_syscalls_43.c
sys/kern/vfs_syscalls.c
sys/miscfs/union/union_subr.c

index e111dec..d41f44c 100644 (file)
@@ -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 $     */
 
 /*
 
 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) &&
index 8598b02..e377f94 100644 (file)
@@ -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) &&
index 408de99..546c195 100644 (file)
@@ -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