kernel: Remove the old unionfs that was unhooked from the build since 2004.
authorSascha Wildner <saw@online.de>
Mon, 21 Dec 2015 20:33:03 +0000 (21:33 +0100)
committerSascha Wildner <saw@online.de>
Mon, 21 Dec 2015 20:33:03 +0000 (21:33 +0100)
Approved-by: dillon
32 files changed:
Makefile_upgrade.inc
contrib/smbfs/mount_smbfs/mntopts.h
include/mntopts.h
lib/libc/sys/chflags.2
lib/libc/sys/undelete.2
sbin/Makefile
sbin/mount/mount.8
sbin/mount/mount.c
sbin/mount_std/mount_std.8
sbin/mount_ufs/mount.c
sbin/mount_ufs/mount_ufs.8
sbin/mount_union/Makefile [deleted file]
sbin/mount_union/mount_union.8 [deleted file]
sbin/mount_union/mount_union.c [deleted file]
sys/conf/files
sys/conf/options
sys/config/LINT64
sys/emulation/43bsd/43bsd_file.c
sys/kern/vfs_subr.c
sys/kern/vfs_syscalls.c
sys/sys/mount.h
sys/vfs/union/Makefile [deleted file]
sys/vfs/union/union.h [deleted file]
sys/vfs/union/union_subr.c [deleted file]
sys/vfs/union/union_vfsops.c [deleted file]
sys/vfs/union/union_vnops.c [deleted file]
test/stress/stress2/misc/all.sh
test/stress/stress2/misc/union.sh [deleted file]
test/stress/stress2/misc/unionfs.sh [deleted file]
test/stress/stress2/misc/unionfs2.sh [deleted file]
test/stress/stress2/misc/unionfs3.sh [deleted file]
usr.sbin/pstat/pstat.c

index e071cf1..b623fb0 100644 (file)
@@ -2264,6 +2264,9 @@ TO_REMOVE+=/usr/include/sys/syslink_vfs.h
 TO_REMOVE+=/usr/share/man/man4/i386
 TO_REMOVE+=/usr/share/man/man8/i386
 TO_REMOVE+=/usr/share/man/man9/i386
+TO_REMOVE+=/boot/kernel/union.ko
+TO_REMOVE+=/sbin/mount_union
+TO_REMOVE+=/usr/share/man/man8/mount_union.8.gz
 
 .if !defined(WANT_INSTALLER)
 TO_REMOVE+=/usr/sbin/dfuibe_installer
