From nobody@FreeBSD.ORG Wed Jul 28 10:07:54 1999
Return-Path: <nobody@FreeBSD.ORG>
Received: by hub.freebsd.org (Postfix, from userid 32767)
	id B1BAF1537A; Wed, 28 Jul 1999 10:07:54 -0700 (PDT)
Message-Id: <19990728170754.B1BAF1537A@hub.freebsd.org>
Date: Wed, 28 Jul 1999 10:07:54 -0700 (PDT)
From: kfarmer@sympatico.ca
Sender: nobody@FreeBSD.ORG
To: freebsd-gnats-submit@freebsd.org
Subject: panic:softdep_flushfiles:looping, caused by user creating deep directory structure
X-Send-Pr-Version: www-1.0

>Number:         12855
>Category:       kern
>Synopsis:       panic:softdep_flushfiles:looping, caused by user creating deep directory structure
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    mckusick
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 28 10:10:01 PDT 1999
>Closed-Date:    Sun Feb 10 16:12:54 PST 2002
>Last-Modified:  Sun Feb 10 16:16:27 PST 2002
>Originator:     Kelvin Farmer
>Release:        4.0-current (as of july 26, 1999)
>Organization:
>Environment:
FreeBSD tristal.sympatico.ca 4.0-CURRENT FreeBSD 4.0-CURRENT #5: Wed Jul 28 12:29:57 EDT 1999     root@tristal.sympatico.ca:/usr/src/sys/compile/TRISTAL  i386

>Description:
if a user creates a very deep directory structure (eg, /usr/home/guest/tmp/tmp/tmp/tmp/tmp/....)
Then umounting the filesystem causes: panic:softdep_flushfiles:looping.
also: rm -rf cannot remove the directory structure, claims 'directory not empty'

>How-To-Repeat:
1) create a directory structure at least 256(?) directories deep.
2) umount the filesystem.

fsck is able to fix this on reboot.
rm -r is able to remove the structure if you go far enough into it.

from ffs_softdep.c: line 675

softdep_worklist_busy = 0;
        /*
         * If we are unmounting then it is an error to fail. If we
         * are simply trying to downgrade to read-only, then filesystem
         * activity can keep us busy forever, so we just fail with EBUSY.
         */
        if (loopcnt == 0) {
                if (oldmnt->mnt_kern_flag & MNTK_UNMOUNT)
                        panic("softdep_flushfiles: looping");
                error = EBUSY;
        }
        return (error); 

>Fix:


>Release-Note:
>Audit-Trail:

From: Bruce Evans <bde@zeta.org.au>
To: freebsd-gnats-submit@FreeBSD.ORG, kfarmer@sympatico.ca
Cc:  
Subject: Re: kern/12855: panic:softdep_flushfiles:looping, caused by user creating deep directory structure
Date: Thu, 29 Jul 1999 13:32:01 +1000

 >>Description:
 >if a user creates a very deep directory structure (eg, /usr/home/guest/tmp/tmp/tmp/tmp/tmp/....)
 >Then umounting the filesystem causes: panic:softdep_flushfiles:looping.
 >also: rm -rf cannot remove the directory structure, claims 'directory not empty'
 
 Here is a possible fix for rm(1) and find(1), etc.  Don't commit it verbatim;
 the changes in fts.c are mostly for debugging.
 
 fts.c is just buggy.  It creates garbage pointers.  rm.c was broken
 in rev.1.2 by applying an apparently obsolete (and wrong) patch from
 FreeBSD-1.1.5.  POSIX.1 requires rm(1) and find(1) to work on arbitrarily
 deep directories; therefore they must use chdir(2) to reduce path lengths
 and they must not use FTS_NOCHDIR.
 
 Burce
 
 diff -c2 src/bin/rm/rm.c~ src/bin/rm/rm.c
 *** src/bin/rm/rm.c~	Sun May 30 17:04:01 1999
 --- src/bin/rm/rm.c	Sun May 30 17:04:04 1999
 ***************
 *** 160,164 ****
   #define	SKIPPED	1
   
 ! 	flags = FTS_PHYSICAL | FTS_NOCHDIR;
   	if (!needstat)
   		flags |= FTS_NOSTAT;
 --- 160,164 ----
   #define	SKIPPED	1
   
 ! 	flags = FTS_PHYSICAL;
   	if (!needstat)
   		flags |= FTS_NOSTAT;
 diff -c2 src/lib/libc/gen/fts.c~ src/lib/libc/gen/fts.c
 *** src/lib/libc/gen/fts.c~	Thu Sep 17 14:24:03 1998
 --- src/lib/libc/gen/fts.c	Thu May  6 14:15:17 1999
 ***************
 *** 964,967 ****
 --- 964,985 ----
   }
   
 + static void
 + ADJUST(p, addr)
 + 	FTSENT *p;
 + 	void *addr;
 + {
 + 	if ((p)->fts_accpath >= (p)->fts_path &&			
 + 	    (p)->fts_accpath < (p)->fts_path + (p)->fts_pathlen) {
 + 		if (p->fts_accpath != p->fts_path)
 + 			errx(1, "fts ADJUST: accpath %p path %p",
 + 			    p->fts_accpath, p->fts_path);
 + 		if (p->fts_level != 0)
 + 			errx(1, "fts ADJUST: level %d not 0", p->fts_level);
 + 		(p)->fts_accpath =					
 + 		    (char *)addr + ((p)->fts_accpath - (p)->fts_path);	
 + 	}
 + 	(p)->fts_path = addr;						
 + }
 + 
   /*
    * When the path is realloc'd, have to fix all of the pointers in structures
 ***************
 *** 975,990 ****
   	FTSENT *p;
   
 ! #define	ADJUST(p) {							\
 ! 	(p)->fts_accpath =						\
 ! 	    (char *)addr + ((p)->fts_accpath - (p)->fts_path);		\
   	(p)->fts_path = addr;						\
   }
   	/* Adjust the current set of children. */
   	for (p = sp->fts_child; p; p = p->fts_link)
 ! 		ADJUST(p);
   
   	/* Adjust the rest of the tree. */
   	for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
 ! 		ADJUST(p);
   		p = p->fts_link ? p->fts_link : p->fts_parent;
   	}
 --- 993,1008 ----
   	FTSENT *p;
   
 ! #define	ADJUST1(p) {							\
 ! 	if ((p)->fts_accpath == (p)->fts_path)				\
 ! 		(p)->fts_accpath = (addr);				\
   	(p)->fts_path = addr;						\
   }
   	/* Adjust the current set of children. */
   	for (p = sp->fts_child; p; p = p->fts_link)
 ! 		ADJUST(p, addr);
   
   	/* Adjust the rest of the tree. */
   	for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
 ! 		ADJUST(p, addr);
   		p = p->fts_link ? p->fts_link : p->fts_parent;
   	}
 
Responsible-Changed-From-To: freebsd-bugs->mckusick 
Responsible-Changed-By: phk 
Responsible-Changed-When: Wed May 23 14:03:05 PDT 2001 
Responsible-Changed-Why:  
Kirk, this may contain a future test-case for softupdates. 
Otherwise just close the PR. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=12855 
State-Changed-From-To: open->closed 
State-Changed-By: mckusick 
State-Changed-When: Sun Feb 10 16:12:54 PST 2002 
State-Changed-Why:  
This bug was fixed with the restucturing done in revision 1.95 
of /sys/ufs/ffs/ffs_softdep.c 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=12855 
>Unformatted:
