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>