index c14b27c..29da868 100644 (file)
@@ -54,7 +54,6 @@ struct mntopt {
 #endif
 #define MOPT_RDONLY            { "rdonly",     0, MNT_RDONLY, 0 }
 #define MOPT_SYNC              { "sync",       0, MNT_SYNCHRONOUS, 0 }
-#define MOPT_UNION             { "union",      0, MNT_UNION, 0 }
 #define MOPT_USERQUOTA         { "userquota",  0, 0, 0 }
 #define MOPT_GROUPQUOTA                { "groupquota", 0, 0, 0 }
 #ifndef APPLE
@@ -100,7 +99,6 @@ struct mntopt {
        MOPT_NOSUID,                                                    \
        MOPT_NOSYMFOLLOW,                                               \
        MOPT_RDONLY,                                                    \
-       MOPT_UNION,                                                     \
        MOPT_NOCLUSTERR,                                                \
        MOPT_NOCLUSTERW
 #endif /* APPLE */
index 8f53008..18d52da 100644 (file)
@@ -56,7 +56,6 @@ struct mntopt {
 #define MOPT_TRIM              { "trim",       0, MNT_TRIM, 0 }
 #define MOPT_RDONLY            { "rdonly",     0, MNT_RDONLY, 0 }
 #define MOPT_SYNC              { "sync",       0, MNT_SYNCHRONOUS, 0 }
-#define MOPT_UNION             { "union",      0, MNT_UNION, 0 }
 #define MOPT_USERQUOTA         { "userquota",  0, 0, 0 }
 #define MOPT_GROUPQUOTA                { "groupquota", 0, 0, 0 }
 #define MOPT_NOCLUSTERR                { "clusterr",   1, MNT_NOCLUSTERR, 0 }
@@ -93,7 +92,6 @@ struct mntopt {
        MOPT_NOSUID,                                                    \
        MOPT_NOSYMFOLLOW,                                               \
        MOPT_RDONLY,                                                    \
-       MOPT_UNION,                                                     \
        MOPT_NOCLUSTERR,                                                \
        MOPT_NOCLUSTERW,                                                \
        MOPT_IGNORE
index 920c6bb..e1cbb96 100644 (file)
@@ -221,7 +221,6 @@ The underlying file system does not support file flags.
 .Xr fflagstostr 3 ,
 .Xr strtofflags 3 ,
 .Xr init 8 ,
-.Xr mount_union 8 ,
 .Xr swapcache 8
 .Sh HISTORY
 The
index 425541a..6bf81a5 100644 (file)
@@ -28,7 +28,6 @@
 .\"
 .\"     @(#)undelete.2 8.4 (Berkeley) 10/18/94
 .\" $FreeBSD: src/lib/libc/sys/undelete.2,v 1.4.2.5 2001/12/14 18:34:02 ru Exp $
-.\" $DragonFly: src/lib/libc/sys/undelete.2,v 1.2 2003/06/17 04:26:47 dillon Exp $
 .\"
 .Dd October 18, 1994
 .Dt UNDELETE 2
@@ -92,8 +91,7 @@ The name resides on a read-only file system.
 points outside the process's allocated address space.
 .El
 .Sh SEE ALSO
-.Xr unlink 2 ,
-.Xr mount_union 8
+.Xr unlink 2
 .Sh HISTORY
 An
 .Fn undelete
index f31bfe5..123e300 100644 (file)
@@ -64,7 +64,6 @@ SUBDIR=       adjkerntz \
        mount_std \
        mount_tmpfs \
        mount_udf \
-       mount_union \
        mountd \
        natacontrol \
        natd \
index 3bacd61..bf6e63c 100644 (file)
@@ -220,13 +220,6 @@ for more information.
 The same as
 .Fl u ;
 indicate that the status of an already mounted file system should be changed.
-.It Cm union
-Causes the namespace at the mount point to appear as the union
-of the mounted filesystem root and the existing directory.
-Lookups will be done in the mounted filesystem first.
-If those operations fail due to a non-existent file the underlying
-directory is then accessed.
-All creates are done in the mounted filesystem.
 .It Cm ignore
 Will be ignored by
 .Xr df 1 .
@@ -421,7 +414,6 @@ have permission to load the module.
 .Xr mount_std 8 ,
 .Xr mount_tmpfs 8 ,
 .Xr mount_udf 8 ,
-.Xr mount_union 8 ,
 .Xr sysctl 8 ,
 .Xr umount 8
 .Sh HISTORY
index 5fe9e97..da33b1c 100644 (file)
@@ -750,7 +750,6 @@ flags2opts(int flags)
        if (flags & MNT_NOEXEC)         res = catopt(res, "noexec");
        if (flags & MNT_NOSUID)         res = catopt(res, "nosuid");
        if (flags & MNT_NODEV)          res = catopt(res, "nodev");
-       if (flags & MNT_UNION)          res = catopt(res, "union");
        if (flags & MNT_ASYNC)          res = catopt(res, "async");
        if (flags & MNT_NOATIME)        res = catopt(res, "noatime");
        if (flags & MNT_NOCLUSTERR)     res = catopt(res, "noclusterr");
index 884d805..1fd2e67 100644 (file)
@@ -68,9 +68,8 @@ options
 .Dq rw ,
 .Dq nodev ,
 .Dq noexec ,
-.Dq nosuid ,
 and
-.Dq union .
+.Dq nosuid .
 .It
 has a kernel filesystem module name the same as its user-visible name.
 .It
index a03dd73..adfb66c 100644 (file)
@@ -719,7 +719,6 @@ flags2opts(int flags)
        if (flags & MNT_NOEXEC)         res = catopt(res, "noexec");
        if (flags & MNT_NOSUID)         res = catopt(res, "nosuid");
        if (flags & MNT_NODEV)          res = catopt(res, "nodev");
-       if (flags & MNT_UNION)          res = catopt(res, "union");
        if (flags & MNT_ASYNC)          res = catopt(res, "async");
        if (flags & MNT_NOATIME)        res = catopt(res, "noatime");
        if (flags & MNT_NOCLUSTERR)     res = catopt(res, "noclusterr");
index f777f27..0fde195 100644 (file)
@@ -220,13 +220,6 @@ for more information.
 The same as
 .Fl u ;
 indicate that the status of an already mounted file system should be changed.
-.It Cm union
-Causes the namespace at the mount point to appear as the union
-of the mounted filesystem root and the existing directory.
-Lookups will be done in the mounted filesystem first.
-If those operations fail due to a non-existent file the underlying
-directory is then accessed.
-All creates are done in the mounted filesystem.
 .It Cm ignore
 Will be ignored by
 .Xr df 1 .
@@ -421,7 +414,6 @@ have permission to load the module.
 .Xr mount_std 8 ,
 .Xr mount_tmpfs 8 ,
 .Xr mount_udf 8 ,
-.Xr mount_union 8 ,
 .Xr sysctl 8 ,
 .Xr umount 8
 .Sh HISTORY
diff --git a/sbin/mount_union/Makefile b/sbin/mount_union/Makefile
deleted file mode 100644 (file)
index 75c7663..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#      @(#)Makefile    8.3 (Berkeley) 3/27/94
-# $FreeBSD: src/sbin/mount_union/Makefile,v 1.6.6.1 2001/04/25 10:58:40 ru Exp $
-
-PROG=  mount_union
-MAN=   mount_union.8
-
-LDADD= -lutil
-DPADD= ${LIBUTIL}
-
-CFLAGS+=-I${.CURDIR}/../../sys
-
-.include <bsd.prog.mk>
diff --git a/sbin/mount_union/mount_union.8 b/sbin/mount_union/mount_union.8
deleted file mode 100644 (file)
index fd871b8..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-.\" Copyright (c) 1994
-.\" The Regents of the University of California.  All rights reserved.
-.\"
-.\" This code is derived from software donated to Berkeley by
-.\" Jan-Simon Pendry.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. Neither the name of the University nor the names of its contributors
-.\"    may be used to endorse or promote products derived from this software
-.\"    without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\"    @(#)mount_union.8       8.6 (Berkeley) 3/27/94
-.\" $FreeBSD: src/sbin/mount_union/mount_union.8,v 1.6.2.2 2001/12/20 16:46:05 ru Exp $
-.\"
-.Dd March 27, 1994
-.Dt MOUNT_UNION 8
-.Os
-.Sh NAME
-.Nm mount_union
-.Nd mount union filesystems
-.Sh SYNOPSIS
-.Nm
-.Op Fl br
-.Op Fl o Ar options
-.Ar directory
-.Ar uniondir
-.Sh DESCRIPTION
-The
-.Nm
-command
-attaches
-.Ar directory
-above
-.Ar uniondir
-in such a way that the contents of both directory trees remain visible.
-By default,
-.Ar directory
-becomes the
-.Em upper
-layer and
-.Ar uniondir
-becomes the
-.Em lower
-layer.
-.Pp
-The options are as follows:
-.Bl -tag -width indent
-.It Fl b
-Invert the default position, so that
-.Ar directory
-becomes the lower layer and
-.Ar uniondir
-becomes the upper layer.
-However,
-.Ar uniondir
-remains the mount point.
-.It Fl o
-Options are specified with a
-.Fl o
-flag followed by a comma separated string of options.
-See the
-.Xr mount 8
-man page for possible options and their meanings.
-.It Fl r
-Hide the lower layer completely in the same way as mounting with
-.Xr mount_null 8 .
-.El
-.Pp
-To enforce filesystem security, the user mounting the filesystem
-must be superuser or else have write permission on the mounted-on
-directory.
-In addition, the
-.Va vfs.usermount
-.Xr sysctl 3
-variable must be set to 1 to permit file system mounting by ordinary users.
-.Pp
-Filenames are looked up in the upper layer and then in the
-lower layer.
-If a directory is found in the lower layer, and there is no entry
-in the upper layer, then a
-.Em shadow
-directory will be created in the upper layer.
-It will be owned by the user who originally did the union mount,
-with mode
-.Dq rwxrwxrwx
-(0777) modified by the umask in effect at that time.
-.Pp
-If a file exists in the upper layer then there is no way to access
-a file with the same name in the lower layer.
-If necessary, a combination of loopback and union mounts can be made
-which will still allow the lower files to be accessed by a different
-pathname.
-.Pp
-Except in the case of a directory,
-access to an object is granted via the normal filesystem access checks.
-For directories, the current user must have access to both the upper
-and lower directories (should they both exist).
-.Pp
-Requests to create or modify objects in
-.Ar uniondir
-are passed to the upper layer with the exception of a few special cases.
-An attempt to open for writing a file which exists in the lower layer
-causes a copy of the
-.Em entire
-file to be made to the upper layer, and then for the upper layer copy
-to be opened.
-Similarly, an attempt to truncate a lower layer file to zero length
-causes an empty file to be created in the upper layer.
-Any other operation which would ultimately require modification to
-the lower layer fails with
-.Er EROFS .
-.Pp
-The union filesystem manipulates the namespace, rather than
-individual filesystems.
-The union operation applies recursively down the directory tree
-now rooted at
-.Ar uniondir .
-Thus any filesystems which are mounted under
-.Ar uniondir
-will take part in the union operation.
-This differs from the
-.Em union
-option to
-.Xr mount 8
-which only applies the union operation to the mount point itself,
-and then only for lookups.
-.Sh EXAMPLES
-The commands
-.Bd -literal -offset indent
-mount -t cd9660 -o ro /dev/cd0a /usr/src
-mount -t union /var/obj /usr/src
-.Ed
-.Pp
-mount the CD-ROM drive
-.Pa /dev/cd0a
-on
-.Pa /usr/src
-and then attaches
-.Pa /var/obj
-on top.
-For most purposes the effect of this is to make the
-source tree appear writable
-even though it is stored on a CD-ROM.
-.Pp
-The command
-.Bd -literal -offset indent
-mount -t union -o -b /sys $HOME/sys
-.Ed
-.Pp
-attaches the system source tree below the
-.Pa sys
-directory in the user's home directory.
-This allows individual users to make private changes
-to the source, and build new kernels, without those
-changes becoming visible to other users.
-Note that the files in the lower layer remain
-accessible via
-.Pa /sys .
-.Sh SEE ALSO
-.Xr intro 2 ,
-.Xr mount 2 ,
-.Xr unmount 2 ,
-.Xr fstab 5 ,
-.Xr mount 8 ,
-.Xr mount_null 8
-.Sh HISTORY
-The
-.Nm
-command first appeared in
-.Bx 4.4 .
-It first worked in
-.Fx Ns -(fill this in) .
-.Sh BUGS
-THIS FILESYSTEM TYPE IS NOT YET FULLY SUPPORTED (READ: IT DOESN'T WORK)
-AND USING IT MAY, IN FACT, DESTROY DATA ON YOUR SYSTEM.  USE AT YOUR
-OWN RISK.  BEWARE OF DOG.  SLIPPERY WHEN WET.
-.Pp
-This code also needs an owner in order to be less dangerous - serious
-hackers can apply by sending mail to
-.Aq Mt kernel@crater.dragonflybsd.org
-and announcing
-their intent to take it over.
-.Pp
-Without whiteout support from the filesystem backing the upper layer,
-there is no way that delete and rename operations on lower layer
-objects can be done.
-.Er EROFS
-is returned for this kind of operations along with any others
-which would make modifications to the lower layer, such as
-.Xr chmod 1 .
-.Pp
-Running
-.Xr find 1
-over a union tree has the side-effect of creating
-a tree of shadow directories in the upper layer.
diff --git a/sbin/mount_union/mount_union.c b/sbin/mount_union/mount_union.c
deleted file mode 100644 (file)
index cb13c17..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 1992, 1993, 1994
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#) Copyright (c) 1992, 1993, 1994 The Regents of the University of California.  All rights reserved.
- * @(#)mount_union.c   8.5 (Berkeley) 3/27/94
- * $FreeBSD: src/sbin/mount_union/mount_union.c,v 1.12 1999/10/09 11:54:14 phk Exp $
- */
-
-#include <sys/param.h>
-#include <sys/mount.h>
-
-#include <vfs/union/union.h>
-
-#include <err.h>
-#include <mntopts.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sysexits.h>
-#include <unistd.h>
-
-static struct mntopt mopts[] = {
-       MOPT_STDOPTS,
-       MOPT_NULL
-};
-
-static int     subdir(const char *, const char *);
-static void    usage(void) __dead2;
-
-int
-main(int argc, char **argv)
-{
-       struct union_args args;
-       int ch, mntflags;
-       char source[MAXPATHLEN];
-       char target[MAXPATHLEN];
-       struct vfsconf vfc;
-       int error;
-
-       mntflags = 0;
-       args.mntflags = UNMNT_ABOVE;
-       while ((ch = getopt(argc, argv, "bo:r")) != -1)
-               switch (ch) {
-               case 'b':
-                       args.mntflags &= ~UNMNT_OPMASK;
-                       args.mntflags |= UNMNT_BELOW;
-                       break;
-               case 'o':
-                       getmntopts(optarg, mopts, &mntflags, 0);
-                       break;
-               case 'r':
-                       args.mntflags &= ~UNMNT_OPMASK;
-                       args.mntflags |= UNMNT_REPLACE;
-                       break;
-               case '?':
-               default:
-                       usage();
-                       /* NOTREACHED */
-               }
-       argc -= optind;
-       argv += optind;
-
-       if (argc != 2)
-               usage();
-
-       /* resolve both target and source with realpath(3) */
-       checkpath(argv[0], target);
-       checkpath(argv[1], source);
-
-       if (subdir(target, source) || subdir(source, target))
-               errx(EX_USAGE, "%s (%s) and %s (%s) are not distinct paths",
-                   argv[0], target, argv[1], source);
-
-       args.target = target;
-
-       error = getvfsbyname("union", &vfc);
-       if (error && vfsisloadable("union")) {
-               if (vfsload("union"))
-                       err(EX_OSERR, "vfsload(union)");
-               endvfsent();    /* flush cache */
-               error = getvfsbyname("union", &vfc);
-       }
-       if (error)
-               errx(EX_OSERR, "union filesystem is not available");
-
-       if (mount(vfc.vfc_name, source, mntflags, &args))
-               err(EX_OSERR, "%s", target);
-       exit(0);
-}
-
-static int
-subdir(const char *p, const char *dir)
-{
-       int l;
-
-       l = strlen(dir);
-       if (l <= 1)
-               return (1);
-
-       if ((strncmp(p, dir, l) == 0) && (p[l] == '/' || p[l] == '\0'))
-               return (1);
-
-       return (0);
-}
-
-static void
-usage(void)
-{
-       fprintf(stderr,
-           "usage: mount_union [-br] [-o options] target_fs mount_point\n");
-       exit(EX_USAGE);
-}
index 3b1840c..d1a2102 100644 (file)
@@ -1224,9 +1224,6 @@ vfs/procfs/procfs_type.c  optional procfs
 vfs/procfs/procfs_vfsops.c     optional procfs
 vfs/procfs/procfs_vnops.c      optional procfs
 vfs/procfs/procfs_rlimit.c     optional procfs
-vfs/union/union_subr.c         optional union
-vfs/union/union_vfsops.c       optional union
-vfs/union/union_vnops.c                optional union
 vfs/hpfs/hpfs_alsubr.c         optional hpfs
 vfs/hpfs/hpfs_hash.c           optional hpfs
 vfs/hpfs/hpfs_lookup.c         optional hpfs
index 6f8d0ae..8621397 100644 (file)
@@ -169,10 +169,6 @@ UFS_DIRHASH        opt_ufs.h
 FFS_ROOT       opt_ffs.h
 NFS_ROOT       opt_nfsroot.h
 
-# The union static file system has bogus static dependencies, so it isn't
-# hidden yet.
-UNION
-
 # Options used only in subr_param.c.
 HZ             opt_param.h
 MAXFILES       opt_param.h
index 7ea2440..4b7d335 100644 (file)
@@ -494,10 +494,10 @@ options           IFPOLL_ENABLE
 # cannot currently be demand-loaded.)  Some people still prefer
 # to statically compile other filesystems as well.
 #
-# NB: The PORTAL and UNION filesystems are known to be
+# NB: The PORTAL filesystem is known to be
 # buggy, and WILL panic your system if you attempt to do anything with
-# them.  They are included here as an incentive for some enterprising
-# soul to sit down and fix them.
+# it.  It is included here as an incentive for some enterprising
+# soul to sit down and fix it.
 #
 
 # One of these is mandatory:
@@ -520,8 +520,6 @@ options     SMBFS                   #SMB/CIFS filesystem
 options        TMPFS                   #Temporary filesystem
 options                UDF                     #UDF filesystem
 
-# YYY-DR Till we rework the VOP methods for this filesystem
-#options       UNION                   #Union filesystem
 # The xFS_ROOT options REQUIRE the associated ``options xFS''
 options        FFS_ROOT                #FFS usable as root device
 options        NFS_ROOT                #NFS usable as root device
index 3415f0e..d137a1d 100644 (file)
@@ -33,9 +33,6 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/emulation/43bsd/43bsd_file.c,v 1.11 2006/09/05 00:55:44 dillon Exp $
- *     from: DragonFly kern/vfs_syscalls.c,v 1.20
- *
  * These syscalls used to live in kern/vfs_syscalls.c.  They are modified
  * to use the new split syscalls.
  */
@@ -61,8 +58,6 @@
 
 #include <sys/mplock2.h>
 
-#include <vfs/union/union.h>
-
 /*
  * MPALMOSTSAFE
  */
index fb0d326..d822584 100644 (file)
@@ -1841,7 +1841,6 @@ vfs_flagstostr(int flags, const struct mountctl_opt *optp,
                { MNT_QUOTA,            "with-quotas" },
                { MNT_RDONLY,           "read-only" },
                { MNT_SYNCHRONOUS,      "synchronous" },
-               { MNT_UNION,            "union" },
                { MNT_NOCLUSTERR,       "noclusterr" },
                { MNT_NOCLUSTERW,       "noclusterw" },
                { MNT_SUIDDIR,          "suiddir" },
index a15f0d0..2c1c68c 100644 (file)
@@ -76,8 +76,6 @@
 #include <machine/limits.h>
 #include <machine/stdarg.h>
 
-#include <vfs/union/union.h>
-
 static void mount_warning(struct mount *mp, const char *ctl, ...)
                __printflike(2, 3);
 static int mount_path(struct proc *p, struct mount *mp, char **rb, char **fb);
@@ -94,8 +92,6 @@ static int setutimes (struct vnode *, struct vattr *,
                        const struct timespec *, int);
 static int     usermount = 0;  /* if 1, non-root can mount fs. */
 
-int (*union_dircheckp) (struct thread *, struct vnode **, struct file *);
-
 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
     "Allow non-root users to mount filesystems");
 
@@ -358,11 +354,11 @@ update:
        else if (mp->mnt_flag & MNT_RDONLY)
                mp->mnt_kern_flag |= MNTK_WANTRDWR;
        mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
-           MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
+           MNT_SYNCHRONOUS | MNT_ASYNC | MNT_NOATIME |
            MNT_NOSYMFOLLOW | MNT_IGNORE | MNT_TRIM |
            MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
        mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC |
-           MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
+           MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_FORCE |
            MNT_NOSYMFOLLOW | MNT_IGNORE | MNT_TRIM |
            MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
        /*
@@ -4243,7 +4239,6 @@ kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res,
                goto done;
        }
        vp = (struct vnode *)fp->f_data;
-unionread:
        if (vp->v_type != VDIR) {
                error = EINVAL;
                goto done;
@@ -4261,27 +4256,6 @@ unionread:
        fp->f_offset = auio.uio_offset;
        if (error)
                goto done;
-       if (count == auio.uio_resid) {
-               if (union_dircheckp) {
-                       error = union_dircheckp(td, &vp, fp);
-                       if (error == -1)
-                               goto unionread;
-                       if (error)
-                               goto done;
-               }
-#if 0
-               if ((vp->v_flag & VROOT) &&
-                   (vp->v_mount->mnt_flag & MNT_UNION)) {
-                       struct vnode *tvp = vp;
-                       vp = vp->v_mount->mnt_vnodecovered;
-                       vref(vp);
-                       fp->f_data = vp;
-                       fp->f_offset = 0;
-                       vrele(tvp);
-                       goto unionread;
-               }
-#endif
-       }
 
        /*
         * WARNING!  *basep may not be wide enough to accomodate the
index bccccfa..fd6b01e 100644 (file)
@@ -267,7 +267,6 @@ struct mount {
 #define        MNT_NOEXEC      0x00000004      /* can't exec from filesystem */
 #define        MNT_NOSUID      0x00000008      /* don't honor setuid bits on fs */
 #define        MNT_NODEV       0x00000010      /* don't interpret special files */
-#define        MNT_UNION       0x00000020      /* union with underlying filesystem */
 #define        MNT_ASYNC       0x00000040      /* file system written asynchronously */
 #define        MNT_SUIDDIR     0x00100000      /* special handling of SUID on dirs */
 #define        MNT_SOFTDEP     0x00200000      /* soft updates being done */
@@ -304,7 +303,7 @@ struct mount {
  * but the 'mount' program may need changing to handle this.
  */
 #define        MNT_VISFLAGMASK (MNT_RDONLY     | MNT_SYNCHRONOUS | MNT_NOEXEC  | \
-                       MNT_NOSUID      | MNT_NODEV     | MNT_UNION     | \
+                       MNT_NOSUID      | MNT_NODEV                     | \
                        MNT_ASYNC       | MNT_EXRDONLY  | MNT_EXPORTED  | \
                        MNT_DEFEXPORTED | MNT_EXPORTANON| MNT_EXKERB    | \
                        MNT_LOCAL       | MNT_USER      | MNT_QUOTA     | \
diff --git a/sys/vfs/union/Makefile b/sys/vfs/union/Makefile
deleted file mode 100644 (file)
index 9061e5a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# $FreeBSD: src/sys/modules/union/Makefile,v 1.7 1999/12/12 20:34:11 peter Exp $
-# $DragonFly: src/sys/vfs/union/Makefile,v 1.4 2004/08/13 17:51:14 dillon Exp $
-
-KMOD=  union
-SRCS=  union_subr.c union_vfsops.c union_vnops.c
-
-.include <bsd.kmod.mk>
diff --git a/sys/vfs/union/union.h b/sys/vfs/union/union.h
deleted file mode 100644 (file)
index 0b9f7ff..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994 Jan-Simon Pendry.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     @(#)union.h     8.9 (Berkeley) 12/10/94
- * $FreeBSD: src/sys/miscfs/union/union.h,v 1.17 1999/12/29 04:54:48 peter Exp $
- * $DragonFly: src/sys/vfs/union/union.h,v 1.9 2006/12/23 00:41:30 swildner Exp $
- */
-
-struct union_args {
-       char            *target;        /* Target of loopback  */
-       int             mntflags;       /* Options on the mount */
-};
-
-#define UNMNT_ABOVE    0x0001          /* Target appears below mount point */
-#define UNMNT_BELOW    0x0002          /* Target appears below mount point */
-#define UNMNT_REPLACE  0x0003          /* Target replaces mount point */
-#define UNMNT_OPMASK   0x0003
-
-struct union_mount {
-       struct vnode    *um_uppervp;    /* UN_ULOCK holds locking state */
-       struct vnode    *um_lowervp;    /* Left unlocked */
-       struct ucred    *um_cred;       /* Credentials of user calling mount */
-       int             um_cmode;       /* cmask from mount process */
-       int             um_op;          /* Operation mode */
-};
-
-#ifdef _KERNEL
-
-#ifndef DIAGNOSTIC
-#define DIAGNOSTIC
-#endif
-
-#endif
-
-#if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
-
-/*
- * DEFDIRMODE is the mode bits used to create a shadow directory.
- */
-#define VRWXMODE (VREAD|VWRITE|VEXEC)
-#define VRWMODE (VREAD|VWRITE)
-#define UN_DIRMODE ((VRWXMODE)|(VRWXMODE>>3)|(VRWXMODE>>6))
-#define UN_FILEMODE ((VRWMODE)|(VRWMODE>>3)|(VRWMODE>>6))
-
-/*
- * A cache of vnode references (hangs off v_data)
- */
-struct union_node {
-       LIST_ENTRY(union_node)  un_cache;       /* Hash chain */
-       struct vnode            *un_vnode;      /* Back pointer */
-       struct vnode            *un_uppervp;    /* overlaying object */
-       struct vnode            *un_lowervp;    /* underlying object */
-       struct vnode            *un_dirvp;      /* Parent dir of uppervp */
-       struct vnode            *un_pvp;        /* Parent vnode */
-       char                    *un_path;       /* saved component name */
-       int                     un_openl;       /* # of opens on lowervp */
-       int                     un_exclcnt;     /* exclusive count */
-       unsigned int            un_flags;
-       struct vnode            **un_dircache;  /* cached union stack */
-       off_t                   un_uppersz;     /* size of upper object */
-       off_t                   un_lowersz;     /* size of lower object */
-#ifdef DIAGNOSTIC
-       pid_t                   un_pid;
-#endif
-};
-
-/*
- * XXX UN_ULOCK -      indicates that the uppervp is locked
- *
- * UN_CACHED - node is in the union cache
- */
-
-/*#define UN_ULOCK     0x04*/  /* Upper node is locked */
-#define UN_CACHED      0x10    /* In union cache */
-
-/*
- * Hash table locking flags
- */
-
-#define UNVP_WANT      0x01
-#define UNVP_LOCKED    0x02
-
-#define        MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
-#define        VTOUNION(vp) ((struct union_node *)(vp)->v_data)
-#define        UNIONTOV(un) ((un)->un_vnode)
-#define        LOWERVP(vp) (VTOUNION(vp)->un_lowervp)
-#define        UPPERVP(vp) (VTOUNION(vp)->un_uppervp)
-#define OTHERVP(vp) (UPPERVP(vp) ? UPPERVP(vp) : LOWERVP(vp))
-
-#define UDEBUG(x)      if (uniondebug) kprintf x
-#define UDEBUG_ENABLED 1
-
-#endif
-
-#ifdef _KERNEL
-
-extern int union_allocvp (struct vnode **, struct mount *,
-                               struct vnode *, 
-                               struct vnode *, 
-                               struct componentname *, struct vnode *,
-                               struct vnode *, int);
-extern int union_freevp (struct vnode *);
-extern struct vnode *union_dircache (struct vnode *, struct thread *);
-extern int union_copyup (struct union_node *, int, struct ucred *,
-                               struct thread *);
-extern int union_dowhiteout (struct union_node *, struct ucred *,
-                                       struct thread *);
-extern int union_mkshadow (struct union_mount *, struct vnode *,
-                               struct componentname *, struct vnode **);
-extern int union_mkwhiteout (struct union_mount *, struct vnode *,
-                               struct componentname *, char *);
-extern int union_cn_close (struct vnode *, int, struct ucred *,
-                               struct thread *);
-extern void union_removed_upper (struct union_node *un);
-extern struct vnode *union_lowervp (struct vnode *);
-extern void union_newsize (struct vnode *, off_t, off_t);
-extern void union_vm_coherency (struct vnode *, struct uio *, int);
-
-extern int (*union_dircheckp) (struct thread *, struct vnode **,
-                                struct file *);
-
-extern struct vfsops union_vfsops;
-extern int uniondebug;
-
-#endif /* _KERNEL */
diff --git a/sys/vfs/union/union_subr.c b/sys/vfs/union/union_subr.c
deleted file mode 100644 (file)
index c2260c9..0000000
+++ /dev/null
@@ -1,1289 +0,0 @@
-/*
- * Copyright (c) 1994 Jan-Simon Pendry
- * Copyright (c) 1994
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     @(#)union_subr.c        8.20 (Berkeley) 5/20/95
- * $FreeBSD: src/sys/miscfs/union/union_subr.c,v 1.43.2.2 2001/12/25 01:44:45 dillon Exp $
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/vnode.h>
-#include <sys/proc.h>
-#include <sys/namei.h>
-#include <sys/malloc.h>
-#include <sys/fcntl.h>
-#include <sys/file.h>
-#include <sys/filedesc.h>
-#include <sys/module.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <vm/vm.h>
-#include <vm/vm_extern.h>      /* for vnode_pager_setsize */
-#include <vm/vm_zone.h>
-#include <vm/vm_object.h>      /* for vm cache coherency */
-#include "union.h"
-
-extern int     union_init (void);
-
-/* must be power of two, otherwise change UNION_HASH() */
-#define NHASH 32
-
-/* unsigned int ... */
-#define UNION_HASH(u, l) \
-       (((((uintptr_t) (u)) + ((uintptr_t) l)) >> 8) & (NHASH-1))
-
-static LIST_HEAD(unhead, union_node) unhead[NHASH];
-static int unvplock[NHASH];
-
-static void    union_dircache_r (struct vnode *vp, struct vnode ***vppp,
-                                     int *cntp);
-static int     union_list_lock (int ix);
-static void    union_list_unlock (int ix);
-static int     union_relookup (struct union_mount *um, struct vnode *dvp,
-                                   struct vnode **vpp,
-                                   struct componentname *cnp,
-                                   struct componentname *cn, char *path,
-                                   int pathlen);
-static void    union_updatevp (struct union_node *un,
-                                   struct vnode *uppervp,
-                                   struct vnode *lowervp);
-static void union_newlower (struct union_node *, struct vnode *);
-static void union_newupper (struct union_node *, struct vnode *);
-static int union_copyfile (struct vnode *, struct vnode *,
-                                       struct ucred *, struct thread *);
-static int union_vn_create (struct vnode **, struct union_node *,
-                               struct thread *);
-static int union_vn_close (struct vnode *, int, struct ucred *);
-
-int
-union_init(void)
-{
-       int i;
-
-       for (i = 0; i < NHASH; i++)
-               LIST_INIT(&unhead[i]);
-       bzero((caddr_t)unvplock, sizeof(unvplock));
-       return (0);
-}
-
-static int
-union_list_lock(int ix)
-{
-       if (unvplock[ix] & UNVP_LOCKED) {
-               unvplock[ix] |= UNVP_WANT;
-               (void) tsleep((caddr_t) &unvplock[ix], 0, "unllck", 0);
-               return (1);
-       }
-       unvplock[ix] |= UNVP_LOCKED;
-       return (0);
-}
-
-static void
-union_list_unlock(int ix)
-{
-       unvplock[ix] &= ~UNVP_LOCKED;
-
-       if (unvplock[ix] & UNVP_WANT) {
-               unvplock[ix] &= ~UNVP_WANT;
-               wakeup((caddr_t) &unvplock[ix]);
-       }
-}
-
-/*
- *     union_updatevp:
- *
- *     The uppervp, if not NULL, must be referenced and not locked by us
- *     The lowervp, if not NULL, must be referenced.
- *
- *     if uppervp and lowervp match pointers already installed, nothing
- *     happens. The passed vp's (when matching) are not adjusted.  This
- *     routine may only be called by union_newupper() and union_newlower().
- */
-
-static void
-union_updatevp(struct union_node *un, struct vnode *uppervp,
-              struct vnode *lowervp)
-{
-       int ohash = UNION_HASH(un->un_uppervp, un->un_lowervp);
-       int nhash = UNION_HASH(uppervp, lowervp);
-       int docache = (lowervp != NULLVP || uppervp != NULLVP);
-       int lhash, uhash;
-
-       /*
-        * Ensure locking is ordered from lower to higher
-        * to avoid deadlocks.
-        */
-       if (nhash < ohash) {
-               lhash = nhash;
-               uhash = ohash;
-       } else {
-               lhash = ohash;
-               uhash = nhash;
-       }
-
-       if (lhash != uhash) {
-               while (union_list_lock(lhash))
-                       continue;
-       }
-
-       while (union_list_lock(uhash))
-               continue;
-
-       if (ohash != nhash || !docache) {
-               if (un->un_flags & UN_CACHED) {
-                       un->un_flags &= ~UN_CACHED;
-                       LIST_REMOVE(un, un_cache);
-               }
-       }
-
-       if (ohash != nhash)
-               union_list_unlock(ohash);
-
-       if (un->un_lowervp != lowervp) {
-               if (un->un_lowervp) {
-                       vrele(un->un_lowervp);
-                       if (un->un_path) {
-                               kfree(un->un_path, M_TEMP);
-                               un->un_path = 0;
-                       }
-               }
-               un->un_lowervp = lowervp;
-               un->un_lowersz = VNOVAL;
-       }
-
-       if (un->un_uppervp != uppervp) {
-               if (un->un_uppervp)
-                       vrele(un->un_uppervp);
-               un->un_uppervp = uppervp;
-               un->un_uppersz = VNOVAL;
-       }
-
-       if (docache && (ohash != nhash)) {
-               LIST_INSERT_HEAD(&unhead[nhash], un, un_cache);
-               un->un_flags |= UN_CACHED;
-       }
-
-       union_list_unlock(nhash);
-}
-
-/*
- * Set a new lowervp.  The passed lowervp must be referenced and will be
- * stored in the vp in a referenced state. 
- */
-
-static void
-union_newlower(struct union_node *un, struct vnode *lowervp)
-{
-       union_updatevp(un, un->un_uppervp, lowervp);
-}
-
-/*
- * Set a new uppervp.  The passed uppervp must be locked and will be 
- * stored in the vp in a locked state.  The caller should not unlock
- * uppervp.
- */
-
-static void
-union_newupper(struct union_node *un, struct vnode *uppervp)
-{
-       union_updatevp(un, uppervp, un->un_lowervp);
-}
-
-/*
- * Keep track of size changes in the underlying vnodes.
- * If the size changes, then callback to the vm layer
- * giving priority to the upper layer size.
- */
-void
-union_newsize(struct vnode *vp, off_t uppersz, off_t lowersz)
-{
-       struct union_node *un;
-       off_t sz;
-
-       /* only interested in regular files */
-       if (vp->v_type != VREG)
-               return;
-
-       un = VTOUNION(vp);
-       sz = VNOVAL;
-
-       if ((uppersz != VNOVAL) && (un->un_uppersz != uppersz)) {
-               un->un_uppersz = uppersz;
-               if (sz == VNOVAL)
-                       sz = un->un_uppersz;
-       }
-
-       if ((lowersz != VNOVAL) && (un->un_lowersz != lowersz)) {
-               un->un_lowersz = lowersz;
-               if (sz == VNOVAL)
-                       sz = un->un_lowersz;
-       }
-
-       if (sz != VNOVAL) {
-               UDEBUG(("union: %s size now %ld\n",
-                       (uppersz != VNOVAL ? "upper" : "lower"), (long)sz));
-               vnode_pager_setsize(vp, sz);
-       }
-}
-
-/*
- *     union_allocvp:  allocate a union_node and associate it with a
- *                     parent union_node and one or two vnodes.
- *
- *     vpp     Holds the returned vnode locked and referenced if no 
- *             error occurs.
- *
- *     mp      Holds the mount point.  mp may or may not be busied. 
- *             allocvp makes no changes to mp.
- *
- *     dvp     Holds the parent union_node to the one we wish to create.
- *             XXX may only be used to traverse an uncopied lowervp-based
- *             tree?  XXX
- *
- *             dvp may or may not be locked.  allocvp makes no changes
- *             to dvp.
- *
- *     upperdvp Holds the parent vnode to uppervp, generally used along
- *             with path component information to create a shadow of
- *             lowervp when uppervp does not exist.
- *
- *             upperdvp is referenced but unlocked on entry, and will be
- *             dereferenced on return.
- *
- *     uppervp Holds the new uppervp vnode to be stored in the 
- *             union_node we are allocating.  uppervp is referenced but
- *             not locked, and will be dereferenced on return.
- *
- *     lowervp Holds the new lowervp vnode to be stored in the
- *             union_node we are allocating.  lowervp is referenced but
- *             not locked, and will be dereferenced on return.
- * 
- *     cnp     Holds path component information to be coupled with
- *             lowervp and upperdvp to allow unionfs to create an uppervp
- *             later on.  Only used if lowervp is valid.  The conents
- *             of cnp is only valid for the duration of the call.
- *
- *     docache Determine whether this node should be entered in the
- *             cache or whether it should be destroyed as soon as possible.
- *
- * all union_nodes are maintained on a singly-linked
- * list.  new nodes are only allocated when they cannot
- * be found on this list.  entries on the list are
- * removed when the vfs reclaim entry is called.
- *
- * a single lock is kept for the entire list.  this is
- * needed because the getnewvnode() function can block
- * waiting for a vnode to become free, in which case there
- * may be more than one process trying to get the same
- * vnode.  this lock is only taken if we are going to
- * call getnewvnode, since the kernel itself is single-threaded.
- *
- * if an entry is found on the list, then call vget() to
- * take a reference.  this is done because there may be
- * zero references to it and so it needs to removed from
- * the vnode free list.
- */
-
-int
-union_allocvp(struct vnode **vpp,
-             struct mount *mp,
-             struct vnode *dvp,                /* parent union vnode */
-             struct vnode *upperdvp,           /* parent vnode of uppervp */
-             struct componentname *cnp,        /* may be null */
-             struct vnode *uppervp,            /* may be null */
-             struct vnode *lowervp,            /* may be null */
-             int docache)
-{
-       int error;
-       struct union_node *un = NULL;
-       struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
-       struct thread *td = (cnp) ? cnp->cn_td : curthread; /* XXX */
-       int hash = 0;
-       int vflag;
-       int try;
-
-       if (uppervp == NULLVP && lowervp == NULLVP)
-               panic("union: unidentifiable allocation");
-
-       if (uppervp && lowervp && (uppervp->v_type != lowervp->v_type)) {
-               vrele(lowervp);
-               lowervp = NULLVP;
-       }
-
-       /* detect the root vnode (and aliases) */
-       vflag = 0;
-       if ((uppervp == um->um_uppervp) &&
-           ((lowervp == NULLVP) || lowervp == um->um_lowervp)) {
-               if (lowervp == NULLVP) {
-                       lowervp = um->um_lowervp;
-                       if (lowervp != NULLVP)
-                               vref(lowervp);
-               }
-               vflag = VROOT;
-       }
-
-loop:
-       if (!docache) {
-               un = NULL;
-       } else for (try = 0; try < 3; try++) {
-               switch (try) {
-               case 0:
-                       if (lowervp == NULLVP)
-                               continue;
-                       hash = UNION_HASH(uppervp, lowervp);
-                       break;
-
-               case 1:
-                       if (uppervp == NULLVP)
-                               continue;
-                       hash = UNION_HASH(uppervp, NULLVP);
-                       break;
-
-               case 2:
-                       if (lowervp == NULLVP)
-                               continue;
-                       hash = UNION_HASH(NULLVP, lowervp);
-                       break;
-               }
-
-               while (union_list_lock(hash))
-                       continue;
-
-               for (un = unhead[hash].lh_first; un != NULL;
-                                       un = un->un_cache.le_next) {
-                       if ((un->un_lowervp == lowervp ||
-                            un->un_lowervp == NULLVP) &&
-                           (un->un_uppervp == uppervp ||
-                            un->un_uppervp == NULLVP) &&
-                           (UNIONTOV(un)->v_mount == mp)) {
-                               if (vget(UNIONTOV(un), LK_EXCLUSIVE|LK_SLEEPFAIL)) {
-                                       union_list_unlock(hash);
-                                       goto loop;
-                               }
-                               break;
-                       }
-               }
-
-               union_list_unlock(hash);
-
-               if (un)
-                       break;
-       }
-
-       if (un) {
-               /*
-                * Obtain a lock on the union_node.  Everything is unlocked
-                * except for dvp, so check that case.  If they match, our
-                * new un is already locked.  Otherwise we have to lock our
-                * new un.
-                *
-                * A potential deadlock situation occurs when we are holding
-                * one lock while trying to get another.  We must follow 
-                * strict ordering rules to avoid it.  We try to locate dvp
-                * by scanning up from un_vnode, since the most likely 
-                * scenario is un being under dvp.
-                */
-
-               if (dvp && un->un_vnode != dvp) {
-                       struct vnode *scan = un->un_vnode;
-
-                       do {
-                               scan = VTOUNION(scan)->un_pvp;
-                       } while (scan && scan->v_tag == VT_UNION && scan != dvp);
-                       if (scan != dvp) {
-                               /*
-                                * our new un is above dvp (we never saw dvp
-                                * while moving up the tree).
-                                */
-                               vref(dvp);
-                               vn_unlock(dvp);
-                               error = vn_lock(un->un_vnode, LK_EXCLUSIVE |
-                                                             LK_FAILRECLAIM);
-                               vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
-                               vrele(dvp);
-                       } else {
-                               /*
-                                * our new un is under dvp
-                                */
-                               error = vn_lock(un->un_vnode, LK_EXCLUSIVE |
-                                                             LK_FAILRECLAIM);
-                       }
-               } else if (dvp == NULLVP) {
-                       /*
-                        * dvp is NULL, we need to lock un.
-                        */
-                       error = vn_lock(un->un_vnode, LK_EXCLUSIVE |
-                                                     LK_FAILRECLAIM);
-               } else {
-                       /*
-                        * dvp == un->un_vnode, we are already locked.
-                        */
-                       error = 0;
-               }
-
-               if (error)
-                       goto loop;
-
-               /*
-                * At this point, the union_node is locked and referenced.
-                *
-                * uppervp is locked and referenced or NULL, lowervp is
-                * referenced or NULL.
-                */
-               UDEBUG(("Modify existing un %p vn %p upper %p(refs %d) -> %p(refs %d)\n",
-                       un, un->un_vnode, un->un_uppervp, 
-                       (un->un_uppervp ? VREFCNT(un->un_uppervp) : -99),
-                       uppervp,
-                       (uppervp ? VREFCNT(uppervp) : -99)
-               ));
-
-               if (uppervp != un->un_uppervp) {
-                       KASSERT(uppervp == NULL || VREFCNT(uppervp) > 0,
-                               ("union_allocvp: too few refs %d (at least 1 "
-                                "required) on uppervp",
-                               VREFCNT(uppervp)));
-                       union_newupper(un, uppervp);
-               } else if (uppervp) {
-                       KASSERT(VREFCNT(uppervp) > 1,
-                               ("union_allocvp: too few refs %d (at least "
-                                "2 required) on uppervp",
-                                VREFCNT(uppervp)));
-                       vrele(uppervp);
-               }
-
-               /*
-                * Save information about the lower layer.
-                * This needs to keep track of pathname
-                * and directory information which union_vn_create
-                * might need.
-                */
-               if (lowervp != un->un_lowervp) {
-                       union_newlower(un, lowervp);
-                       if (cnp && (lowervp != NULLVP)) {
-                               un->un_path = malloc(cnp->cn_namelen+1,
-                                               M_TEMP, M_WAITOK);
-                               bcopy(cnp->cn_nameptr, un->un_path,
-                                               cnp->cn_namelen);
-                               un->un_path[cnp->cn_namelen] = '\0';
-                       }
-               } else if (lowervp) {
-                       vrele(lowervp);
-               }
-
-               /*
-                * and upperdvp
-                */
-               if (upperdvp != un->un_dirvp) {
-                       if (un->un_dirvp)
-                               vrele(un->un_dirvp);
-                       un->un_dirvp = upperdvp;
-               } else if (upperdvp) {
-                       vrele(upperdvp);
-               }
-
-               *vpp = UNIONTOV(un);
-               return (0);
-       }
-
-       if (docache) {
-               /*
-                * otherwise lock the vp list while we call getnewvnode
-                * since that can block.
-                */ 
-               hash = UNION_HASH(uppervp, lowervp);
-
-               if (union_list_lock(hash))
-                       goto loop;
-       }
-
-       /*
-        * Create new node rather then replace old node
-        */
-
-       error = getnewvnode(VT_UNION, mp, vpp, 0, 0);
-       if (error) {
-               /*
-                * If an error occurs clear out vnodes.
-                */
-               if (lowervp)
-                       vrele(lowervp);
-               if (uppervp) 
-                       vrele(uppervp);
-               if (upperdvp)
-                       vrele(upperdvp);
-               *vpp = NULL;
-               goto out;
-       }
-
-       (*vpp)->v_data = kmalloc(sizeof(struct union_node), M_TEMP, M_WAITOK);
-
-       vsetflags(*vpp, vflag);
-       if (uppervp)
-               (*vpp)->v_type = uppervp->v_type;
-       else
-               (*vpp)->v_type = lowervp->v_type;
-
-       un = VTOUNION(*vpp);
-       bzero(un, sizeof(*un));
-
-       un->un_vnode = *vpp;
-       un->un_uppervp = uppervp;
-       un->un_uppersz = VNOVAL;
-       un->un_lowervp = lowervp;
-       un->un_lowersz = VNOVAL;
-       un->un_dirvp = upperdvp;
-       un->un_pvp = dvp;               /* only parent dir in new allocation */
-       if (dvp != NULLVP)
-               vref(dvp);
-       un->un_dircache = 0;
-       un->un_openl = 0;
-
-       if (cnp && (lowervp != NULLVP)) {
-               un->un_path = kmalloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
-               bcopy(cnp->cn_nameptr, un->un_path, cnp->cn_namelen);
-               un->un_path[cnp->cn_namelen] = '\0';
-       } else {
-               un->un_path = 0;
-               un->un_dirvp = NULL;
-       }
-
-       if (docache) {
-               LIST_INSERT_HEAD(&unhead[hash], un, un_cache);
-               un->un_flags |= UN_CACHED;
-       }
-
-       /* 
-        * locked refd vpp is returned
-        */
-
-out:
-       if (docache)
-               union_list_unlock(hash);
-
-       return (error);
-}
-
-int
-union_freevp(struct vnode *vp)
-{
-       struct union_node *un = VTOUNION(vp);
-
-       vp->v_data = NULL;
-       if (un->un_flags & UN_CACHED) {
-               un->un_flags &= ~UN_CACHED;
-               LIST_REMOVE(un, un_cache);
-       }
-       if (un->un_pvp != NULLVP) {
-               vrele(un->un_pvp);
-               un->un_pvp = NULL;
-       }
-       if (un->un_uppervp != NULLVP) {
-               vrele(un->un_uppervp);
-               un->un_uppervp = NULL;
-       }
-       if (un->un_lowervp != NULLVP) {
-               vrele(un->un_lowervp);
-               un->un_lowervp = NULL;
-       }
-       if (un->un_dirvp != NULLVP) {
-               vrele(un->un_dirvp);
-               un->un_dirvp = NULL;
-       }
-       if (un->un_path) {
-               kfree(un->un_path, M_TEMP);
-               un->un_path = NULL;
-       }
-       kfree(un, M_TEMP);
-       return (0);
-}
-
-/*
- * copyfile.  copy the vnode (fvp) to the vnode (tvp)
- * using a sequence of reads and writes.  both (fvp)
- * and (tvp) are locked on entry and exit.
- *
- * fvp and tvp are both exclusive locked on call, but their refcount's
- * haven't been bumped at all.
- */
-static int
-union_copyfile(struct vnode *fvp, struct vnode *tvp, struct ucred *cred,
-              struct thread *td)
-{
-       char *buf;
-       struct uio uio;
-       struct iovec iov;
-       int error = 0;
-
-       /*
-        * strategy:
-        * allocate a buffer of size MAXBSIZE.
-        * loop doing reads and writes, keeping track
-        * of the current uio offset.
-        * give up at the first sign of trouble.
-        */
-
-       bzero(&uio, sizeof(uio));
-
-       uio.uio_td = td;
-       uio.uio_segflg = UIO_SYSSPACE;
-       uio.uio_offset = 0;
-
-       buf = kmalloc(MAXBSIZE, M_TEMP, M_WAITOK);
-
-       /* ugly loop follows... */
-       do {
-               off_t offset = uio.uio_offset;
-               int count;
-               int bufoffset;
-
-               /*
-                * Setup for big read
-                */
-               uio.uio_iov = &iov;
-               uio.uio_iovcnt = 1;
-               iov.iov_base = buf;
-               iov.iov_len = MAXBSIZE;
-               uio.uio_resid = iov.iov_len;
-               uio.uio_rw = UIO_READ;
-
-               if ((error = VOP_READ(fvp, &uio, 0, cred)) != 0)
-                       break;
-
-               /*
-                * Get bytes read, handle read eof case and setup for
-                * write loop
-                */
-               if ((count = MAXBSIZE - uio.uio_resid) == 0)
-                       break;
-               bufoffset = 0;
-
-               /*
-                * Write until an error occurs or our buffer has been
-                * exhausted, then update the offset for the next read.
-                */
-               while (bufoffset < count) {
-                       uio.uio_iov = &iov;
-                       uio.uio_iovcnt = 1;
-                       iov.iov_base = buf + bufoffset;
-                       iov.iov_len = count - bufoffset;
-                       uio.uio_offset = offset + bufoffset;
-                       uio.uio_rw = UIO_WRITE;
-                       uio.uio_resid = iov.iov_len;
-
-                       if ((error = VOP_WRITE(tvp, &uio, 0, cred)) != 0)
-                               break;
-                       bufoffset += (count - bufoffset) - uio.uio_resid;
-               }
-               uio.uio_offset = offset + bufoffset;
-       } while (error == 0);
-
-       kfree(buf, M_TEMP);
-       return (error);
-}
-
-/*
- *
- * un's vnode is assumed to be locked on entry and remains locked on exit.
- */
-
-int
-union_copyup(struct union_node *un, int docopy, struct ucred *cred,
-            struct thread *td)
-{
-       int error;
-       struct vnode *lvp, *uvp;
-
-       /*
-        * If the user does not have read permission, the vnode should not
-        * be copied to upper layer.
-        */
-       vn_lock(un->un_lowervp, LK_EXCLUSIVE | LK_RETRY);
-       error = VOP_EACCESS(un->un_lowervp, VREAD, cred);
-       vn_unlock(un->un_lowervp);
-       if (error)
-               return (error);
-
-       error = union_vn_create(&uvp, un, td);
-       if (error)
-               return (error);
-
-       lvp = un->un_lowervp;
-
-       KASSERT(VREFCNT(uvp) > 0,
-               ("copy: uvp refcount 0: %d", VREFCNT(uvp)));
-       if (docopy) {
-               /*
-                * XX - should not ignore errors
-                * from VOP_CLOSE
-                */
-               vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY);
-               error = VOP_OPEN(lvp, FREAD, cred, NULL);
-               if (error == 0) {
-                       error = union_copyfile(lvp, uvp, cred, td);
-                       (void) VOP_CLOSE(lvp, FREAD);
-                       vn_unlock(lvp);
-               }
-               if (error == 0)
-                       UDEBUG(("union: copied up %s\n", un->un_path));
-
-       }
-       vn_unlock(uvp);
-       union_newupper(un, uvp);
-       KASSERT(VREFCNT(uvp) > 0, ("copy: uvp refcount 0: %d", VREFCNT(uvp)));
-       union_vn_close(uvp, FWRITE, cred);
-       KASSERT(VREFCNT(uvp) > 0, ("copy: uvp refcount 0: %d", VREFCNT(uvp)));
-       /*
-        * Subsequent IOs will go to the top layer, so
-        * call close on the lower vnode and open on the
-        * upper vnode to ensure that the filesystem keeps
-        * its references counts right.  This doesn't do
-        * the right thing with (cred) and (FREAD) though.
-        * Ignoring error returns is not right, either.
-        */
-       if (error == 0) {
-               int i;
-
-               for (i = 0; i < un->un_openl; i++) {
-                       vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY);
-                       VOP_CLOSE(lvp, FREAD);
-                       vn_unlock(lvp);
-                       vn_lock(uvp, LK_EXCLUSIVE | LK_RETRY);
-                       VOP_OPEN(uvp, FREAD, cred, NULL);
-                       vn_unlock(uvp);
-               }
-               un->un_openl = 0;
-       }
-
-       return (error);
-
-}
-
-/*
- *     union_relookup:
- *
- *     dvp should be locked on entry and will be locked on return.  No
- *     net change in the ref count will occur.
- *
- *     If an error is returned, *vpp will be invalid, otherwise it
- *     will hold a locked, referenced vnode.  If *vpp == dvp then
- *     remember that only one exclusive lock is held.
- */
-
-static int
-union_relookup(struct union_mount *um, struct vnode *dvp, struct vnode **vpp,
-              struct componentname *cnp, struct componentname *cn, char *path,
-              int pathlen)
-{
-       int error;
-
-       /*
-        * A new componentname structure must be faked up because
-        * there is no way to know where the upper level cnp came
-        * from or what it is being used for.  This must duplicate
-        * some of the work done by NDINIT, some of the work done
-        * by namei, some of the work done by lookup and some of
-        * the work done by VOP_LOOKUP when given a CREATE flag.
-        * Conclusion: Horrible.
-        */
-       cn->cn_namelen = pathlen;
-       cn->cn_nameptr = objcache_get(namei_oc, M_WAITOK);
-       bcopy(path, cn->cn_nameptr, cn->cn_namelen);
-       cn->cn_nameptr[cn->cn_namelen] = '\0';
-
-       cn->cn_nameiop = NAMEI_CREATE;
-       cn->cn_flags = CNP_LOCKPARENT;
-       cn->cn_td = cnp->cn_td;
-       if (um->um_op == UNMNT_ABOVE)
-               cn->cn_cred = cnp->cn_cred;
-       else
-               cn->cn_cred = um->um_cred;
-       cn->cn_consume = cnp->cn_consume;
-
-       vref(dvp);
-       vn_unlock(dvp);
-
-       /*
-        * Pass dvp unlocked and referenced on call to relookup().
-        *
-        * If an error occurs, dvp will be returned unlocked and dereferenced.
-        */
-
-       if ((error = relookup(dvp, vpp, cn)) != 0) {
-               objcache_put(namei_oc, cn->cn_nameptr);
-               vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
-               return(error);
-       }
-       objcache_put(namei_oc, cn->cn_nameptr);
-
-       /*
-        * If no error occurs, dvp will be returned locked with the reference
-        * left as before, and vpp will be returned referenced and locked.
-        *
-        * We want to return with dvp as it was passed to us, so we get
-        * rid of our reference.
-        */
-       vrele(dvp);
-       return (0);
-}
-
-/*
- * Create a shadow directory in the upper layer.
- * The new vnode is returned locked.
- *
- * (um) points to the union mount structure for access to the
- * the mounting process's credentials.
- * (dvp) is the directory in which to create the shadow directory,
- * it is locked (but not ref'd) on entry and return.
- * (cnp) is the componentname to be created.
- * (vpp) is the returned newly created shadow directory, which
- * is returned locked and ref'd
- */
-int
-union_mkshadow(struct union_mount *um, struct vnode *dvp,
-              struct componentname *cnp, struct vnode **vpp)
-{
-       int error;
-       struct vattr va;
-       struct thread *td = cnp->cn_td;
-       struct componentname cn;
-
-       error = union_relookup(um, dvp, vpp, cnp, &cn,
-                       cnp->cn_nameptr, cnp->cn_namelen);
-       if (error)
-               return (error);
-
-       if (*vpp) {
-               if (dvp == *vpp)
-                       vrele(*vpp);
-               else
-                       vput(*vpp);
-               *vpp = NULLVP;
-               return (EEXIST);
-       }
-
-       /*
-        * policy: when creating the shadow directory in the
-        * upper layer, create it owned by the user who did
-        * the mount, group from parent directory, and mode
-        * 777 modified by umask (ie mostly identical to the
-        * mkdir syscall).  (jsp, kb)
-        */
-
-       VATTR_NULL(&va);
-       va.va_type = VDIR;
-       va.va_mode = um->um_cmode;
-
-       error = VOP_MKDIR(dvp, vpp, &cn, &va);
-       /*vput(dvp);*/
-       return (error);
-}
-
-/*
- * Create a whiteout entry in the upper layer.
- *
- * (um) points to the union mount structure for access to the
- * the mounting process's credentials.
- * (dvp) is the directory in which to create the whiteout.
- * it is locked on entry and return.
- * (cnp) is the componentname to be created.
- */
-int
-union_mkwhiteout(struct union_mount *um, struct vnode *dvp,
-                struct componentname *cnp, char *path)
-{
-       int error;
-       struct thread *td = cnp->cn_td;
-       struct vnode *wvp;
-       struct componentname cn;
-
-       KKASSERT(td->td_proc);
-
-       error = union_relookup(um, dvp, &wvp, cnp, &cn, path, strlen(path));
-       if (error)
-               return (error);
-
-       if (wvp) {
-               if (wvp == dvp)
-                       vrele(wvp);
-               else
-                       vput(wvp);
-               return (EEXIST);
-       }
-
-       error = VOP_WHITEOUT(dvp, &cn, NAMEI_CREATE);
-       return (error);
-}
-
-/*
- * union_vn_create: creates and opens a new shadow file
- * on the upper union layer.  this function is similar
- * in spirit to calling vn_open but it avoids calling namei().
- * the problem with calling namei is that a) it locks too many
- * things, and b) it doesn't start at the "right" directory,
- * whereas relookup is told where to start.
- *
- * On entry, the vnode associated with un is locked.  It remains locked
- * on return.
- *
- * If no error occurs, *vpp contains a locked referenced vnode for your
- * use.  If an error occurs *vpp iis undefined.
- */
-static int
-union_vn_create(struct vnode **vpp, struct union_node *un, struct thread *td)
-{
-       struct vnode *vp;
-       struct ucred *cred;
-       struct vattr vat;
-       struct vattr *vap = &vat;
-       int fmode = FFLAGS(O_WRONLY|O_CREAT|O_TRUNC|O_EXCL);
-       int error;
-       int cmode;
-       struct componentname cn;
-
-       KKASSERT(td->td_proc);
-       cred = td->td_proc->p_ucred;
-       cmode = UN_FILEMODE & ~td->td_proc->p_fd->fd_cmask;
-
-       *vpp = NULLVP;
-
-       /*
-        * Build a new componentname structure (for the same
-        * reasons outlines in union_mkshadow).
-        * The difference here is that the file is owned by
-        * the current user, rather than by the person who
-        * did the mount, since the current user needs to be
-        * able to write the file (that's why it is being
-        * copied in the first place).
-        */
-       cn.cn_namelen = strlen(un->un_path);
-       cn.cn_nameptr = objcache_get(namei_oc, M_WAITOK);
-       bcopy(un->un_path, cn.cn_nameptr, cn.cn_namelen+1);
-       cn.cn_nameiop = NAMEI_CREATE;
-       cn.cn_flags = CNP_LOCKPARENT;
-       cn.cn_td = td;
-       cn.cn_cred = cred;
-       cn.cn_consume = 0;
-
-       /*
-        * Pass dvp unlocked and referenced on call to relookup().
-        *
-        * If an error occurs, dvp will be returned unlocked and dereferenced.
-        */
-       vref(un->un_dirvp);
-       error = relookup(un->un_dirvp, &vp, &cn);
-       objcache_put(namei_oc, cn.cn_nameptr);
-       if (error)
-               return (error);
-
-       /*
-        * If no error occurs, dvp will be returned locked with the reference
-        * left as before, and vpp will be returned referenced and locked.
-        */
-       if (vp) {
-               vput(un->un_dirvp);
-               if (vp == un->un_dirvp)
-                       vrele(vp);
-               else
-                       vput(vp);
-               return (EEXIST);
-       }
-
-       /*
-        * Good - there was no race to create the file
-        * so go ahead and create it.  The permissions
-        * on the file will be 0666 modified by the
-        * current user's umask.  Access to the file, while
-        * it is unioned, will require access to the top *and*
-        * bottom files.  Access when not unioned will simply
-        * require access to the top-level file.
-        * TODO: confirm choice of access permissions.
-        */
-       VATTR_NULL(vap);
-       vap->va_type = VREG;
-       vap->va_mode = cmode;
-       error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap);
-       vput(un->un_dirvp);
-       if (error)
-               return (error);
-
-       error = VOP_OPEN(vp, fmode, cred, NULL);
-       if (error) {
-               vput(vp);
-               return (error);
-       }
-       *vpp = vp;
-       return (0);
-}
-
-static int
-union_vn_close(struct vnode *vp, int fmode, struct ucred *cred)
-{
-       return (VOP_CLOSE(vp, fmode));
-}
-
-#if 0
-
-/*
- *     union_removed_upper:
- *
- *     called with union_node unlocked. XXX
- */
-
-void
-union_removed_upper(struct union_node *un)
-{
-       struct thread *td = curthread;  /* XXX */
-       struct vnode **vpp;
-
-       /*
-        * Do not set the uppervp to NULLVP.  If lowervp is NULLVP,
-        * union node will have neither uppervp nor lowervp.  We remove
-        * the union node from cache, so that it will not be referrenced.
-        */
-       union_newupper(un, NULLVP);
-       if (un->un_dircache != 0) {
-               for (vpp = un->un_dircache; *vpp != NULLVP; vpp++)
-                       vrele(*vpp);
-               kfree(un->un_dircache, M_TEMP);
-               un->un_dircache = 0;
-       }
-
-       if (un->un_flags & UN_CACHED) {
-               un->un_flags &= ~UN_CACHED;
-               LIST_REMOVE(un, un_cache);
-       }
-}
-
-#endif
-
-/*
- * determine whether a whiteout is needed
- * during a remove/rmdir operation.
- */
-int
-union_dowhiteout(struct union_node *un, struct ucred *cred, struct thread *td)
-{
-       struct vattr va;
-
-       if (un->un_lowervp != NULLVP)
-               return (1);
-
-       if (VOP_GETATTR(un->un_uppervp, &va) == 0 &&
-           (va.va_flags & OPAQUE))
-               return (1);
-
-       return (0);
-}
-
-static void
-union_dircache_r(struct vnode *vp, struct vnode ***vppp, int *cntp)
-{
-       struct union_node *un;
-
-       if (vp->v_tag != VT_UNION) {
-               if (vppp) {
-                       vref(vp);
-                       *(*vppp)++ = vp;
-                       if (--(*cntp) == 0)
-                               panic("union: dircache table too small");
-               } else {
-                       (*cntp)++;
-               }
-
-               return;
-       }
-
-       un = VTOUNION(vp);
-       if (un->un_uppervp != NULLVP)
-               union_dircache_r(un->un_uppervp, vppp, cntp);
-       if (un->un_lowervp != NULLVP)
-               union_dircache_r(un->un_lowervp, vppp, cntp);
-}
-
-struct vnode *
-union_dircache(struct vnode *vp, struct thread *td)
-{
-       int cnt;
-       struct vnode *nvp;
-       struct vnode **vpp;
-       struct vnode **dircache;
-       struct union_node *un;
-       int error;
-
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-       dircache = VTOUNION(vp)->un_dircache;
-
-       nvp = NULLVP;
-
-       if (dircache == NULL) {
-               cnt = 0;
-               union_dircache_r(vp, 0, &cnt);
-               cnt++;
-               dircache = malloc(cnt * sizeof(struct vnode *),
-                               M_TEMP, M_WAITOK);
-               vpp = dircache;
-               union_dircache_r(vp, &vpp, &cnt);
-               *vpp = NULLVP;
-               vpp = dircache + 1;
-       } else {
-               vpp = dircache;
-               do {
-                       if (*vpp++ == VTOUNION(vp)->un_uppervp)
-                               break;
-               } while (*vpp != NULLVP);
-       }
-
-       if (*vpp == NULLVP)
-               goto out;
-
-       /*vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);*/
-       UDEBUG(("ALLOCVP-3 %p ref %08x\n",
-               *vpp, (*vpp ? (*vpp)->v_refcnt : -99)));
-       vref(*vpp);
-       error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, NULL, *vpp, NULLVP, 0);
-       UDEBUG(("ALLOCVP-3B %p ref %08x\n",
-               nvp, (*vpp ? (*vpp)->v_refcnt : -99)));
-       if (error)
-               goto out;
-
-       VTOUNION(vp)->un_dircache = 0;
-       un = VTOUNION(nvp);
-       un->un_dircache = dircache;
-
-out:
-       vn_unlock(vp);
-       return (nvp);
-}
-
-/*
- * Guarentee coherency with the VM cache by invalidating any clean VM pages
- * associated with this write and updating any dirty VM pages.  Since our
- * vnode is locked, other processes will not be able to read the pages in
- * again until after our write completes.
- *
- * We also have to be coherent with reads, by flushing any pending dirty
- * pages prior to issuing the read.
- *
- * XXX this is somewhat of a hack at the moment.  To support this properly
- * we would have to be able to run VOP_READ and VOP_WRITE through the VM
- * cache.  Then we wouldn't need to worry about coherency.
- */
-
-void 
-union_vm_coherency(struct vnode *vp, struct uio *uio, int cleanfls)
-{
-       vm_object_t object;
-       vm_pindex_t pstart;
-       vm_pindex_t pend;
-       int pgoff;
-
-       if ((object = vp->v_object) == NULL)
-           return;
-
-       pgoff = uio->uio_offset & PAGE_MASK;
-       pstart = uio->uio_offset / PAGE_SIZE;
-       pend = pstart + (uio->uio_resid + pgoff + PAGE_MASK) / PAGE_SIZE;
-
-       vm_object_page_clean(object, pstart, pend, OBJPC_SYNC);
-       if (cleanfls)
-               vm_object_page_remove(object, pstart, pend, TRUE);
-}
-
-/*
- * Module glue to remove #ifdef UNION from vfs_syscalls.c
- */
-static int
-union_dircheck(struct thread *td, struct vnode **vp, struct file *fp)
-{
-       int error = 0;
-
-       if ((*vp)->v_tag == VT_UNION) {
-               struct vnode *lvp;
-
-               lvp = union_dircache(*vp, td);
-               if (lvp != NULLVP) {
-                       struct vattr va;
-
-                       /*
-                        * If the directory is opaque,
-                        * then don't show lower entries
-                        */
-                       error = VOP_GETATTR(*vp, &va);
-                       if (va.va_flags & OPAQUE) {
-                               vput(lvp);
-                               lvp = NULL;
-                       }
-               }
-
-               if (lvp != NULLVP) {
-                       error = VOP_OPEN(lvp, FREAD, fp->f_cred, NULL);
-                       if (error) {
-                               vput(lvp);
-                               return (error);
-                       }
-                       vn_unlock(lvp);
-                       fp->f_data = lvp;
-                       fp->f_offset = 0;
-                       error = vn_close(*vp, FREAD);
-                       if (error)
-                               return (error);
-                       *vp = lvp;
-                       return -1;      /* goto unionread */
-               }
-       }
-       return error;
-}
-
-static int
-union_modevent(module_t mod, int type, void *data)
-{
-       switch (type) {
-       case MOD_LOAD:
-               union_dircheckp = union_dircheck;
-               break;
-       case MOD_UNLOAD:
-               union_dircheckp = NULL;
-               break;
-       default:
-               break;
-       }
-       return 0;
-}
-
-static moduledata_t union_mod = {
-       "union_dircheck",
-       union_modevent,
-       NULL
-};
-
-DECLARE_MODULE(union_dircheck, union_mod, SI_SUB_VFS, SI_ORDER_ANY);
diff --git a/sys/vfs/union/union_vfsops.c b/sys/vfs/union/union_vfsops.c
deleted file mode 100644 (file)
index a856adb..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (c) 1994, 1995 The Regents of the University of California.
- * Copyright (c) 1994, 1995 Jan-Simon Pendry.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     @(#)union_vfsops.c      8.20 (Berkeley) 5/20/95
- * $FreeBSD: src/sys/miscfs/union/union_vfsops.c,v 1.39.2.2 2001/10/25 19:18:53 dillon Exp $
- */
-
-/*
- * Union Layer
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-#include <sys/nlookup.h>
-#include <sys/namei.h>
-#include <sys/malloc.h>
-#include <sys/filedesc.h>
-#include "union.h"
-#include <vm/vm_zone.h>
-
-extern struct vop_ops union_vnode_vops;
-
-static MALLOC_DEFINE(M_UNIONFSMNT, "UNION mount", "UNION mount structure");
-
-extern int     union_init (struct vfsconf *);
-static int     union_mount (struct mount *mp, char *path, caddr_t data,
-                                struct ucred *cred);
-static int     union_root (struct mount *mp, struct vnode **vpp);
-static int     union_statfs (struct mount *mp, struct statfs *sbp,
-                               struct ucred *cred);
-static int     union_unmount (struct mount *mp, int mntflags);
-
-/*
- * Mount union filesystem
- */
-static int
-union_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
-{
-       int error = 0;
-       struct union_args args;
-       struct vnode *lowerrootvp = NULLVP;
-       struct vnode *upperrootvp = NULLVP;
-       struct union_mount *um = NULL;
-       struct ucred *cred = NULL;
-       struct nlookupdata nd;
-       char *cp = NULL;
-       int len;
-       u_int size;
-
-       UDEBUG(("union_mount(mp = %p)\n", (void *)mp));
-
-       /*
-        * Disable clustered write, otherwise system becomes unstable.
-        */
-       mp->mnt_flag |= MNT_NOCLUSTERW;
-
-       /*
-        * Update is a no-op
-        */
-       if (mp->mnt_flag & MNT_UPDATE) {
-               /*
-                * Need to provide.
-                * 1. a way to convert between rdonly and rdwr mounts.
-                * 2. support for nfs exports.
-                */
-               error = EOPNOTSUPP;
-               goto bad;
-       }
-
-       /*
-        * Get argument
-        */
-       error = copyin(data, (caddr_t)&args, sizeof(struct union_args));
-       if (error)
-               goto bad;
-
-       /*
-        * Obtain lower vnode. 
-        */
-
-       lowerrootvp = mp->mnt_vnodecovered;
-       vref(lowerrootvp);
-
-#if 0
-       /*
-        * Unlock lower node to avoid deadlock.
-        */
-       if (lowerrootvp->v_tag == VT_UNION)
-               vn_unlock(lowerrootvp);
-#endif
-
-       /*
-        * Obtain upper vnode by calling nlookup() on the path.  The
-        * upperrootvp will be turned referenced but not locked.
-        */
-       error = nlookup_init(&nd, args.target, UIO_USERSPACE, NLC_FOLLOW);
-       if (error == 0)
-               error = nlookup(&nd);
-       if (error == 0)
-               error = cache_vref(&nd.nl_nch, nd.nl_cred, &upperrootvp);
-       nlookup_done(&nd);
-       if (error)
-               goto bad;
-
-       UDEBUG(("mount_root UPPERVP %p locked = %d\n", upperrootvp,
-           vn_islocked(upperrootvp)));
-
-       /*
-        * Check multi union mount to avoid `lock myself again' panic.
-        * Also require that it be a directory.
-        */
-       if (upperrootvp == VTOUNION(lowerrootvp)->un_uppervp) {
-#ifdef DIAGNOSTIC
-               kprintf("union_mount: multi union mount?\n");
-#endif
-               error = EDEADLK;
-               goto bad;
-       }
-
-       if (upperrootvp->v_type != VDIR) {
-               error = EINVAL;
-               goto bad;
-       }
-
-       /*
-        * Allocate our union_mount structure and populate the fields.
-        * The vnode references are stored in the union_mount as held,
-        * unlocked references.  Depending on the _BELOW flag, the
-        * filesystems are viewed in a different order.  In effect this
-        * is the same as providing a mount-under option to the mount
-        * syscall.
-        */
-
-       um = (struct union_mount *) malloc(sizeof(struct union_mount),
-                               M_UNIONFSMNT, M_WAITOK);
-
-       bzero(um, sizeof(struct union_mount));
-
-       um->um_op = args.mntflags & UNMNT_OPMASK;
-
-       switch (um->um_op) {
-       case UNMNT_ABOVE:
-               um->um_lowervp = lowerrootvp;
-               um->um_uppervp = upperrootvp;
-               upperrootvp = NULL;
-               lowerrootvp = NULL;
-               break;
-
-       case UNMNT_BELOW:
-               um->um_lowervp = upperrootvp;
-               um->um_uppervp = lowerrootvp;
-               upperrootvp = NULL;
-               lowerrootvp = NULL;
-               break;
-
-       case UNMNT_REPLACE:
-               vrele(lowerrootvp);
-               lowerrootvp = NULL;
-               um->um_uppervp = upperrootvp;
-               um->um_lowervp = lowerrootvp;
-               upperrootvp = NULL;
-               break;
-
-       default:
-               error = EINVAL;
-               goto bad;
-       }
-
-       /*
-        * Unless the mount is readonly, ensure that the top layer
-        * supports whiteout operations
-        */
-       if ((mp->mnt_flag & MNT_RDONLY) == 0) {
-               error = VOP_WHITEOUT(um->um_uppervp, NULL, NAMEI_LOOKUP);
-               if (error)
-                       goto bad;
-       }
-
-       /*
-        * File creds and modes for shadowed files are based on the user
-        * that did the mount.
-        */
-       um->um_cred = crhold(cred);
-       um->um_cmode = UN_DIRMODE;
-       if (curproc)
-               um->um_cmode &= ~curproc->p_fd->fd_cmask;
-
-       /*
-        * Depending on what you think the MNT_LOCAL flag might mean,
-        * you may want the && to be || on the conditional below.
-        * At the moment it has been defined that the filesystem is
-        * only local if it is all local, ie the MNT_LOCAL flag implies
-        * that the entire namespace is local.  If you think the MNT_LOCAL
-        * flag implies that some of the files might be stored locally
-        * then you will want to change the conditional.
-        */
-       if (um->um_op == UNMNT_ABOVE) {
-               if (((um->um_lowervp == NULLVP) ||
-                    (um->um_lowervp->v_mount->mnt_flag & MNT_LOCAL)) &&
-                   (um->um_uppervp->v_mount->mnt_flag & MNT_LOCAL))
-                       mp->mnt_flag |= MNT_LOCAL;
-       }
-
-       /*
-        * Copy in the upper layer's RDONLY flag.  This is for the benefit
-        * of lookup() which explicitly checks the flag, rather than asking
-        * the filesystem for its own opinion.  This means, that an update
-        * mount of the underlying filesystem to go from rdonly to rdwr
-        * will leave the unioned view as read-only.
-        */
-       mp->mnt_flag |= (um->um_uppervp->v_mount->mnt_flag & MNT_RDONLY);
-
-       mp->mnt_data = (qaddr_t) um;
-       vfs_getnewfsid(mp);
-
-       switch (um->um_op) {
-       case UNMNT_ABOVE:
-               cp = "<above>:";
-               break;
-       case UNMNT_BELOW:
-               cp = "<below>:";
-               break;
-       case UNMNT_REPLACE:
-               cp = "";
-               break;
-       }
-       len = strlen(cp);
-       bcopy(cp, mp->mnt_stat.f_mntfromname, len);
-
-       cp = mp->mnt_stat.f_mntfromname + len;
-       len = MNAMELEN - len;
-
-       (void) copyinstr(args.target, cp, len - 1, &size);
-       bzero(cp + size, len - size);
-
-       vfs_add_vnodeops(mp, &union_vnode_vops, &mp->mnt_vn_norm_ops);
-
-       (void)union_statfs(mp, &mp->mnt_stat, cred);
-
-       return (0);
-
-bad:
-       if (um) {
-               if (um->um_uppervp)
-                       vrele(um->um_uppervp);
-               if (um->um_lowervp)
-                       vrele(um->um_lowervp);
-               /* XXX other fields */
-               kfree(um, M_UNIONFSMNT);
-       }
-       if (cred)
-               crfree(cred);
-       if (upperrootvp)
-               vrele(upperrootvp);
-       if (lowerrootvp)
-               vrele(lowerrootvp);
-       return (error);
-}
-
-/*
- * Free reference to union layer
- */
-static int
-union_unmount(struct mount *mp, int mntflags)
-{
-       struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
-       int error;
-       int freeing;
-       int flags = 0;
-
-       UDEBUG(("union_unmount(mp = %p)\n", (void *)mp));
-
-       if (mntflags & MNT_FORCE)
-               flags |= FORCECLOSE;
-
-       /*
-        * Keep flushing vnodes from the mount list.
-        * This is needed because of the un_pvp held
-        * reference to the parent vnode.
-        * If more vnodes have been freed on a given pass,
-        * the try again.  The loop will iterate at most
-        * (d) times, where (d) is the maximum tree depth
-        * in the filesystem.
-        */
-       for (freeing = 0; (error = vflush(mp, 0, flags)) != 0;) {
-               int n = mp->mnt_nvnodelistsize;
-
-               /* if this is unchanged then stop */
-               if (n == freeing)
-                       break;
-
-               /* otherwise try once more time */
-               freeing = n;
-       }
-
-       /* If the most recent vflush failed, the filesystem is still busy. */
-       if (error)
-               return (error);
-
-       /*
-        * Discard references to upper and lower target vnodes.
-        */
-       if (um->um_lowervp)
-               vrele(um->um_lowervp);
-       vrele(um->um_uppervp);
-       crfree(um->um_cred);
-       /*
-        * Finally, throw away the union_mount structure
-        */
-       kfree(mp->mnt_data, M_UNIONFSMNT);      /* XXX */
-       mp->mnt_data = 0;
-       return (0);
-}
-
-static int
-union_root(struct mount *mp, struct vnode **vpp)
-{
-       struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
-       int error;
-
-       /*
-        * Supply an unlocked reference to um_uppervp and to um_lowervp.  It
-        * is possible for um_uppervp to be locked without the associated
-        * root union_node being locked.  We let union_allocvp() deal with
-        * it.
-        */
-       UDEBUG(("union_root UPPERVP %p locked = %d\n", um->um_uppervp,
-           vn_islocked(um->um_uppervp)));
-
-       vref(um->um_uppervp);
-       if (um->um_lowervp)
-               vref(um->um_lowervp);
-
-       error = union_allocvp(vpp, mp, NULLVP, NULLVP, NULL, 
-                   um->um_uppervp, um->um_lowervp, 1);
-       UDEBUG(("error %d\n", error));
-       UDEBUG(("union_root2 UPPERVP %p locked = %d\n", um->um_uppervp,
-           vn_islocked(um->um_uppervp)));
-
-       return (error);
-}
-
-static int
-union_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
-{
-       int error;
-       struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
-       struct statfs mstat;
-       int lbsize;
-
-       UDEBUG(("union_statfs(mp = %p, lvp = %p, uvp = %p)\n",
-           (void *)mp, (void *)um->um_lowervp, (void *)um->um_uppervp));
-
-       bzero(&mstat, sizeof(mstat));
-
-       if (um->um_lowervp) {
-               error = VFS_STATFS(um->um_lowervp->v_mount, &mstat, cred);
-               if (error)
-                       return (error);
-       }
-
-       /* now copy across the "interesting" information and fake the rest */
-#if 0
-       sbp->f_type = mstat.f_type;
-       sbp->f_flags = mstat.f_flags;
-       sbp->f_bsize = mstat.f_bsize;
-       sbp->f_iosize = mstat.f_iosize;
-#endif
-       lbsize = mstat.f_bsize;
-       sbp->f_blocks = mstat.f_blocks;
-       sbp->f_bfree = mstat.f_bfree;
-       sbp->f_bavail = mstat.f_bavail;
-       sbp->f_files = mstat.f_files;
-       sbp->f_ffree = mstat.f_ffree;
-
-       error = VFS_STATFS(um->um_uppervp->v_mount, &mstat, cred);
-       if (error)
-               return (error);
-
-       sbp->f_flags = mstat.f_flags;
-       sbp->f_bsize = mstat.f_bsize;
-       sbp->f_iosize = mstat.f_iosize;
-
-       /*
-        * if the lower and upper blocksizes differ, then frig the
-        * block counts so that the sizes reported by df make some
-        * kind of sense.  none of this makes sense though.
-        */
-
-       if (mstat.f_bsize != lbsize)
-               sbp->f_blocks = ((off_t) sbp->f_blocks * lbsize) / mstat.f_bsize;
-
-       /*
-        * The "total" fields count total resources in all layers,
-        * the "free" fields count only those resources which are
-        * free in the upper layer (since only the upper layer
-        * is writeable).
-        */
-       sbp->f_blocks += mstat.f_blocks;
-       sbp->f_bfree = mstat.f_bfree;
-       sbp->f_bavail = mstat.f_bavail;
-       sbp->f_files += mstat.f_files;
-       sbp->f_ffree = mstat.f_ffree;
-
-       if (sbp != &mp->mnt_stat) {
-               sbp->f_type = mp->mnt_vfc->vfc_typenum;
-               bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
-               bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
-       }
-       return (0);
-}
-
-static struct vfsops union_vfsops = {
-       .vfs_mount =            union_mount,
-       .vfs_unmount =          union_unmount,
-       .vfs_root =             union_root,
-       .vfs_statfs =           union_statfs,
-       .vfs_sync =             vfs_stdsync,
-       .vfs_init =             union_init
-};
-
-VFS_SET(union_vfsops, union, VFCF_LOOPBACK);
diff --git a/sys/vfs/union/union_vnops.c b/sys/vfs/union/union_vnops.c
deleted file mode 100644 (file)
index 479aa0b..0000000
+++ /dev/null
@@ -1,1795 +0,0 @@
-/*
- * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
- * Copyright (c) 1992, 1993, 1994, 1995
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     @(#)union_vnops.c       8.32 (Berkeley) 6/23/95
- * $FreeBSD: src/sys/miscfs/union/union_vnops.c,v 1.72 1999/12/15 23:02:14 eivind Exp $
- * $DragonFly: src/sys/vfs/union/union_vnops.c,v 1.39 2007/11/20 21:03:51 dillon Exp $
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-#include <sys/kernel.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/lock.h>
-#include <sys/sysctl.h>
-#include "union.h"
-
-#include <vm/vm.h>
-#include <vm/vnode_pager.h>
-
-#include <vm/vm_page.h>
-#include <vm/vm_object.h>
-
-int uniondebug = 0;
-
-#if UDEBUG_ENABLED
-SYSCTL_INT(_vfs, OID_AUTO, uniondebug, CTLFLAG_RW, &uniondebug, 0, "");
-#else
-SYSCTL_INT(_vfs, OID_AUTO, uniondebug, CTLFLAG_RD, &uniondebug, 0, "");
-#endif
-
-static int     union_access (struct vop_access_args *ap);
-static int     union_advlock (struct vop_advlock_args *ap);
-static int     union_bmap (struct vop_bmap_args *ap);
-static int     union_close (struct vop_close_args *ap);
-static int     union_create (struct vop_old_create_args *ap);
-static int     union_fsync (struct vop_fsync_args *ap);
-static int     union_getattr (struct vop_getattr_args *ap);
-static int     union_inactive (struct vop_inactive_args *ap);
-static int     union_ioctl (struct vop_ioctl_args *ap);
-static int     union_link (struct vop_old_link_args *ap);
-static int     union_lookup (struct vop_old_lookup_args *ap);
-static int     union_lookup1 (struct vnode *udvp, struct vnode **dvp,
-                                  struct vnode **vpp,
-                                  struct componentname *cnp);
-static int     union_mkdir (struct vop_old_mkdir_args *ap);
-static int     union_mknod (struct vop_old_mknod_args *ap);
-static int     union_mmap (struct vop_mmap_args *ap);
-static int     union_open (struct vop_open_args *ap);
-static int     union_pathconf (struct vop_pathconf_args *ap);
-static int     union_print (struct vop_print_args *ap);
-static int     union_read (struct vop_read_args *ap);
-static int     union_readdir (struct vop_readdir_args *ap);
-static int     union_readlink (struct vop_readlink_args *ap);
-static int     union_reclaim (struct vop_reclaim_args *ap);
-static int     union_remove (struct vop_old_remove_args *ap);
-static int     union_rename (struct vop_old_rename_args *ap);
-static int     union_rmdir (struct vop_old_rmdir_args *ap);
-static int     union_poll (struct vop_poll_args *ap);
-static int     union_setattr (struct vop_setattr_args *ap);
-static int     union_strategy (struct vop_strategy_args *ap);
-static int     union_getpages (struct vop_getpages_args *ap);
-static int     union_putpages (struct vop_putpages_args *ap);
-static int     union_symlink (struct vop_old_symlink_args *ap);
-static int     union_whiteout (struct vop_old_whiteout_args *ap);
-static int     union_write (struct vop_read_args *ap);
-
-static __inline
-struct vnode *
-union_lock_upper(struct union_node *un, struct thread *td)
-{
-       struct vnode *uppervp;
-
-       if ((uppervp = un->un_uppervp) != NULL) {
-               vref(uppervp);
-               vn_lock(uppervp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY);
-       }
-       KASSERT((uppervp == NULL || VREFCNT(uppervp) > 0),
-               ("uppervp usecount is 0"));
-       return(uppervp);
-}
-
-static __inline
-struct vnode *
-union_ref_upper(struct union_node *un)
-{
-       struct vnode *uppervp;
-
-       if ((uppervp = un->un_uppervp) != NULL) {
-               vref(uppervp);
-               if (uppervp->v_flag & VRECLAIMED) {
-                       vrele(uppervp);
-                       return (NULLVP);
-               }
-       }
-       return (uppervp);
-}
-
-static __inline
-void
-union_unlock_upper(struct vnode *uppervp, struct thread *td)
-{
-       vput(uppervp);
-}
-
-static __inline
-struct vnode *
-union_lock_other(struct union_node *un, struct thread *td)
-{
-       struct vnode *vp;
-
-       if (un->un_uppervp != NULL) {
-               vp = union_lock_upper(un, td);
-       } else if ((vp = un->un_lowervp) != NULL) {
-               vref(vp);
-               vn_lock(vp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY);
-       }
-       return(vp);
-}
-
-static __inline
-void
-union_unlock_other(struct vnode *vp, struct thread *td)
-{
-       vput(vp);
-}
-
-/*
- *     union_lookup:
- *
- *     udvp    must be exclusively locked on call and will remain 
- *             exclusively locked on return.  This is the mount point 
- *             for out filesystem.
- *
- *     dvp     Our base directory, locked and referenced.
- *             The passed dvp will be dereferenced and unlocked on return
- *             and a new dvp will be returned which is locked and 
- *             referenced in the same variable.
- *
- *     vpp     is filled in with the result if no error occured,
- *             locked and ref'd.
- *
- *             If an error is returned, *vpp is set to NULLVP.  If no
- *             error occurs, *vpp is returned with a reference and an
- *             exclusive lock.
- */
-
-static int
-union_lookup1(struct vnode *udvp, struct vnode **pdvp, struct vnode **vpp,
-             struct componentname *cnp)
-{
-       int error;
-       struct thread *td = cnp->cn_td;
-       struct vnode *dvp = *pdvp;
-       struct vnode *tdvp;
-       struct mount *mp;
-
-       /*
-        * If stepping up the directory tree, check for going
-        * back across the mount point, in which case do what
-        * lookup would do by stepping back down the mount
-        * hierarchy.
-        */
-       if (cnp->cn_flags & CNP_ISDOTDOT) {
-               while ((dvp != udvp) && (dvp->v_flag & VROOT)) {
-                       /*
-                        * Don't do the NOCROSSMOUNT check
-                        * at this level.  By definition,
-                        * union fs deals with namespaces, not
-                        * filesystems.
-                        */
-                       tdvp = dvp;
-                       dvp = dvp->v_mount->mnt_vnodecovered;
-                       vref(dvp);
-                       vput(tdvp);
-                       vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
-               }
-       }
-
-       /*
-        * Set return dvp to be the upperdvp 'parent directory.
-        */
-       *pdvp = dvp;
-
-       /*
-        * If the VOP_LOOKUP call generates an error, tdvp is invalid and no
-        * changes will have been made to dvp, so we are set to return.
-        */
-
-        error = VOP_LOOKUP(dvp, &tdvp, cnp);
-       if (error) {
-               UDEBUG(("dvp %p error %d flags %lx\n", dvp, error, cnp->cn_flags));
-               *vpp = NULL;
-               return (error);
-       }
-
-       /*
-        * The parent directory will have been unlocked, unless lookup
-        * found the last component or if dvp == tdvp (tdvp must be locked).
-        *
-        * We want our dvp to remain locked and ref'd.  We also want tdvp
-        * to remain locked and ref'd.
-        */
-       UDEBUG(("parentdir %p result %p flag %lx\n", dvp, tdvp, cnp->cn_flags));
-
-#if 0
-       if (dvp != tdvp && (cnp->cn_flags & CNP_XXXISLASTCN) == 0)
-               vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
-#endif
-
-       /*
-        * Lastly check if the current node is a mount point in
-        * which case walk up the mount hierarchy making sure not to
-        * bump into the root of the mount tree (ie. dvp != udvp).
-        *
-        * We use dvp as a temporary variable here, it is no longer related
-        * to the dvp above.  However, we have to ensure that both *pdvp and
-        * tdvp are locked on return.
-        */
-
-       dvp = tdvp;
-       while (
-           dvp != udvp && 
-           (dvp->v_type == VDIR) &&
-           (mp = dvp->v_mountedhere)
-       ) {
-               int relock_pdvp = 0;
-
-               if (vfs_busy(mp, 0))
-                       continue;
-
-               if (dvp == *pdvp)
-                       relock_pdvp = 1;
-               vput(dvp);
-               dvp = NULL;
-               error = VFS_ROOT(mp, &dvp);
-
-               vfs_unbusy(mp);
-
-               if (relock_pdvp)
-                       vn_lock(*pdvp, LK_EXCLUSIVE | LK_RETRY);
-
-               if (error) {
-                       *vpp = NULL;
-                       return (error);
-               }
-       }
-       *vpp = dvp;
-       return (0);
-}
-
-/*
- * union_lookup(struct vnode *a_dvp, struct vnode **a_vpp,
- *             struct componentname *a_cnp)
- */
-static int
-union_lookup(struct vop_old_lookup_args *ap)
-{
-       int error;
-       int uerror, lerror;
-       struct vnode *uppervp, *lowervp;
-       struct vnode *upperdvp, *lowerdvp;
-       struct vnode *dvp = ap->a_dvp;          /* starting dir */
-       struct union_node *dun = VTOUNION(dvp); /* associated union node */
-       struct componentname *cnp = ap->a_cnp;
-       struct thread *td = cnp->cn_td;
-       int lockparent = cnp->cn_flags & CNP_LOCKPARENT;
-       struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount);
-       struct ucred *saved_cred = NULL;
-       int iswhiteout;
-       struct vattr va;
-
-       *ap->a_vpp = NULLVP;
-
-       /*
-        * Disallow write attemps to the filesystem mounted read-only.
-        */
-       if ((dvp->v_mount->mnt_flag & MNT_RDONLY) &&
-           (cnp->cn_nameiop == NAMEI_DELETE || cnp->cn_nameiop == NAMEI_RENAME)) {
-               return (EROFS);
-       }
-
-       /*
-        * For any lookup's we do, always return with the parent locked
-        */
-       cnp->cn_flags |= CNP_LOCKPARENT;
-
-       lowerdvp = dun->un_lowervp;
-       uppervp = NULLVP;
-       lowervp = NULLVP;
-       iswhiteout = 0;
-
-       uerror = ENOENT;
-       lerror = ENOENT;
-
-       /*
-        * Get a private lock on uppervp and a reference, effectively 
-        * taking it out of the union_node's control.
-        *
-        * We must lock upperdvp while holding our lock on dvp
-        * to avoid a deadlock.
-        */
-       upperdvp = union_lock_upper(dun, td);
-
-       /*
-        * do the lookup in the upper level.
-        * if that level comsumes additional pathnames,
-        * then assume that something special is going
-        * on and just return that vnode.
-        */
-       if (upperdvp != NULLVP) {
-               /*
-                * We do not have to worry about the DOTDOT case, we've
-                * already unlocked dvp.
-                */
-               UDEBUG(("A %p\n", upperdvp));
-
-               /*
-                * Do the lookup.   We must supply a locked and referenced
-                * upperdvp to the function and will get a new locked and
-                * referenced upperdvp back with the old having been 
-                * dereferenced.
-                *
-                * If an error is returned, uppervp will be NULLVP.  If no
-                * error occurs, uppervp will be the locked and referenced
-                * return vnode or possibly NULL, depending on what is being
-                * requested.  It is possible that the returned uppervp
-                * will be the same as upperdvp.
-                */
-               uerror = union_lookup1(um->um_uppervp, &upperdvp, &uppervp, cnp);
-               UDEBUG((
-                   "uerror %d upperdvp %p %d/%d, uppervp %p ref=%d/lck=%d\n",
-                   uerror,
-                   upperdvp,
-                   VREFCNT(upperdvp),
-                   vn_islocked(upperdvp),
-                   uppervp,
-                   (uppervp ? VREFCNT(uppervp) : -99),
-                   (uppervp ? vn_islocked(uppervp) : -99)
-               ));
-
-               /*
-                * Disallow write attemps to the filesystem mounted read-only.
-                */
-               if (uerror == EJUSTRETURN && 
-                   (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
-                   (cnp->cn_nameiop == NAMEI_CREATE || cnp->cn_nameiop == NAMEI_RENAME)) {
-                       error = EROFS;
-                       goto out;
-               }
-
-               /*
-                * Special case.  If cn_consume != 0 skip out.  The result
-                * of the lookup is transfered to our return variable.  If
-                * an error occured we have to throw away the results.
-                */
-
-               if (cnp->cn_consume != 0) {
-                       if ((error = uerror) == 0) {
-                               *ap->a_vpp = uppervp;
-                               uppervp = NULL;
-                       }
-                       goto out;
-               }
-
-               /*
-                * Calculate whiteout, fall through
-                */
-
-               if (uerror == ENOENT || uerror == EJUSTRETURN) {
-                       if (cnp->cn_flags & CNP_ISWHITEOUT) {
-                               iswhiteout = 1;
-                       } else if (lowerdvp != NULLVP) {
-                               int terror;
-
-                               terror = VOP_GETATTR(upperdvp, &va);
-                               if (terror == 0 && (va.va_flags & OPAQUE))
-                                       iswhiteout = 1;
-                       }
-               }
-       }
-
-       /*
-        * in a similar way to the upper layer, do the lookup
-        * in the lower layer.   this time, if there is some
-        * component magic going on, then vput whatever we got
-        * back from the upper layer and return the lower vnode
-        * instead.
-        */
-
-       if (lowerdvp != NULLVP && !iswhiteout) {
-               int nameiop;
-
-               UDEBUG(("B %p\n", lowerdvp));
-
-               /*
-                * Force only LOOKUPs on the lower node, since
-                * we won't be making changes to it anyway.
-                */
-               nameiop = cnp->cn_nameiop;
-               cnp->cn_nameiop = NAMEI_LOOKUP;
-               if (um->um_op == UNMNT_BELOW) {
-                       saved_cred = cnp->cn_cred;
-                       cnp->cn_cred = um->um_cred;
-               }
-
-               /*
-                * We shouldn't have to worry about locking interactions
-                * between the lower layer and our union layer (w.r.t.
-                * `..' processing) because we don't futz with lowervp
-                * locks in the union-node instantiation code path.
-                *
-                * union_lookup1() requires lowervp to be locked on entry,
-                * and it will be unlocked on return.  The ref count will
-                * not change.  On return lowervp doesn't represent anything
-                * to us so we NULL it out.
-                */
-               vref(lowerdvp);
-               vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY);
-               lerror = union_lookup1(um->um_lowervp, &lowerdvp, &lowervp, cnp);
-               if (lowerdvp == lowervp)
-                       vrele(lowerdvp);
-               else
-                       vput(lowerdvp);
-               lowerdvp = NULL;        /* lowerdvp invalid after vput */
-
-               if (um->um_op == UNMNT_BELOW)
-                       cnp->cn_cred = saved_cred;
-               cnp->cn_nameiop = nameiop;
-
-               if (cnp->cn_consume != 0 || lerror == EACCES) {
-                       if ((error = lerror) == 0) {
-                               *ap->a_vpp = lowervp;
-                               lowervp = NULL;
-                       }
-                       goto out;
-               }
-       } else {
-               UDEBUG(("C %p\n", lowerdvp));
-               if ((cnp->cn_flags & CNP_ISDOTDOT) && dun->un_pvp != NULLVP) {
-                       if ((lowervp = LOWERVP(dun->un_pvp)) != NULL) {
-                               vref(lowervp);
-                               vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY);
-                               lerror = 0;
-                       }
-               }
-       }
-
-       /*
-        * Ok.  Now we have uerror, uppervp, upperdvp, lerror, and lowervp.
-        *
-        * 1. If both layers returned an error, select the upper layer.
-        *
-        * 2. If the upper layer faile and the bottom layer succeeded,
-        *    two subcases occur:
-        *
-        *      a.  The bottom vnode is not a directory, in which case
-        *          just return a new union vnode referencing an
-        *          empty top layer and the existing bottom layer.
-        *
-        *      b.  The button vnode is a directory, in which case
-        *          create a new directory in the top layer and
-        *          and fall through to case 3.
-        *
-        * 3. If the top layer succeeded then return a new union
-        *    vnode referencing whatever the new top layer and
-        *    whatever the bottom layer returned.
-        */
-
-       /* case 1. */
-       if ((uerror != 0) && (lerror != 0)) {
-               error = uerror;
-               goto out;
-       }
-
-       /* case 2. */
-       if (uerror != 0 /* && (lerror == 0) */ ) {
-               if (lowervp->v_type == VDIR) { /* case 2b. */
-                       KASSERT(uppervp == NULL, ("uppervp unexpectedly non-NULL"));
-                       /*
-                        * oops, uppervp has a problem, we may have to shadow.
-                        */
-                       uerror = union_mkshadow(um, upperdvp, cnp, &uppervp);
-                       if (uerror) {
-                               error = uerror;
-                               goto out;
-                       }
-               }
-       }
-
-       /*
-        * Must call union_allocvp with both the upper and lower vnodes
-        * referenced and the upper vnode locked.   ap->a_vpp is returned 
-        * referenced and locked.  lowervp, uppervp, and upperdvp are 
-        * absorbed by union_allocvp() whether it succeeds or fails.
-        *
-        * upperdvp is the parent directory of uppervp which may be
-        * different, depending on the path, from dvp->un_uppervp.  That's
-        * why it is a separate argument.  Note that it must be unlocked.
-        *
-        * dvp must be locked on entry to the call and will be locked on
-        * return.
-        */
-
-       if (uppervp && uppervp != upperdvp)
-               vn_unlock(uppervp);
-       if (lowervp)
-               vn_unlock(lowervp);
-       if (upperdvp)
-               vn_unlock(upperdvp);
-
-       error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
-                             uppervp, lowervp, 1);
-
-       UDEBUG(("Create %p = %p %p refs=%d\n",
-               *ap->a_vpp, uppervp, lowervp,
-               (*ap->a_vpp) ? (VREFCNT(*ap->a_vpp)) : -99));
-
-       uppervp = NULL;
-       upperdvp = NULL;
-       lowervp = NULL;
-
-       /* 
-        *      Termination Code
-        *
-        *      - put away any extra junk laying around.  Note that lowervp
-        *        (if not NULL) will never be the same as *ap->a_vp and 
-        *        neither will uppervp, because when we set that state we 
-        *        NULL-out lowervp or uppervp.  On the otherhand, upperdvp
-        *        may match uppervp or *ap->a_vpp.
-        *
-        *      - relock/unlock dvp if appropriate.
-        */
-
-out:
-       if (upperdvp) {
-               if (upperdvp == uppervp || upperdvp == *ap->a_vpp)
-                       vrele(upperdvp);
-               else
-                       vput(upperdvp);
-       }
-
-       if (uppervp)
-               vput(uppervp);
-
-       if (lowervp)
-               vput(lowervp);
-
-       /*
-        * Restore LOCKPARENT state
-        */
-
-       if (!lockparent)
-               cnp->cn_flags &= ~CNP_LOCKPARENT;
-
-       UDEBUG(("Out %d vpp %p/%d lower %p upper %p\n", error, *ap->a_vpp,
-               ((*ap->a_vpp) ? (*ap->a_vpp)->v_refcnt : -99),
-               lowervp, uppervp));
-
-       /*
-        * dvp lock state, determine whether to relock dvp.  dvp is expected
-        * to be locked on return if:
-        *
-        *      - there was an error (except not EJUSTRETURN), or
-        *      - we hit the last component and lockparent is true
-        *
-        * dvp_is_locked is the current state of the dvp lock, not counting
-        * the possibility that *ap->a_vpp == dvp (in which case it is locked
-        * anyway).  Note that *ap->a_vpp == dvp only if no error occured.
-        */
-
-       if (*ap->a_vpp != dvp) {
-               if ((error == 0 || error == EJUSTRETURN) && !lockparent) {
-                       vn_unlock(dvp);
-               }
-       }
-
-       /*
-        * Diagnostics
-        */
-
-#ifdef DIAGNOSTIC
-       if (cnp->cn_namelen == 1 &&
-           cnp->cn_nameptr[0] == '.' &&
-           *ap->a_vpp != dvp) {
-               panic("union_lookup returning . (%p) not same as startdir (%p)", ap->a_vpp, dvp);
-       }
-#endif
-
-       return (error);
-}
-
-/*
- *     union_create:
- *
- * a_dvp is locked on entry and remains locked on return.  a_vpp is returned
- * locked if no error occurs, otherwise it is garbage.
- *
- * union_create(struct vnode *a_dvp, struct vnode **a_vpp,
- *             struct componentname *a_cnp, struct vattr *a_vap)
- */
-static int
-union_create(struct vop_old_create_args *ap)
-{
-       struct union_node *dun = VTOUNION(ap->a_dvp);
-       struct componentname *cnp = ap->a_cnp;
-       struct thread *td = cnp->cn_td;
-       struct vnode *dvp;
-       int error = EROFS;
-
-       if ((dvp = union_lock_upper(dun, td)) != NULL) {
-               struct vnode *vp;
-               struct mount *mp;
-
-               error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap);
-               if (error == 0) {
-                       mp = ap->a_dvp->v_mount;
-                       vn_unlock(vp);
-                       UDEBUG(("ALLOCVP-1 FROM %p REFS %d\n",
-                               vp, vp->v_refcnt));
-                       error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
-                               cnp, vp, NULLVP, 1);
-                       UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n",
-                               *ap->a_vpp, vp->v_refcnt));
-               }
-               union_unlock_upper(dvp, td);
-       }
-       return (error);
-}
-
-/*
- * union_whiteout(struct vnode *a_dvp, struct componentname *a_cnp,
- *               int a_flags)
- */
-static int
-union_whiteout(struct vop_old_whiteout_args *ap)
-{
-       struct union_node *un = VTOUNION(ap->a_dvp);
-       struct componentname *cnp = ap->a_cnp;
-       struct vnode *uppervp;
-       int error = EOPNOTSUPP;
-
-       if ((uppervp = union_lock_upper(un, cnp->cn_td)) != NULLVP) {
-               error = VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags);
-               union_unlock_upper(uppervp, cnp->cn_td);
-       }
-       return(error);
-}
-
-/*
- *     union_mknod:
- *
- *     a_dvp is locked on entry and should remain locked on return.
- *     a_vpp is garbagre whether an error occurs or not.
- *
- * union_mknod(struct vnode *a_dvp, struct vnode **a_vpp,
- *             struct componentname *a_cnp, struct vattr *a_vap)
- */
-static int
-union_mknod(struct vop_old_mknod_args *ap)
-{
-       struct union_node *dun = VTOUNION(ap->a_dvp);
-       struct componentname *cnp = ap->a_cnp;
-       struct vnode *dvp;
-       int error = EROFS;
-
-       if ((dvp = union_lock_upper(dun, cnp->cn_td)) != NULL) {
-               error = VOP_MKNOD(dvp, ap->a_vpp, cnp, ap->a_vap);
-               union_unlock_upper(dvp, cnp->cn_td);
-       }
-       return (error);
-}
-
-/*
- *     union_open:
- *
- *     run open VOP.  When opening the underlying vnode we have to mimic
- *     vn_open.  What we *really* need to do to avoid screwups if the
- *     open semantics change is to call vn_open().  For example, ufs blows
- *     up if you open a file but do not vmio it prior to writing.
- *
- * union_open(struct vnode *a_vp, int a_mode,
- *           struct ucred *a_cred, struct thread *a_td)
- */
-static int
-union_open(struct vop_open_args *ap)
-{
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct vnode *tvp;
-       int mode = ap->a_mode;
-       struct ucred *cred = ap->a_cred;
-       struct thread *td = ap->a_td;
-       int error = 0;
-       int tvpisupper = 1;
-
-       /*
-        * If there is an existing upper vp then simply open that.
-        * The upper vp takes precedence over the lower vp.  When opening
-        * a lower vp for writing copy it to the uppervp and then open the
-        * uppervp.
-        *
-        * At the end of this section tvp will be left locked.
-        */
-       if ((tvp = union_lock_upper(un, td)) == NULLVP) {
-               /*
-                * If the lower vnode is being opened for writing, then
-                * copy the file contents to the upper vnode and open that,
-                * otherwise can simply open the lower vnode.
-                */
-               tvp = un->un_lowervp;
-               if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
-                       int docopy = !(mode & O_TRUNC);
-                       error = union_copyup(un, docopy, cred, td);
-                       tvp = union_lock_upper(un, td);
-               } else {
-                       un->un_openl++;
-                       vref(tvp);
-                       vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);
-                       tvpisupper = 0;
-               }
-       }
-
-       /*
-        * We are holding the correct vnode, open it.  Note
-        * that in DragonFly, VOP_OPEN is responsible for associating
-        * a VM object with the vnode if the vnode is mappable or the
-        * underlying filesystem uses buffer cache calls on it.
-        */
-       if (error == 0)
-               error = VOP_OPEN(tvp, mode, cred, NULL);
-
-       /*
-        * Release any locks held
-        */
-       if (tvpisupper) {
-               if (tvp)
-                       union_unlock_upper(tvp, td);
-       } else {
-               vput(tvp);
-       }
-       return (error);
-}
-
-/*
- *     union_close:
- *
- *     It is unclear whether a_vp is passed locked or unlocked.  Whatever
- *     the case we do not change it.
- *
- * union_close(struct vnode *a_vp, int a_fflag, struct ucred *a_cred,
- *             struct thread *a_td)
- */
-static int
-union_close(struct vop_close_args *ap)
-{
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct vnode *vp;
-
-       vn_lock(vp, LK_UPGRADE | LK_RETRY);
-       if ((vp = un->un_uppervp) == NULLVP) {
-#ifdef UNION_DIAGNOSTIC
-               if (un->un_openl <= 0)
-                       panic("union: un_openl cnt");
-#endif
-               --un->un_openl;
-               vp = un->un_lowervp;
-       }
-       ap->a_head.a_ops = *vp->v_ops;
-       ap->a_vp = vp;
-       return(vop_close_ap(ap));
-}
-
-/*
- * Check access permission on the union vnode.
- * The access check being enforced is to check
- * against both the underlying vnode, and any
- * copied vnode.  This ensures that no additional
- * file permissions are given away simply because
- * the user caused an implicit file copy.
- *
- * union_access(struct vnode *a_vp, int a_mode,
- *             struct ucred *a_cred, struct thread *a_td)
- */
-static int
-union_access(struct vop_access_args *ap)
-{
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct thread *td = ap->a_td;
-       int error = EACCES;
-       struct vnode *vp;
-
-       /*
-        * Disallow write attempts on filesystems mounted read-only.
-        */
-       if ((ap->a_mode & VWRITE) && 
-           (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) {
-               switch (ap->a_vp->v_type) {
-               case VREG: 
-               case VDIR:
-               case VLNK:
-                       return (EROFS);
-               default:
-                       break;
-               }
-       }
-
-       if ((vp = union_lock_upper(un, td)) != NULLVP) {
-               ap->a_head.a_ops = *vp->v_ops;
-               ap->a_vp = vp;
-               error = vop_access_ap(ap);
-               union_unlock_upper(vp, td);
-               return(error);
-       }
-
-       if ((vp = un->un_lowervp) != NULLVP) {
-               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-               ap->a_head.a_ops = *vp->v_ops;
-               ap->a_vp = vp;
-
-               /*
-                * Remove VWRITE from a_mode if our mount point is RW, because
-                * we want to allow writes and lowervp may be read-only.
-                */
-               if ((un->un_vnode->v_mount->mnt_flag & MNT_RDONLY) == 0)
-                       ap->a_mode &= ~VWRITE;
-
-               error = vop_access_ap(ap);
-               if (error == 0) {
-                       struct union_mount *um;
-
-                       um = MOUNTTOUNIONMOUNT(un->un_vnode->v_mount);
-
-                       if (um->um_op == UNMNT_BELOW) {
-                               ap->a_cred = um->um_cred;
-                               error = vop_access_ap(ap);
-                       }
-               }
-               vn_unlock(vp);
-       }
-       return(error);
-}
-
-/*
- * We handle getattr only to change the fsid and
- * track object sizes
- *
- * It's not clear whether VOP_GETATTR is to be
- * called with the vnode locked or not.  stat() calls
- * it with (vp) locked, and fstat calls it with
- * (vp) unlocked. 
- *
- * Because of this we cannot use our normal locking functions
- * if we do not intend to lock the main a_vp node.  At the moment
- * we are running without any specific locking at all, but beware
- * to any programmer that care must be taken if locking is added
- * to this function.
- *
- * union_getattr(struct vnode *a_vp, struct vattr *a_vap,
- *              struct ucred *a_cred, struct thread *a_td)
- */
-static int
-union_getattr(struct vop_getattr_args *ap)
-{
-       int error;
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct vnode *vp;
-       struct vattr *vap;
-       struct vattr va;
-
-       /*
-        * Some programs walk the filesystem hierarchy by counting
-        * links to directories to avoid stat'ing all the time.
-        * This means the link count on directories needs to be "correct".
-        * The only way to do that is to call getattr on both layers
-        * and fix up the link count.  The link count will not necessarily
-        * be accurate but will be large enough to defeat the tree walkers.
-        */
-
-       vap = ap->a_vap;
-
-       if ((vp = un->un_uppervp) != NULLVP) {
-               error = VOP_GETATTR(vp, vap);
-               if (error)
-                       return (error);
-               /* XXX isn't this dangerouso without a lock? */
-               union_newsize(ap->a_vp, vap->va_size, VNOVAL);
-       }
-
-       if (vp == NULLVP) {
-               vp = un->un_lowervp;
-       } else if (vp->v_type == VDIR && un->un_lowervp != NULLVP) {
-               vp = un->un_lowervp;
-               vap = &va;
-       } else {
-               vp = NULLVP;
-       }
-
-       if (vp != NULLVP) {
-               error = VOP_GETATTR(vp, vap);
-               if (error)
-                       return (error);
-               /* XXX isn't this dangerous without a lock? */
-               union_newsize(ap->a_vp, VNOVAL, vap->va_size);
-       }
-
-       if ((vap != ap->a_vap) && (vap->va_type == VDIR))
-               ap->a_vap->va_nlink += vap->va_nlink;
-       return (0);
-}
-
-/*
- * union_setattr(struct vnode *a_vp, struct vattr *a_vap,
- *              struct ucred *a_cred, struct thread *a_td)
- */
-static int
-union_setattr(struct vop_setattr_args *ap)
-{
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct thread *td = ap->a_td;
-       struct vattr *vap = ap->a_vap;
-       struct vnode *uppervp;
-       int error;
-
-       /*
-        * Disallow write attempts on filesystems mounted read-only.
-        */
-       if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) &&
-           (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
-            vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
-            vap->va_mtime.tv_sec != VNOVAL || 
-            vap->va_mode != (mode_t)VNOVAL)) {
-               return (EROFS);
-       }
-
-       /*
-        * Handle case of truncating lower object to zero size,
-        * by creating a zero length upper object.  This is to
-        * handle the case of open with O_TRUNC and O_CREAT.
-        */
-       if (un->un_uppervp == NULLVP && (un->un_lowervp->v_type == VREG)) {
-               error = union_copyup(un, (ap->a_vap->va_size != 0),
-                           ap->a_cred, ap->a_td);
-               if (error)
-                       return (error);
-       }
-
-       /*
-        * Try to set attributes in upper layer,
-        * otherwise return read-only filesystem error.
-        */
-       error = EROFS;
-       if ((uppervp = union_lock_upper(un, td)) != NULLVP) {
-               error = VOP_SETATTR(un->un_uppervp, ap->a_vap, ap->a_cred);
-               if ((error == 0) && (ap->a_vap->va_size != VNOVAL))
-                       union_newsize(ap->a_vp, ap->a_vap->va_size, VNOVAL);
-               union_unlock_upper(uppervp, td);
-       }
-       return (error);
-}
-
-/*
- *     union_getpages:
- */
-
-static int
-union_getpages(struct vop_getpages_args *ap)
-{
-       int r;
-
-       r = vnode_pager_generic_getpages(ap->a_vp, ap->a_m,
-                                        ap->a_count, ap->a_reqpage,
-                                        ap->a_seqaccess);
-       return(r);
-}
-
-/*
- *     union_putpages:
- */
-
-static int
-union_putpages(struct vop_putpages_args *ap)
-{
-       int r;
-
-       r = vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
-               ap->a_sync, ap->a_rtvals);
-       return(r);
-}
-
-/*
- * union_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
- *           struct ucred *a_cred)
- */
-static int
-union_read(struct vop_read_args *ap)
-{
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct thread *td = ap->a_uio->uio_td;
-       struct vnode *uvp;
-       int error;
-
-       uvp = union_lock_other(un, td);
-       KASSERT(uvp != NULL, ("union_read: backing vnode missing!"));
-
-       if (ap->a_vp->v_flag & VOBJBUF)
-               union_vm_coherency(ap->a_vp, ap->a_uio, 0);
-
-       error = VOP_READ(uvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
-       union_unlock_other(uvp, td);
-
-       /*
-        * XXX
-        * perhaps the size of the underlying object has changed under
-        * our feet.  take advantage of the offset information present
-        * in the uio structure.
-        */
-       if (error == 0) {
-               struct union_node *un = VTOUNION(ap->a_vp);
-               off_t cur = ap->a_uio->uio_offset;
-
-               if (uvp == un->un_uppervp) {
-                       if (cur > un->un_uppersz)
-                               union_newsize(ap->a_vp, cur, VNOVAL);
-               } else {
-                       if (cur > un->un_lowersz)
-                               union_newsize(ap->a_vp, VNOVAL, cur);
-               }
-       }
-       return (error);
-}
-
-/*
- * union_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
- *             struct ucred *a_cred)
- */
-static int
-union_write(struct vop_read_args *ap)
-{
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct thread *td = ap->a_uio->uio_td;
-       struct vnode *uppervp;
-       int error;
-
-       if ((uppervp = union_lock_upper(un, td)) == NULLVP)
-               panic("union: missing upper layer in write");
-
-       /*
-        * Since our VM pages are associated with our vnode rather then
-        * the real vnode, and since we do not run our reads and writes 
-        * through our own VM cache, we have a VM/VFS coherency problem. 
-        * We solve them by invalidating or flushing the associated VM
-        * pages prior to allowing a normal read or write to occur.
-        *
-        * VM-backed writes (UIO_NOCOPY) have to be converted to normal
-        * writes because we are not cache-coherent.  Normal writes need
-        * to be made coherent with our VM-backing store, which we do by
-        * first flushing any dirty VM pages associated with the write
-        * range, and then destroying any clean VM pages associated with
-        * the write range.
-        */
-
-       if (ap->a_uio->uio_segflg == UIO_NOCOPY) {
-               ap->a_uio->uio_segflg = UIO_SYSSPACE;
-       } else if (ap->a_vp->v_flag & VOBJBUF) {
-               union_vm_coherency(ap->a_vp, ap->a_uio, 1);
-       }
-
-       error = VOP_WRITE(uppervp, ap->a_uio, ap->a_ioflag, ap->a_cred);
-
-       /*
-        * the size of the underlying object may be changed by the
-        * write.
-        */
-       if (error == 0) {
-               off_t cur = ap->a_uio->uio_offset;
-
-               if (cur > un->un_uppersz)
-                       union_newsize(ap->a_vp, cur, VNOVAL);
-       }
-       union_unlock_upper(uppervp, td);
-       return (error);
-}
-
-/*
- * union_ioctl(struct vnode *a_vp, int a_command, caddr_t a_data, int a_fflag,
- *             struct ucred *a_cred, struct thread *a_td)
- */
-static int
-union_ioctl(struct vop_ioctl_args *ap)
-{
-       struct vnode *ovp = OTHERVP(ap->a_vp);
-
-       ap->a_head.a_ops = *ovp->v_ops;
-       ap->a_vp = ovp;
-       return(vop_ioctl_ap(ap));
-}
-
-/*
- * union_poll(struct vnode *a_vp, int a_events, struct ucred *a_cred,
- *           struct thread *a_td)
- */
-static int
-union_poll(struct vop_poll_args *ap)
-{
-       struct vnode *ovp = OTHERVP(ap->a_vp);
-
-       ap->a_head.a_ops = *ovp->v_ops;
-       ap->a_vp = ovp;
-       return(vop_poll_ap(ap));
-}
-
-/*
- * union_mmap(struct vnode *a_vp, int a_fflags, struct ucred *a_cred,
- *           struct thread *a_td)
- */
-static int
-union_mmap(struct vop_mmap_args *ap)
-{
-       struct vnode *ovp = OTHERVP(ap->a_vp);
-
-       ap->a_head.a_ops = *ovp->v_ops;
-       ap->a_vp = ovp;
-       return (vop_mmap_ap(ap));
-}
-
-/*
- * union_fsync(struct vnode *a_vp, struct ucred *a_cred, int a_waitfor,
- *             struct thread *a_td)
- */
-static int
-union_fsync(struct vop_fsync_args *ap)
-{
-       int error = 0;
-       struct thread *td = ap->a_td;
-       struct vnode *targetvp;
-       struct union_node *un = VTOUNION(ap->a_vp);
-
-       if ((targetvp = union_lock_other(un, td)) != NULLVP) {
-               error = VOP_FSYNC(targetvp, ap->a_waitfor, 0);
-               union_unlock_other(targetvp, td);
-       }
-
-       return (error);
-}
-
-/*
- *     union_remove:
- *
- *     Remove the specified cnp.  The dvp and vp are passed to us locked
- *     and must remain locked on return.
- *
- * union_remove(struct vnode *a_dvp, struct vnode *a_vp,
- *             struct componentname *a_cnp)
- */
-static int
-union_remove(struct vop_old_remove_args *ap)
-{
-       struct union_node *dun = VTOUNION(ap->a_dvp);
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct componentname *cnp = ap->a_cnp;
-       struct thread *td = cnp->cn_td;
-       struct vnode *uppervp;
-       struct vnode *upperdvp;
-       int error;
-
-       if ((upperdvp = union_lock_upper(dun, td)) == NULLVP)
-               panic("union remove: null upper vnode");
-
-       if ((uppervp = union_lock_upper(un, td)) != NULLVP) {
-               if (union_dowhiteout(un, cnp->cn_cred, td))
-                       cnp->cn_flags |= CNP_DOWHITEOUT;
-               error = VOP_REMOVE(upperdvp, uppervp, cnp);
-#if 0
-               /* XXX */
-               if (!error)
-                       union_removed_upper(un);
-#endif
-               union_unlock_upper(uppervp, td);
-       } else {
-               error = union_mkwhiteout(
-                           MOUNTTOUNIONMOUNT(ap->a_dvp->v_mount),
-                           upperdvp, ap->a_cnp, un->un_path);
-       }
-       union_unlock_upper(upperdvp, td);
-       return (error);
-}
-
-/*
- *     union_link:
- *
- *     tdvp will be locked on entry, vp will not be locked on entry.
- *     tdvp should remain locked on return and vp should remain unlocked
- *     on return.
- *
- * union_link(struct vnode *a_tdvp, struct vnode *a_vp,
- *           struct componentname *a_cnp)
- */
-static int
-union_link(struct vop_old_link_args *ap)
-{
-       struct componentname *cnp = ap->a_cnp;
-       struct thread *td = cnp->cn_td;
-       struct union_node *dun = VTOUNION(ap->a_tdvp);
-       struct vnode *vp;
-       struct vnode *tdvp;
-       int error = 0;
-
-       if (ap->a_tdvp->v_ops != ap->a_vp->v_ops) {
-               vp = ap->a_vp;
-       } else {
-               struct union_node *tun = VTOUNION(ap->a_vp);
-
-               if (tun->un_uppervp == NULLVP) {
-                       vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
-#if 0
-                       if (dun->un_uppervp == tun->un_dirvp) {
-                               if (dun->un_flags & UN_ULOCK) {
-                                       dun->un_flags &= ~UN_ULOCK;
-                                       vn_unlock(dun->un_uppervp);
-                               }
-                       }
-#endif
-                       error = union_copyup(tun, 1, cnp->cn_cred, td);
-#if 0
-                       if (dun->un_uppervp == tun->un_dirvp) {
-                               vn_lock(dun->un_uppervp, 
-                                       LK_EXCLUSIVE | LK_RETRY);
-                               dun->un_flags |= UN_ULOCK;
-                       }
-#endif
-                       vn_unlock(ap->a_vp);
-               }
-               vp = tun->un_uppervp;
-       }
-
-       if (error)
-               return (error);
-
-       /*
-        * Make sure upper is locked, then unlock the union directory we were 
-        * called with to avoid a deadlock while we are calling VOP_LINK on 
-        * the upper (with tdvp locked and vp not locked).  Our ap->a_tdvp
-        * is expected to be locked on return.
-        */
-
-       if ((tdvp = union_lock_upper(dun, td)) == NULLVP)
-               return (EROFS);
-
-       vn_unlock(ap->a_tdvp);  /* unlock calling node */
-       error = VOP_LINK(tdvp, vp, cnp); /* call link on upper */
-
-       /*
-        * We have to unlock tdvp prior to relocking our calling node in
-        * order to avoid a deadlock.
-        */
-       union_unlock_upper(tdvp, td);
-       vn_lock(ap->a_tdvp, LK_EXCLUSIVE | LK_RETRY);
-       return (error);
-}
-
-/*
- * union_rename(struct vnode *a_fdvp, struct vnode *a_fvp,
- *             struct componentname *a_fcnp, struct vnode *a_tdvp,
- *             struct vnode *a_tvp, struct componentname *a_tcnp)
- */
-static int
-union_rename(struct vop_old_rename_args *ap)
-{
-       int error;
-       struct vnode *fdvp = ap->a_fdvp;
-       struct vnode *fvp = ap->a_fvp;
-       struct vnode *tdvp = ap->a_tdvp;
-       struct vnode *tvp = ap->a_tvp;
-
-       /*
-        * Figure out what fdvp to pass to our upper or lower vnode.  If we
-        * replace the fdvp, release the original one and ref the new one.
-        */
-
-       if (fdvp->v_tag == VT_UNION) {  /* always true */
-               struct union_node *un = VTOUNION(fdvp);
-               if (un->un_uppervp == NULLVP) {
-                       /*
-                        * this should never happen in normal
-                        * operation but might if there was
-                        * a problem creating the top-level shadow
-                        * directory.
-                        */
-                       error = EXDEV;
-                       goto bad;
-               }
-               fdvp = un->un_uppervp;
-               vref(fdvp);
-               vrele(ap->a_fdvp);
-       }
-
-       /*
-        * Figure out what fvp to pass to our upper or lower vnode.  If we
-        * replace the fvp, release the original one and ref the new one.
-        */
-
-       if (fvp->v_tag == VT_UNION) {   /* always true */
-               struct union_node *un = VTOUNION(fvp);
-#if 0
-               struct union_mount *um = MOUNTTOUNIONMOUNT(fvp->v_mount);
-#endif
-
-               if (un->un_uppervp == NULLVP) {
-                       switch(fvp->v_type) {
-                       case VREG:
-                               vn_lock(un->un_vnode, LK_EXCLUSIVE | LK_RETRY);
-                               error = union_copyup(un, 1, ap->a_fcnp->cn_cred, ap->a_fcnp->cn_td);
-                               vn_unlock(un->un_vnode);
-                               if (error)
-                                       goto bad;
-                               break;
-                       case VDIR:
-                               /*
-                                * XXX not yet.
-                                *
-                                * There is only one way to rename a directory
-                                * based in the lowervp, and that is to copy
-                                * the entire directory hierarchy.  Otherwise
-                                * it would not last across a reboot.
-                                */
-#if 0
-                               vrele(fvp);
-                               fvp = NULL;
-                               vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
-                               error = union_mkshadow(um, fdvp, 
-                                           ap->a_fcnp, &un->un_uppervp);
-                               vn_unlock(fdvp);
-                               if (un->un_uppervp)
-                                       vn_unlock(un->un_uppervp);
-                               if (error)
-                                       goto bad;
-                               break;
-#endif
-                       default:
-                               error = EXDEV;
-                               goto bad;
-                       }
-               }
-
-               if (un->un_lowervp != NULLVP)
-                       ap->a_fcnp->cn_flags |= CNP_DOWHITEOUT;
-               fvp = un->un_uppervp;
-               vref(fvp);
-               vrele(ap->a_fvp);
-       }
-
-       /*
-        * Figure out what tdvp (destination directory) to pass to the
-        * lower level.  If we replace it with uppervp, we need to vput the 
-        * old one.  The exclusive lock is transfered to what we will pass
-        * down in the VOP_RENAME and we replace uppervp with a simple
-        * reference.
-        */
-
-       if (tdvp->v_tag == VT_UNION) {
-               struct union_node *un = VTOUNION(tdvp);
-
-               if (un->un_uppervp == NULLVP) {
-                       /*
-                        * this should never happen in normal
-                        * operation but might if there was
-                        * a problem creating the top-level shadow
-                        * directory.
-                        */
-                       error = EXDEV;
-                       goto bad;
-               }
-
-               /*
-                * new tdvp is a lock and reference on uppervp, put away
-                * the old tdvp.
-                */
-               tdvp = union_lock_upper(un, ap->a_tcnp->cn_td);
-               vput(ap->a_tdvp);
-       }
-
-       /*
-        * Figure out what tvp (destination file) to pass to the
-        * lower level.
-        *
-        * If the uppervp file does not exist put away the (wrong)
-        * file and change tvp to NULL.
-        */
-
-       if (tvp != NULLVP && tvp->v_tag == VT_UNION) {
-               struct union_node *un = VTOUNION(tvp);
-
-               tvp = union_lock_upper(un, ap->a_tcnp->cn_td);
-               vput(ap->a_tvp);
-               /* note: tvp may be NULL */
-       }
-
-       /*
-        * VOP_RENAME releases/vputs prior to returning, so we have no
-        * cleanup to do.
-        */
-
-       return (VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp));
-
-       /*
-        * Error.  We still have to release / vput the various elements.
-        */
-
-bad:
-       vrele(fdvp);
-       if (fvp)
-               vrele(fvp);
-       vput(tdvp);
-       if (tvp != NULLVP) {
-               if (tvp != tdvp)
-                       vput(tvp);
-               else
-                       vrele(tvp);
-       }
-       return (error);
-}
-
-/*
- * union_mkdir(struct vnode *a_dvp, struct vnode **a_vpp,
- *             struct componentname *a_cnp, struct vattr *a_vap)
- */
-static int
-union_mkdir(struct vop_old_mkdir_args *ap)
-{
-       struct union_node *dun = VTOUNION(ap->a_dvp);
-       struct componentname *cnp = ap->a_cnp;
-       struct thread *td = cnp->cn_td;
-       struct vnode *upperdvp;
-       int error = EROFS;
-
-       if ((upperdvp = union_lock_upper(dun, td)) != NULLVP) {
-               struct vnode *vp;
-
-               error = VOP_MKDIR(upperdvp, &vp, cnp, ap->a_vap);
-               union_unlock_upper(upperdvp, td);
-
-               if (error == 0) {
-                       vn_unlock(vp);
-                       UDEBUG(("ALLOCVP-2 FROM %p REFS %d\n",
-                               vp, vp->v_refcnt));
-                       error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount,
-                               ap->a_dvp, NULLVP, cnp, vp, NULLVP, 1);
-                       UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n",
-                               *ap->a_vpp, vp->v_refcnt));
-               }
-       }
-       return (error);
-}
-
-/*
- * union_rmdir(struct vnode *a_dvp, struct vnode *a_vp,
- *             struct componentname *a_cnp)
- */
-static int
-union_rmdir(struct vop_old_rmdir_args *ap)
-{
-       struct union_node *dun = VTOUNION(ap->a_dvp);
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct componentname *cnp = ap->a_cnp;
-       struct thread *td = cnp->cn_td;
-       struct vnode *upperdvp;
-       struct vnode *uppervp;
-       int error;
-
-       if ((upperdvp = union_lock_upper(dun, td)) == NULLVP)
-               panic("union rmdir: null upper vnode");
-
-       if ((uppervp = union_lock_upper(un, td)) != NULLVP) {
-               if (union_dowhiteout(un, cnp->cn_cred, td))
-                       cnp->cn_flags |= CNP_DOWHITEOUT;
-               error = VOP_RMDIR(upperdvp, uppervp, ap->a_cnp);
-               union_unlock_upper(uppervp, td);
-       } else {
-               error = union_mkwhiteout(
-                           MOUNTTOUNIONMOUNT(ap->a_dvp->v_mount),
-                           dun->un_uppervp, ap->a_cnp, un->un_path);
-       }
-       union_unlock_upper(upperdvp, td);
-       return (error);
-}
-
-/*
- *     union_symlink:
- *
- *     dvp is locked on entry and remains locked on return.  a_vpp is garbage
- *     (unused).
- *
- * union_symlink(struct vnode *a_dvp, struct vnode **a_vpp,
- *             struct componentname *a_cnp, struct vattr *a_vap,
- *             char *a_target)
- */
-static int
-union_symlink(struct vop_old_symlink_args *ap)
-{
-       struct union_node *dun = VTOUNION(ap->a_dvp);
-       struct componentname *cnp = ap->a_cnp;
-       struct thread *td = cnp->cn_td;
-       struct vnode *dvp;
-       int error = EROFS;
-
-       if ((dvp = union_lock_upper(dun, td)) != NULLVP) {
-               error = VOP_SYMLINK(dvp, ap->a_vpp, cnp, ap->a_vap,
-                           ap->a_target);
-               union_unlock_upper(dvp, td);
-       }
-       return (error);
-}
-
-/*
- * union_readdir works in concert with getdirentries and
- * readdir(3) to provide a list of entries in the unioned
- * directories.  getdirentries is responsible for walking
- * down the union stack.  readdir(3) is responsible for
- * eliminating duplicate names from the returned data stream.
- *
- * union_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
- *              int *a_eofflag, off_t *a_cookies, int a_ncookies)
- */
-static int
-union_readdir(struct vop_readdir_args *ap)
-{
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct thread *td = ap->a_uio->uio_td;
-       struct vnode *uvp;
-       int error = 0;
-
-       if ((uvp = union_ref_upper(un)) != NULLVP) {
-               ap->a_head.a_ops = *uvp->v_ops;
-               ap->a_vp = uvp;
-               error = vop_readdir_ap(ap);
-               vrele(uvp);
-       }
-       return(error);
-}
-
-/*
- * union_readlink(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred)
- */
-static int
-union_readlink(struct vop_readlink_args *ap)
-{
-       int error;
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct uio *uio = ap->a_uio;
-       struct thread *td = uio->uio_td;
-       struct vnode *vp;
-
-       vp = union_lock_other(un, td);
-       KASSERT(vp != NULL, ("union_readlink: backing vnode missing!"));
-
-       ap->a_head.a_ops = *vp->v_ops;
-       ap->a_vp = vp;
-       error = vop_readlink_ap(ap);
-       union_unlock_other(vp, td);
-
-       return (error);
-}
-
-/*
- *     union_inactive:
- *
- *     Called with the vnode locked.  We are expected to unlock the vnode.
- *
- * union_inactive(struct vnode *a_vp, struct thread *a_td)
- */
-static int
-union_inactive(struct vop_inactive_args *ap)
-{
-       struct vnode *vp = ap->a_vp;
-       /*struct thread *td = ap->a_td;*/
-       struct union_node *un = VTOUNION(vp);
-       struct vnode **vpp;
-
-       /*
-        * Do nothing (and _don't_ bypass).
-        * Wait to vrele lowervp until reclaim,
-        * so that until then our union_node is in the
-        * cache and reusable.
-        *
-        * NEEDSWORK: Someday, consider inactive'ing
-        * the lowervp and then trying to reactivate it
-        * with capabilities (v_id)
-        * like they do in the name lookup cache code.
-        * That's too much work for now.
-        */
-
-       if (un->un_dircache != 0) {
-               for (vpp = un->un_dircache; *vpp != NULLVP; vpp++)
-                       vrele(*vpp);
-               kfree (un->un_dircache, M_TEMP);
-               un->un_dircache = 0;
-       }
-
-#if 0
-       if ((un->un_flags & UN_ULOCK) && un->un_uppervp) {
-               un->un_flags &= ~UN_ULOCK;
-               vn_unlock(un->un_uppervp);
-       }
-#endif
-
-       if ((un->un_flags & UN_CACHED) == 0)
-               vgone_vxlocked(vp);
-
-       return (0);
-}
-
-/*
- * union_reclaim(struct vnode *a_vp)
- */
-static int
-union_reclaim(struct vop_reclaim_args *ap)
-{
-       union_freevp(ap->a_vp);
-
-       return (0);
-}
-
-/*
- *     union_bmap:
- *
- *     There isn't much we can do.  We cannot push through to the real vnode
- *     to get to the underlying device because this will bypass data
- *     cached by the real vnode.
- *
- *     For some reason we cannot return the 'real' vnode either, it seems
- *     to blow up memory maps.
- *
- * union_bmap(struct vnode *a_vp, off_t a_loffset,
- *           off_t *a_doffsetp, int *a_runp, int *a_runb)
- */
-static int
-union_bmap(struct vop_bmap_args *ap)
-{
-       return(EOPNOTSUPP);
-}
-
-/*
- * union_print(struct vnode *a_vp)
- */
-static int
-union_print(struct vop_print_args *ap)
-{
-       struct vnode *vp = ap->a_vp;
-
-       kprintf("\ttag VT_UNION, vp=%p, uppervp=%p, lowervp=%p\n",
-                       vp, UPPERVP(vp), LOWERVP(vp));
-       if (UPPERVP(vp) != NULLVP)
-               vprint("union: upper", UPPERVP(vp));
-       if (LOWERVP(vp) != NULLVP)
-               vprint("union: lower", LOWERVP(vp));
-
-       return (0);
-}
-
-/*
- * union_pathconf(struct vnode *a_vp, int a_name, int *a_retval)
- */
-static int
-union_pathconf(struct vop_pathconf_args *ap)
-{
-       int error;
-       struct thread *td = curthread;          /* XXX */
-       struct union_node *un = VTOUNION(ap->a_vp);
-       struct vnode *vp;
-
-       vp = union_lock_other(un, td);
-       KASSERT(vp != NULL, ("union_pathconf: backing vnode missing!"));
-
-       ap->a_head.a_ops = *vp->v_ops;
-       ap->a_vp = vp;
-       error = vop_pathconf_ap(ap);
-       union_unlock_other(vp, td);
-
-       return (error);
-}
-
-/*
- * union_advlock(struct vnode *a_vp, caddr_t a_id, int a_op,
- *              struct flock *a_fl, int a_flags)
- */
-static int
-union_advlock(struct vop_advlock_args *ap)
-{
-       struct vnode *ovp = OTHERVP(ap->a_vp);
-
-       ap->a_head.a_ops = *ovp->v_ops;
-       ap->a_vp = ovp;
-       return (vop_advlock_ap(ap));
-}
-
-
-/*
- * XXX - vop_strategy must be hand coded because it has no
- * YYY - and it is not coherent with anything
- *
- * vnode in its arguments.
- * This goes away with a merged VM/buffer cache.
- *
- * union_strategy(struct vnode *a_vp, struct bio *a_bio)
- */
-static int
-union_strategy(struct vop_strategy_args *ap)
-{
-       struct bio *bio = ap->a_bio;
-       struct buf *bp = bio->bio_buf;
-       struct vnode *othervp = OTHERVP(ap->a_vp);
-
-#ifdef DIAGNOSTIC
-       if (othervp == NULLVP)
-               panic("union_strategy: nil vp");
-       if (bp->b_cmd != BUF_CMD_READ && (othervp == LOWERVP(ap->a_vp)))
-               panic("union_strategy: writing to lowervp");
-#endif
-       return (vn_strategy(othervp, bio));
-}
-
-/*
- * Global vfs data structures
- */
-struct vop_ops union_vnode_vops = {
-       .vop_default =          vop_defaultop,
-       .vop_access =           union_access,
-       .vop_advlock =          union_advlock,
-       .vop_bmap =             union_bmap,
-       .vop_close =            union_close,
-       .vop_old_create =       union_create,
-       .vop_fsync =            union_fsync,
-       .vop_getpages =         union_getpages,
-       .vop_putpages =         union_putpages,
-       .vop_getattr =          union_getattr,
-       .vop_inactive =         union_inactive,
-       .vop_ioctl =            union_ioctl,
-       .vop_old_link =         union_link,
-       .vop_old_lookup =       union_lookup,
-       .vop_old_mkdir =        union_mkdir,
-       .vop_old_mknod =        union_mknod,
-       .vop_mmap =             union_mmap,
-       .vop_open =             union_open,
-       .vop_pathconf =         union_pathconf,
-       .vop_poll =             union_poll,
-       .vop_print =            union_print,
-       .vop_read =             union_read,
-       .vop_readdir =          union_readdir,
-       .vop_readlink =         union_readlink,
-       .vop_reclaim =          union_reclaim,
-       .vop_old_remove =       union_remove,
-       .vop_old_rename =       union_rename,
-       .vop_old_rmdir =        union_rmdir,
-       .vop_setattr =          union_setattr,
-       .vop_strategy =         union_strategy,
-       .vop_old_symlink =      union_symlink,
-       .vop_old_whiteout =     union_whiteout,
-       .vop_write =            union_write
-};
-
index dabb792..00c455d 100755 (executable)
 # umountf2.sh                  N       Waiting for commit of fix
 # umountf3.sh                  N       Deadlock. Waiting for commit of fix             20081212
 # umountf4.sh                  Y       Page fault in ufs/ufs/ufs_dirhash.c:204         20081003
