To build Unionfs, there are two main components:

-  unionfs.o: the kernel module in 2.4
or unionfs.ko: the kernel module in 2.6

-  unionctl: a user utility which allows you to add and remove branches

You should be able to just type "make" and Unionfs will build itself for the
running kernel.  The Makefile will look for your running kernel sources in
/lib/modules/`uname -r`/build/include.

If your kernel sources are located in a different directory, create a
"fistdev.mk" file along the lines of:
LINUXSRC=/path/to/my/kernel/sources/linux-2.4.xx
TOPINC=-I$(LINUXSRC)/include
MODDIR=/lib/modules/2.4.xx

LINUXSRC points to the root of a Linux source tree.  TOPINC should point to
that tree's include directory.  Finally, the module will be copied to
$MODDIR/kernel/fs/unionfs.ko.

You must set all three variables together, otherwise you can have problems
compiling, installing, or loading the module.

You also need to have the headers for e2fsprogs installed, on Red Hat
derived systems (like Fedora Core), this means that you need to have
e2fsprogs-devel installed.

There are two Makefile options related to extended attribute support,
which is turned off by default.  You should define UNIONFS_XATTR to turn
it on.  Vanilla kernels should work automatically, but if you (or your
vendor) has applied the ACL/EA patches you might need to define
FIST_SETXATTR_CONSTVOID to correct the setxattr operation's function
prototype.

Using fistdev.mk, you can also turn off the debugging print system,
which adds to the modules code size significantly.  Just add
"EXTRACFLAGS=-DUNIONFS_NDEBUG" to fistdev.mk.

The doit.sh script included in the distribution will mount unionfs
with two branches (/branch0 and /branch1) by default.  You can use it
as an example and edit to your tastes.

To install unionfs run "make install".  This copies unionfs.o into
/lib/modules/`uname -r`/kernel/fs/; copies the utilities into
/usr/local/sbin; and copies man pages into /usr/local/man;

fistdev.mk summary:
UNIONFS_OPT_CFLAG	By default -O2.  If you want a different optimization
			level change this variable.
UNIONFS_DEBUG_CFLAG	By default -g.  If you want to remove debug, set
			this variable to nothing.  This will result in a
			smaller (but harder to debug) Unionfs.
EXTRACFLAGS		Additional stuff to pass to the compiler, this
			is useful when combined with the definitions below.
			(e.g., EXTRACFLAGS=-DUNIONFS_NDEBUG to turn off
			debugging).
LINUXSRC		Where to find the kernel build directory.
TOPINC			Where to find the kernel headers.
PREFIX			Where to install Unionfs utilities.
			By default /usr/local.
MODPREFIX		What is the prefix to the root directory for modules,
			by default this is unset.  Your modules will end up
			in /lib/modules/`uname -r`/kernel/fs.  With
			MODPREFIX=/foo they end up in
			/foo/lib/modules/`uname -r`/kernel/fs.

Define options summary:
UNIONFS_XATTR		Enable extended attribute support
FIST_SETXATTR_CONSTVOID	Change prototypes of setxattr function for some
			vendor kernels
UNIONFS_NDEBUG		Turn off debugging facility (reduces code size).
UNIONFS_UNSUPPORTED	Bypass kernel versions checks.
SUPPORT_BROKEN_SETUP	Enable sendfile, which allows you to run losetup, but
			if you try to write to a loop file, you will cause
			an Oops.
NFS_SECURITY_HOLE	If the NFS server returns -EACCES, then assume that
			standard permission checks are good enough.  This
			allows you to use read-only exports (which return
			-EACCES instead of -EROFS), and will respect standard
			Unix permissions, but causes NFS ACLs to be ignored.

Known interactions with other kernel features/patches:
* If you get an error like this on Fedora Core 4:
  make: *** /lib/modules/2.6.11-1.1369_FC4/build: No such file or directory.  Stop.
  Then you need to install the kernel-devel package.

