Bug 26498

Summary: Fix for bug in union mounts (mout -o union)
Product: Base System Reporter: Oliver Fromme <olli>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description Oliver Fromme 2001-04-11 18:20:01 UTC
   When you mount a directory on top of another, using the
   "union" option to the mount command (I'm NOT talking
   about UNIONFS!), then all entries which are present in
   both directories appear twice, like this:
   
   $ ls -a
   .       ..      bar     bar1    baz     baz1    foo     foo1
   .       ..      bar     bar2    baz     baz2    foo     foo2
   
   It is particularly disturbing that "." and ".." appear
   twice, even if the directories are otherwise disjunct.
   
   Same problem with /usr/bin/find, /bin/sh (``echo *'')
   and all other tools that read and traverse directories.
   
   The culprit is in src/lib/libc/gen/opendir.c in the
   function __opendir2().  Look at the variable "unionstack"
   (near line 110).  It is correctly set to 1 in the case of
   a UNIONFS -- in this case the code removes duplicates.
   However, it doesn't handle the case of a union mount.

Fix: The following patch fixes the problem by simply checking
   if the MNT_UNION flag is set in the statfs struct.
   The patch is against rev. 1.10 (4-stable as of 2000-04-10).

   I have had a look at the code in current, and the fix
   should be applicable there, too.  I haven't actually
   tested it, due to lack of a -current machine, but the
   fix is trivial enough for me to be sure that it should
   work.  :-)

   I have this code in production on a box with several
   jails, all of them containing union-mounted filesystems,
   and everything works fine.

   *phew*  Such a long PR for a one-line fix ...
How-To-Repeat: 
   /*  Create two small vnode filesystems, /bin/sh syntax:  */

   for i in 0 1; do
           dd if=/dev/zero of=fs$i.vn bs=1m count=1
           vnconfig -s labels -c vn$i fs$i.vn
           disklabel -r -w vn$i auto
           newfs /dev/vn${i}c
   done

   /*  Mount them over each other:  */

   mkdir fs
   mount /dev/vn0c fs
   mount -o union /dev/vn1c fs

   ls -a
   .       .      ..      ..

   /*  Note that "." and ".." appear twice.  */
Comment 1 Joerg Wunsch freebsd_committer freebsd_triage 2001-04-23 11:01:46 UTC
State Changed
From-To: open->closed

Suggested fix applied in rev 1.15 of opendir.c. 

Thanks!