-# unionfs.sh                   N       Page fault                                      20070503
-# unionfs2.sh                  N       Reported as cons224                             20070504
-# unionfs3.sh                  N       Page fault in vfs_statfs                        20070504
 
 # End of list
 
diff --git a/test/stress/stress2/misc/union.sh b/test/stress/stress2/misc/union.sh
deleted file mode 100755 (executable)
index c02dac6..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2009 Peter Holm <pho@FreeBSD.org>
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-#
-
-# Simple union test scenario
-
-[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
-
-. ../default.cfg
-
-u1=$mdstart
-u2=$((u1 + 1))
-[ -d mp1 ] || mkdir mp1
-
-mount | grep -q /dev/md${u2}$part && umount -f /dev/md${u2}$part
-mount | grep -q /dev/md${u1}$part && umount -f /dev/md${u1}$part
-mdconfig -l | grep -q md${u2} && mdconfig -d -u $u2
-mdconfig -l | grep -q md${u1} && mdconfig -d -u $u1
-
-mdconfig -s 256m -u $u1
-bsdlabel -w md$u1 auto
-newfs md${u1}${part} > /dev/null
-
-mdconfig -s 256m -u $u2
-bsdlabel -w md$u2 auto
-newfs md${u2}${part} > /dev/null
-
-mount -o ro    /dev/md${u1}$part mp1
-mount -o union /dev/md${u2}$part mp1
-
-export RUNDIR=`pwd`/mp1/stressX
-export runRUNTIME=10m
-(cd ..; ./run.sh marcus.cfg)
-
-umount /dev/md${u2}$part
-umount /dev/md${u1}$part
-
-mount | grep -q /dev/md${u2}$part && umount -f /dev/md${u2}$part
-mount | grep -q /dev/md${u1}$part && umount -f /dev/md${u1}$part
-
-mdconfig -d -u $u2
-mdconfig -d -u $u1
-
-rm -rf mp1
diff --git a/test/stress/stress2/misc/unionfs.sh b/test/stress/stress2/misc/unionfs.sh
deleted file mode 100755 (executable)
index 68f7c5e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2008 Peter Holm <pho@FreeBSD.org>
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-#
-
-[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
-
-# Causes this: panic: mutex Giant not owned at ../../../kern/vfs_subr.c:1968
-# with a kernel compiled with "options QUOTA"
-
-D=/usr/tmp/diskimage
-truncate -s 256M $D
-
-mount | grep "/mnt" | grep md0c > /dev/null && umount /mnt
-mdconfig -l | grep md0 > /dev/null &&  mdconfig -d -u 0
-
-mdconfig -a -t vnode -f $D -u 0
-bsdlabel -w md0 auto
-newfs -U  md0c > /dev/null
-mount /dev/md0c /mnt
-mount -t unionfs -o noatime /mnt /tmp
-export RUNDIR=/tmp/stressX
-export runRUNTIME=10m            # Run tests for 10 minutes
-(cd /home/pho/stress2; ./run.sh disk.cfg)
-mount | grep "/mnt" | grep md0c > /dev/null && umount    /mnt
-mount | grep "/mnt" | grep md0c > /dev/null && umount -f /mnt
-mdconfig -d -u 0
-rm -f $D
diff --git a/test/stress/stress2/misc/unionfs2.sh b/test/stress/stress2/misc/unionfs2.sh
deleted file mode 100755 (executable)
index 5960082..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2008 Peter Holm <pho@FreeBSD.org>
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-#
-
-[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
-
-saved=`sysctl vfs.lookup_shared | awk '{print $NF}'`
-for i in 1 0; do
-   sysctl vfs.lookup_shared=$i
-   [ -d /var/tmp/unionfs ] || mkdir -p /var/tmp/unionfs
-   mount_unionfs /var/tmp/unionfs /tmp/stressX
-
-   export RUNDIR=/var/tmp/unionfs/stressX
-   export runRUNTIME=10m            # Run tests for 10 minutes
-   (cd /home/pho/stress2; ./run.sh disk.cfg)
-   false
-   while mount | grep -q /unionfs; do
-      umount /tmp/stressX > /dev/null 2>&1
-   done
-   rm -rf /var/tmp/unionfs
-done
-sysctl vfs.lookup_shared=$saved
diff --git a/test/stress/stress2/misc/unionfs3.sh b/test/stress/stress2/misc/unionfs3.sh
deleted file mode 100755 (executable)
index f3cd77b..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2008 Peter Holm <pho@FreeBSD.org>
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-#
-
-[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
-
-# Test with interchanged arguments to mount_unionfs
-# Causes page fault in vfs_mount.c:1975
-
-D=/usr/tmp/diskimage
-truncate -s 256M $D
-
-mount | grep "/mnt" | grep md0c > /dev/null && umount /mnt
-mdconfig -l | grep md0 > /dev/null &&  mdconfig -d -u 0
-
-mdconfig -a -t vnode -f $D -u 0
-bsdlabel -w md0 auto
-newfs -U  md0c > /dev/null
-mount /dev/md0c /mnt
-mount -t unionfs -o noatime /tmp /mnt
-umount -f /tmp # panic
-mount /tmp
-mount | grep "/mnt" | grep md0c > /dev/null && umount    /mnt
-mount | grep "/mnt" | grep md0c > /dev/null && umount -f /mnt
-mdconfig -d -u 0
-rm -f $D
index 75500e1..d1769e3 100644 (file)
@@ -43,7 +43,6 @@
 #include <sys/mount.h>
 #include <sys/uio.h>
 #include <sys/namei.h>
-#include <vfs/union/union.h>
 #include <sys/stat.h>
 #include <nfs/rpcv2.h>
 #include <nfs/nfsproto.h>
@@ -117,7 +116,6 @@ struct {
        { MNT_NOEXEC, "noexec" },
        { MNT_NOSUID, "nosuid" },
        { MNT_NODEV, "nodev" },
-       { MNT_UNION, "union" },
        { MNT_ASYNC, "async" },
        { MNT_SUIDDIR, "suiddir" },
        { MNT_SOFTDEP, "softdep" },
@@ -181,8 +179,6 @@ void        ttyprt(struct tty *, int);
 void   ttytype(struct tty *, const char *, int, int, int);
 void   ufs_header(void);
 int    ufs_print(struct vnode *);
-void   union_header(void);
-int    union_print(struct vnode *);
 static void usage(void);
 void   vnode_header(void);
 void   vnode_print(struct vnode *, struct vnode *);
@@ -349,8 +345,6 @@ vnodemode(void)
                                ufs_header();
                        else if (!strcmp(ST.f_fstypename, "nfs"))
                                nfs_header();
-                       else if (!strcmp(ST.f_fstypename, "union"))
-                               union_header();
                        printf("\n");
                }
                vnode_print(evp->avnode, vp);
@@ -359,8 +353,6 @@ vnodemode(void)
                        ufs_print(vp);
                else if (!strcmp(ST.f_fstypename, "nfs"))
                        nfs_print(vp);
-               else if (!strcmp(ST.f_fstypename, "union"))
-                       union_print(vp);
                printf("\n");
        }
        free(e_vnodebase);
@@ -563,24 +555,6 @@ nfs_print(struct vnode *vp)
        return (0);
 }
 
-void
-union_header(void)
-{
-       printf("    UPPER    LOWER");
-}
-
-int
-union_print(struct vnode *vp)
-{
-       struct union_node unode, *up = &unode;
-
-       KGETRET(VTOUNION(vp), &unode, sizeof(unode), "vnode's unode");
-
-       printf(" %8lx %8lx", (u_long)(void *)up->un_uppervp,
-           (u_long)(void *)up->un_lowervp);
-       return (0);
-}
-       
 /*
  * Given a pointer to a mount structure in kernel space,
  * read it in and return a usable pointer to it.