[Glibc-bsd-commits] r5712 - in trunk/kfreebsd-10/debian: . patches

stevenc-guest at alioth.debian.org stevenc-guest at alioth.debian.org
Sat May 23 14:50:10 UTC 2015


Author: stevenc-guest
Date: 2015-05-23 14:50:10 +0000 (Sat, 23 May 2015)
New Revision: 5712

Added:
   trunk/kfreebsd-10/debian/patches/EN-15_05.ufs.patch
Modified:
   trunk/kfreebsd-10/debian/changelog
   trunk/kfreebsd-10/debian/patches/series
Log:
Pick SVN r282873 from FreeBSD 10.1-RELEASE to fix:
- EN-15:05: Fix deadlock on reboot with UFS tuned with SU+J.
  (Closes: #786619)


Modified: trunk/kfreebsd-10/debian/changelog
===================================================================
--- trunk/kfreebsd-10/debian/changelog	2015-05-23 14:27:46 UTC (rev 5711)
+++ trunk/kfreebsd-10/debian/changelog	2015-05-23 14:50:10 UTC (rev 5712)
@@ -3,6 +3,9 @@
   * Create tarballs of upstream source, and of the kfreebsd-source
     binary-indep package, using a reproducible stable file order.
     (Closes: #786615)
+  * Pick SVN r282873 from FreeBSD 10.1-RELEASE to fix:
+    - EN-15:05: Fix deadlock on reboot with UFS tuned with SU+J.
+      (Closes: #786619)
 
  -- Steven Chamberlain <steven at pyro.eu.org>  Sat, 23 May 2015 14:57:14 +0100
 

Added: trunk/kfreebsd-10/debian/patches/EN-15_05.ufs.patch
===================================================================
--- trunk/kfreebsd-10/debian/patches/EN-15_05.ufs.patch	                        (rev 0)
+++ trunk/kfreebsd-10/debian/patches/EN-15_05.ufs.patch	2015-05-23 14:50:10 UTC (rev 5712)
@@ -0,0 +1,314 @@
+Description:
+ Fix deadlock on reboot with UFS tuned with SU+J. [EN-15:05]
+Origin: vendor, https://security.FreeBSD.org/patches/EN-15:05/ufs.patch
+Bug: https://security.FreeBSD.org/advisories/FreeBSD-EN-15:05.ufs.asc
+Bug-Debian: https://bugs.debian.org/786619
+Applied-Upstream: https://svnweb.freebsd.org/base?view=revision&revision=282873
+
+--- a/sys/ufs/ffs/ffs_softdep.c
++++ b/sys/ufs/ffs/ffs_softdep.c
+@@ -735,9 +735,10 @@
+ static	void check_clear_deps(struct mount *);
+ static	void softdep_error(char *, int);
+ static	int softdep_process_worklist(struct mount *, int);
+-static	int softdep_waitidle(struct mount *);
++static	int softdep_waitidle(struct mount *, int);
+ static	void drain_output(struct vnode *);
+ static	struct buf *getdirtybuf(struct buf *, struct rwlock *, int);
++static	int check_inodedep_free(struct inodedep *);
+ static	void clear_remove(struct mount *);
+ static	void clear_inodedeps(struct mount *);
+ static	void unlinked_inodedep(struct mount *, struct inodedep *);
+@@ -1377,6 +1378,10 @@
+ 	mp = (struct mount *)addr;
+ 	ump = VFSTOUFS(mp);
+ 	atomic_add_int(&stat_flush_threads, 1);
++	ACQUIRE_LOCK(ump);
++	ump->softdep_flags &= ~FLUSH_STARTING;
++	wakeup(&ump->softdep_flushtd);
++	FREE_LOCK(ump);
+ 	if (print_threads) {
+ 		if (stat_flush_threads == 1)
+ 			printf("Running %s at pid %d\n", bufdaemonproc->p_comm,
+@@ -1389,7 +1394,7 @@
+ 		    VFSTOUFS(mp)->softdep_jblocks->jb_suspended))
+ 			kthread_suspend_check();
+ 		ACQUIRE_LOCK(ump);
+-		if ((ump->softdep_flags & FLUSH_CLEANUP) == 0)
++		if ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0)
+ 			msleep(&ump->softdep_flushtd, LOCK_PTR(ump), PVM,
+ 			    "sdflush", hz / 2);
+ 		ump->softdep_flags &= ~FLUSH_CLEANUP;
+@@ -1419,11 +1424,9 @@
+ 
+ 	ump = VFSTOUFS(mp);
+ 	LOCK_OWNED(ump);
+-	if ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0) {
++	if ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0)
+ 		ump->softdep_flags |= FLUSH_CLEANUP;
+-		if (ump->softdep_flushtd->td_wchan == &ump->softdep_flushtd)
+-			wakeup(&ump->softdep_flushtd);
+-	}
++	wakeup(&ump->softdep_flushtd);
+ }
+ 
+ static int
+@@ -1468,14 +1471,10 @@
+ 			TAILQ_INSERT_TAIL(&softdepmounts, sdp, sd_next);
+ 			FREE_GBLLOCK(&lk);
+ 			if ((altump->softdep_flags &
+-			    (FLUSH_CLEANUP | FLUSH_EXIT)) == 0) {
++			    (FLUSH_CLEANUP | FLUSH_EXIT)) == 0)
+ 				altump->softdep_flags |= FLUSH_CLEANUP;
+-				altump->um_softdep->sd_cleanups++;
+-				if (altump->softdep_flushtd->td_wchan ==
+-				    &altump->softdep_flushtd) {
+-					wakeup(&altump->softdep_flushtd);
+-				}
+-			}
++			altump->um_softdep->sd_cleanups++;
++			wakeup(&altump->softdep_flushtd);
+ 			FREE_LOCK(altump);
+ 		}
+ 	}
+@@ -1887,8 +1886,8 @@
+ 	struct thread *td;
+ {
+ 	struct vnode *devvp;
+-	int count, error = 0;
+ 	struct ufsmount *ump;
++	int count, error;
+ 
+ 	/*
+ 	 * Alternately flush the block device associated with the mount
+@@ -1897,6 +1896,7 @@
+ 	 * are found.
+ 	 */
+ 	*countp = 0;
++	error = 0;
+ 	ump = VFSTOUFS(oldmnt);
+ 	devvp = ump->um_devvp;
+ 	while ((count = softdep_process_worklist(oldmnt, 1)) > 0) {
+@@ -1904,36 +1904,47 @@
+ 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
+ 		error = VOP_FSYNC(devvp, MNT_WAIT, td);
+ 		VOP_UNLOCK(devvp, 0);
+-		if (error)
++		if (error != 0)
+ 			break;
+ 	}
+ 	return (error);
+ }
+ 
++#define	SU_WAITIDLE_RETRIES	20
+ static int
+-softdep_waitidle(struct mount *mp)
++softdep_waitidle(struct mount *mp, int flags __unused)
+ {
+ 	struct ufsmount *ump;
+-	int error;
+-	int i;
++	struct vnode *devvp;
++	struct thread *td;
++	int error, i;
+ 
+ 	ump = VFSTOUFS(mp);
++	devvp = ump->um_devvp;
++	td = curthread;
++	error = 0;
+ 	ACQUIRE_LOCK(ump);
+-	for (i = 0; i < 10 && ump->softdep_deps; i++) {
++	for (i = 0; i < SU_WAITIDLE_RETRIES && ump->softdep_deps != 0; i++) {
+ 		ump->softdep_req = 1;
+-		if (ump->softdep_on_worklist)
+-			panic("softdep_waitidle: work added after flush.");
+-		msleep(&ump->softdep_deps, LOCK_PTR(ump), PVM, "softdeps", 1);
++		KASSERT((flags & FORCECLOSE) == 0 ||
++		    ump->softdep_on_worklist == 0,
++		    ("softdep_waitidle: work added after flush"));
++		msleep(&ump->softdep_deps, LOCK_PTR(ump), PVM | PDROP,
++		    "softdeps", 10 * hz);
++		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
++		error = VOP_FSYNC(devvp, MNT_WAIT, td);
++		VOP_UNLOCK(devvp, 0);
++		if (error != 0)
++			break;
++		ACQUIRE_LOCK(ump);
+ 	}
+ 	ump->softdep_req = 0;
+-	FREE_LOCK(ump);
+-	error = 0;
+-	if (i == 10) {
++	if (i == SU_WAITIDLE_RETRIES && error == 0 && ump->softdep_deps != 0) {
+ 		error = EBUSY;
+ 		printf("softdep_waitidle: Failed to flush worklist for %p\n",
+ 		    mp);
+ 	}
+-
++	FREE_LOCK(ump);
+ 	return (error);
+ }
+ 
+@@ -1990,7 +2001,7 @@
+ 		error = EBUSY;
+ 	}
+ 	if (!error)
+-		error = softdep_waitidle(oldmnt);
++		error = softdep_waitidle(oldmnt, flags);
+ 	if (!error) {
+ 		if (oldmnt->mnt_kern_flag & MNTK_UNMOUNT) {
+ 			retry = 0;
+@@ -2490,9 +2501,18 @@
+ 	/*
+ 	 * Start our flushing thread in the bufdaemon process.
+ 	 */
++	ACQUIRE_LOCK(ump);
++	ump->softdep_flags |= FLUSH_STARTING;
++	FREE_LOCK(ump);
+ 	kproc_kthread_add(&softdep_flush, mp, &bufdaemonproc,
+ 	    &ump->softdep_flushtd, 0, 0, "softdepflush", "%s worker",
+ 	    mp->mnt_stat.f_mntonname);
++	ACQUIRE_LOCK(ump);
++	while ((ump->softdep_flags & FLUSH_STARTING) != 0) {
++		msleep(&ump->softdep_flushtd, LOCK_PTR(ump), PVM, "sdstart",
++		    hz / 2);
++	}
++	FREE_LOCK(ump);
+ 	/*
+ 	 * When doing soft updates, the counters in the
+ 	 * superblock may have gotten out of sync. Recomputation
+@@ -7629,17 +7649,13 @@
+ 	return (1);
+ }
+ 
+-/*
+- * Try to free an inodedep structure. Return 1 if it could be freed.
+- */
+ static int
+-free_inodedep(inodedep)
++check_inodedep_free(inodedep)
+ 	struct inodedep *inodedep;
+ {
+ 
+ 	LOCK_OWNED(VFSTOUFS(inodedep->id_list.wk_mp));
+-	if ((inodedep->id_state & (ONWORKLIST | UNLINKED)) != 0 ||
+-	    (inodedep->id_state & ALLCOMPLETE) != ALLCOMPLETE ||
++	if ((inodedep->id_state & ALLCOMPLETE) != ALLCOMPLETE ||
+ 	    !LIST_EMPTY(&inodedep->id_dirremhd) ||
+ 	    !LIST_EMPTY(&inodedep->id_pendinghd) ||
+ 	    !LIST_EMPTY(&inodedep->id_bufwait) ||
+@@ -7654,6 +7670,21 @@
+ 	    inodedep->id_nlinkdelta != 0 ||
+ 	    inodedep->id_savedino1 != NULL)
+ 		return (0);
++	return (1);
++}
++
++/*
++ * Try to free an inodedep structure. Return 1 if it could be freed.
++ */
++static int
++free_inodedep(inodedep)
++	struct inodedep *inodedep;
++{
++
++	LOCK_OWNED(VFSTOUFS(inodedep->id_list.wk_mp));
++	if ((inodedep->id_state & (ONWORKLIST | UNLINKED)) != 0 ||
++	    !check_inodedep_free(inodedep))
++		return (0);
+ 	if (inodedep->id_state & ONDEPLIST)
+ 		LIST_REMOVE(inodedep, id_deps);
+ 	LIST_REMOVE(inodedep, id_hash);
+@@ -13838,7 +13869,8 @@
+ {
+ 	struct bufobj *bo;
+ 	struct ufsmount *ump;
+-	int error;
++	struct inodedep *inodedep;
++	int error, unlinked;
+ 
+ 	bo = &devvp->v_bufobj;
+ 	ASSERT_BO_WLOCKED(bo);
+@@ -13899,6 +13931,20 @@
+ 		break;
+ 	}
+ 
++	unlinked = 0;
++	if (MOUNTEDSUJ(mp)) {
++		for (inodedep = TAILQ_FIRST(&ump->softdep_unlinked);
++		    inodedep != NULL;
++		    inodedep = TAILQ_NEXT(inodedep, id_unlinked)) {
++			if ((inodedep->id_state & (UNLINKED | UNLINKLINKS |
++			    UNLINKONLIST)) != (UNLINKED | UNLINKLINKS |
++			    UNLINKONLIST) ||
++			    !check_inodedep_free(inodedep))
++				continue;
++			unlinked++;
++		}
++	}
++
+ 	/*
+ 	 * Reasons for needing more work before suspend:
+ 	 * - Dirty buffers on devvp.
+@@ -13908,8 +13954,8 @@
+ 	error = 0;
+ 	if (bo->bo_numoutput > 0 ||
+ 	    bo->bo_dirty.bv_cnt > 0 ||
+-	    softdep_depcnt != 0 ||
+-	    ump->softdep_deps != 0 ||
++	    softdep_depcnt != unlinked ||
++	    ump->softdep_deps != unlinked ||
+ 	    softdep_accdepcnt != ump->softdep_accdeps ||
+ 	    secondary_writes != 0 ||
+ 	    mp->mnt_secondary_writes != 0 ||
+--- a/sys/ufs/ffs/ffs_vfsops.c
++++ b/sys/ufs/ffs/ffs_vfsops.c
+@@ -1502,8 +1502,11 @@
+ 	if (fs->fs_fmod != 0 && fs->fs_ronly != 0 && ump->um_fsckpid == 0)
+ 		panic("%s: ffs_sync: modification on read-only filesystem",
+ 		    fs->fs_fsmnt);
+-	if (waitfor == MNT_LAZY)
+-		return (ffs_sync_lazy(mp));
++	if (waitfor == MNT_LAZY) {
++		if (!rebooting)
++			return (ffs_sync_lazy(mp));
++		waitfor = MNT_NOWAIT;
++	}
+ 
+ 	/*
+ 	 * Write back each (modified) inode.
+@@ -1560,7 +1563,7 @@
+ 	/*
+ 	 * Force stale filesystem control information to be flushed.
+ 	 */
+-	if (waitfor == MNT_WAIT) {
++	if (waitfor == MNT_WAIT || rebooting) {
+ 		if ((error = softdep_flushworklist(ump->um_mountp, &count, td)))
+ 			allerror = error;
+ 		/* Flushed work items may create new vnodes to clean */
+@@ -1577,9 +1580,12 @@
+ 	if (bo->bo_numoutput > 0 || bo->bo_dirty.bv_cnt > 0) {
+ 		BO_UNLOCK(bo);
+ 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
+-		if ((error = VOP_FSYNC(devvp, waitfor, td)) != 0)
+-			allerror = error;
++		error = VOP_FSYNC(devvp, waitfor, td);
+ 		VOP_UNLOCK(devvp, 0);
++		if (MOUNTEDSOFTDEP(mp) && (error == 0 || error == EAGAIN))
++			error = ffs_sbupdate(ump, waitfor, 0);
++		if (error != 0)
++			allerror = error;
+ 		if (allerror == 0 && waitfor == MNT_WAIT)
+ 			goto loop;
+ 	} else if (suspend != 0) {
+--- a/sys/ufs/ffs/softdep.h
++++ b/sys/ufs/ffs/softdep.h
+@@ -1063,6 +1063,8 @@
+  */
+ #define FLUSH_EXIT	0x0001	/* time to exit */
+ #define FLUSH_CLEANUP	0x0002	/* need to clear out softdep structures */
++#define	FLUSH_STARTING	0x0004	/* flush thread not yet started */
++
+ /*
+  * Keep the old names from when these were in the ufsmount structure.
+  */

Modified: trunk/kfreebsd-10/debian/patches/series
===================================================================
--- trunk/kfreebsd-10/debian/patches/series	2015-05-23 14:27:46 UTC (rev 5711)
+++ trunk/kfreebsd-10/debian/patches/series	2015-05-23 14:50:10 UTC (rev 5712)
@@ -43,3 +43,4 @@
 SA-15_04.igmp.patch
 EN-15_01.vt.patch
 SA-15_09.ipv6.patch
+EN-15_05.ufs.patch




More information about the Glibc-bsd-commits mailing list