Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 18 Apr 2011 13:29:08 +0400
From:      Alex Zimnitsky <aavzz@yandex.ru>
To:        freebsd-fs@freebsd.org
Subject:   unionfs kernel panic while mounting (i386, R8.2)
Message-ID:  <1303118948.2112.40.camel@localhost>

next in thread | raw e-mail | index | archive | help
Hi everyone!


There is a problem with unionfs mount procedure
which consistently causes system crash. I observed
this behavior (freshly installed release 8.2) on
two i386 boxes one of which was an ancient laptop
with 256MB RAM and the other was a not-so-old
desktop with more than 4GB jf RAM.

******* How to reproduce: **************

mkdir /var/ftp

mkdir /var/ftpdata1
mkdir /var/ftpdata2
      ...
mkdir /var/ftpdata15

mount -t unionfs /var/ftpdata1 /var/ftp
mount -t unionfs /var/ftpdata2 /var/ftp
      ...
mount -t unionfs /var/ftpdata15 /var/ftp

mounting /var/ftpdata12 reliably caused
kernel panic on the laptop in my case
(desktop reliably crashed while mounting ftpdata10-12)

************ Possible cause ****************

A little investigation revealed that this crash
happens in unionfs_statfs which lives
in /usr/src/sys/fs/unionfs/union_vfsops.c

Debug printing showed that it calls itself
recursively n+1 times depending on the
quantity of previously mounted dirs:

mount -t unionfs /var/ftpdata1 /var/ftp   - 2 times
mount -t unionfs /var/ftpdata2 /var/ftp   - 3 times
      ...
mount -t unionfs /var/ftpdata10 /var/ftp  - 11 times
      ...

It appears that the crash is caused by lack of system
resources (stack I guess)

The crash itself writes something like "double fault"
or "double error" (I'm sure about that "double")


**************** Workaround ************************

Reducing recursion eliminates the problem.

unionfs_statfs part:

old (with the problem):
---------------------------------------------------------------

        struct unionfs_mount *ump;
        int             error;
        struct statfs   mstat;
        uint64_t        lbsize;
 
        ump = MOUNTTOUNIONFSMOUNT(mp);
         
        UNIONFSDEBUG("unionfs_statfs(mp = %p, lvp = %p, uvp = %p)\n",
            (void *)mp, (void *)ump->um_lowervp, (void
*)ump->um_uppervp);
 
        bzero(&mstat, sizeof(mstat));

        error = VFS_STATFS(ump->um_lowervp->v_mount, &mstat);
 
-----------------------------------------------------------------------

new (without crashes):
-----------------------------------------------------------------------
  struct unionfs_mount *ump;
        int             error;
        struct statfs   mstat;
        uint64_t        lbsize;
 
        struct unionfs_mount *ump_aavzz; /*AAVZZ*/
 
        /*ump = MOUNTTOUNIONFSMOUNT(mp);*/ /*AAVZZ*/
        ump_aavzz = MOUNTTOUNIONFSMOUNT(mp); /*AAVZZ*/
 
 
        UNIONFSDEBUG("unionfs_statfs(mp = %p, lvp = %p, uvp = %p)\n",
            (void *)mp, (void *)ump->um_lowervp, (void
*)ump->um_uppervp);
 
        bzero(&mstat, sizeof(mstat));

        /*Dirty hack to fast forward*/
        while (!
strcmp(ump_aavzz->um_lowervp->v_mount->mnt_stat.f_fstypename,
                      "unionfs")) {

ump_aavzz=MOUNTTOUNIONFSMOUNT(ump_aavzz->um_lowervp->v_mount);
        }
        ump=ump_aavzz;
        /*end of dirty hack*/

        error = VFS_STATFS(ump->um_lowervp->v_mount, &mstat);

-------------------------------------------------------------------------------


**************************** Considerations **************************

I'm sure that the above is not the way to treat the problem. But
I do not have deep understanding of the internal workings of filesystems
in general and unionfs in particular and cannot come up with anything
better.

Probably this growing recursion should not take place at all, which
requires defferent handling of ump->um_lowervp->v_mount during list
creation (mount?).



Regards,

Alex




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1303118948.2112.40.camel>