Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Mar 2015 17:45:53 +0200
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Ian Lepore <ian@freebsd.org>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org
Subject:   Re: svn commit: r280760 - head/sys/ufs/ffs
Message-ID:  <20150327154552.GN2379@kib.kiev.ua>
In-Reply-To: <1427470995.91374.7.camel@freebsd.org>
References:  <201503271355.t2RDtuLt071068@svn.freebsd.org> <1427470995.91374.7.camel@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Mar 27, 2015 at 09:43:15AM -0600, Ian Lepore wrote:
> On Fri, 2015-03-27 at 13:55 +0000, Konstantin Belousov wrote:
> > Author: kib
> > Date: Fri Mar 27 13:55:56 2015
> > New Revision: 280760
> > URL: https://svnweb.freebsd.org/changeset/base/280760
> > 
> > Log:
> >   Fix the hand after the immediate reboot when the following command
> >   sequence is performed on UFS SU+J rootfs:
> >   cp -Rp /sbin/init /sbin/init.old
> >   mv -f /sbin/init.old /sbin/init
> >   
> >   Hang occurs on the rootfs unmount.  There are two issues:
> >   
> >   1. Removed init binary, which is still mapped, creates a reference to
> >   the removed vnode. The inodeblock for such vnode must have active
> >   inodedep, which is (eventually) linked through the unlinked list. This
> >   means that ffs_sync(MNT_SUSPEND) cannot succeed, because number of
> >   softdep workitems for the mp is always > 0.  FFS is suspended during
> >   unmount, so unmount just hangs.
> >   
> >   2. As noted above, the inodedep is linked eventually.  It is not
> >   linked until the superblock is written.  But at the vfs_unmountall()
> >   time, when the rootfs is unmounted, the call is made to
> >   ffs_unmount()->ffs_sync() before vflush(), and ffs_sync() only calls
> >   ffs_sbupdate() after all workitems are flushed.  It is masked for
> >   normal system operations, because syncer works in parallel and
> >   eventually flushes superblock.  Syncer is stopped when rootfs
> >   unmounted, so ffs_sync() must do sb update on its own.
> >   
> >   Correct the issues listed above. For MNT_SUSPEND, count the number of
> >   linked unlinked inodedeps (this is not a typo) and substract the count
> >   of such workitems from the total. For the second issue, the
> >   ffs_sbupdate() is called right after device sync in ffs_sync() loop.
> >   
> >   There is third problem, occuring with both SU and SU+J. The
> >   softdep_waitidle() loop, which waits for softdep_flush() thread to
> >   clear the worklist, only waits 20ms max. It seems that the 1 tick,
> >   specified for msleep(9), was a typo.
> >   
> >   Add fsync(devvp, MNT_WAIT) call to softdep_waitidle(), which seems to
> >   significantly help the softdep thread, and change the MNT_LAZY update
> >   at the reboot time to MNT_WAIT for similar reasons.  Note that
> >   userspace cannot create more work while devvp is flushed, since the
> >   mount point is always suspended before the call to softdep_waitidle()
> >   in unmount or remount path.
> >   
> >   PR:	195458
> >   In collaboration with:	gjb, pho
> >   Reviewed by:	mckusick
> >   Sponsored by:	The FreeBSD Foundation
> >   MFC after:	2 weeks
> > 
> > Modified:
> >   head/sys/ufs/ffs/ffs_softdep.c
> >   head/sys/ufs/ffs/ffs_vfsops.c
> 
> This is causing warning: function declaration isn't a prototype on
> platforms that still compile with old gcc.  Simple fix, but I thought
> you might want to do the commit so you can get an mfc reminder along
> with the main commit.
> 
> -- Ian
> 
> Index: sys/ufs/ffs/ffs_softdep.c
> ===================================================================
> --- sys/ufs/ffs/ffs_softdep.c	(revision 280761)
> +++ sys/ufs/ffs/ffs_softdep.c	(working copy)
> @@ -804,6 +804,7 @@ static	struct indirdep *indirdep_lookup(struct mou
>  	    struct buf *);
>  static	void cancel_indirdep(struct indirdep *, struct buf *,
>  	    struct freeblks *);
> +static	int check_inodedep_free(struct inodedep *);
>  static	void free_indirdep(struct indirdep *);
>  static	void free_diradd(struct diradd *, struct workhead *);
>  static	void merge_diradd(struct inodedep *, struct diradd *);
> 

Yes, thank you.  I was already notified and trying to compile ppc GENERIC64
kernel to confirm the same fix.

Did you compile-tested the change on arm with gcc ?  If so, I will just
commit it.



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