* If you get an error like this:
  unionimap.h:9:23: uuid/uuid.h: No such file or directory
  Followed, by more parse errors,  then you need to make sure you have
  e2fsprogs-devel installed (or your distribution's equivalent).

* Some NFS servers return -EPERM instead of -EROFS when they are exported
  read-only.  This means that we can't legitimately determine when a user is
  not allowed to access a file.  To enable a hack so that NFS appears to work
  correctly (but NFS ACLs will break), compile unionfs with -DNFS_SECURITY_HOLE.

* If you want to export Unionfs over NFS, then you need to add
  extra information to /etc/exports.  knfsd will not export Unionfs unless
  you have an fsid option in /etc/exports.  This is because Unionfs has no
  real device.  See man exports(5) for more information on fsid.

* If you want to use Unionfs as your root file system you need to use
  pivot_root.  www.linux-live.org provides scripts for creating live CDs with
  Unionfs as the root.  The following commands are adapted from the linuxrc
  from linux-live 5.0.16.  You may want to look at the original script from
  www.linux-live.org if you are having problems.  SLAX (www.slax.org) is a
  an actual live CD distribution based on these scripts.

  UNION=/union
  MEMORY=/memory
  MOUNTDIR=/mnt
  CHANGES=$MEMORY/changes

  mkdir -p $UNION

  mkdir -p $MEMORY
  mount -t tmpfs tmpfs $MEMORY

  mkdir -p $CHANGES
  mount -t unionfs -o dirs=$CHANGES=rw unionfs $UNION

  # Here other things are added to the Union, by using unionctl.

  cd $UNION
  mkdir -p initrd
  pivot_root . initrd
  exec chroot . /bin/bash
  # You should never get here

* If you want to use losetup, then you need to define -DSUPPORT_BROKEN_LOSETUP
  You will be able to use it read-only, but when you try to use it read-write,
  you will get an Oops.  This should eventually be fixed when we have our
  own address-space operations (so that we can support sendfile).

* Selinux requires extended attributes (but has not been tested by us).
  You should compile Unionfs with Extended Attribute support by adding
  EXTRACFLAGS=-DUNIONFS_XATTR to fistdev.mk.  After this, you can follow
  the following instructions are from Jaspreet Singh:

  1. Install strict/targetted selinux policy sources
  2. Open /etc/selinux/<policy_type>/src/policy/fs_use
  3. Append "fs_use_xattr unionfs system_u:object_r:fs_t;"
  4. Compile, install, and reload the selinux policy

  "There were a couple of issues with Unionfs but they were minor."

* tmpfs does not support fsyncing directories, so if you have a Union with
  tmpfs as the leftmost branch, fsync returns EINVAL.

Other known limitations:
* Unionfs does not provide cache coherency.  What this means to you is that
  if you directly modify the lower-level branches, then Unionfs will get
  confused.  You can tell Unionfs to throw out its cache and recreate all
  of its objects (lazily), by running "uniondbg -g UNION".

  It is especially dangerous to create or remove whiteouts from underneath
  Unionfs, as there are several places where it ASSERTs on invariants
  that must be true (e.g., if the file exists, the whiteout should not and
  vice versa).

* Unionfs doesn't support sendfile.  This often manifests itself as apache
  serving zero length files.  You can turn off sendfile n Apache with the
  EnableSendfile httpd.conf directive (see
  http://httpd.apache.org/docs/2.0/mod/core.html).   This is also the reason
  that losetup is unsupported, Unionfs needs its own address space operations
  otherwise upper and lower-level files and pages get mixed and matched.

* If you restart an NFS server, you will get ESTALE errors on the client
  because Unionfs does not have persistent inode numbers.  You should also
  consider NFS over TCP, so lost packets don't cause readdir to get confused.

* Renaming a directory on a read-only branch returns an EXDEV error.  The "mv"
  utility is designed to handle this error (at least GNU coreutils and busybox
  will handle this correctly), so a user will not see anything.  The only
  issue will be applications that internally rename a directory, but do not
  properly handle EXDEV (which is really a bug on the application's part).

* The documentation needs to improve

* The object code is much larger than it could be, but this can be solved by
  enabling UNIONFS_NDEBUG and setting UNIONFS_DEBUG_CFLAG to the empty string.

Integrating Unionfs into a 2.6 kernel source tree (2.4 is not supported):
1. First run patch-kernel.sh included with Unionfs. Its first argument is the
   path to your kernel source tree.
2. Configure and compile your kernel as you normally would.   Unionfs is at the
   bottom of the the File systems -> Miscellaenous filesystems menu.
3. To install the Unionfs utilities (i.e., unionctl and uniondbg), run
   "make utils install-utils" from the Unionfs source directory.
4. Boot into your new kernel, and enjoy Unionfs.
