summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>1997-01-02 12:20:44 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>1997-01-02 12:20:44 +0000
commit134b6f71c5753849936741021d4f62f7e3f4c93e (patch)
tree54d90227e9dd9d19ffd2d6a07c80e07ef239008a
parent13cf37ba87ea1676f902dcedac95e8b9fa901cb6 (diff)
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 <paul@pgoyette.bdt.com>)
-rw-r--r--sys/compat/common/vfs_syscalls_43.c63
-rw-r--r--sys/kern/vfs_syscalls.c63
-rw-r--r--sys/miscfs/union/union_subr.c63
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 $ */
/*
@@ -70,6 +70,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.
*/
static void
@@ -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 $ */
/*
@@ -69,6 +69,17 @@ 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