Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 6 Sep 2009 11:46:51 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r196888 - head/sys/ufs/ffs
Message-ID:  <200909061146.n86BkpXK082995@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sun Sep  6 11:46:51 2009
New Revision: 196888
URL: http://svn.freebsd.org/changeset/base/196888

Log:
  The clear_remove() and clear_inodedeps() call vn_start_write(NULL, &mp,
  V_NOWAIT) on the non-busied mount point. Unmount might free ufs-specific
  mp data, causing ffs_vgetf() to access freed memory.
  
  Busy mountpoint before dropping softdep lk.
  
  Noted and reviewed by:	tegge
  Tested by:	pho
  MFC after:	1 week

Modified:
  head/sys/ufs/ffs/ffs_softdep.c

Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c	Sun Sep  6 11:44:46 2009	(r196887)
+++ head/sys/ufs/ffs/ffs_softdep.c	Sun Sep  6 11:46:51 2009	(r196888)
@@ -5977,12 +5977,19 @@ clear_remove(td)
 			if (vn_start_write(NULL, &mp, V_NOWAIT) != 0)
 				continue;
 			FREE_LOCK(&lk);
-			if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
-			     FFSV_FORCEINSMQ))) {
+
+			/*
+			 * Let unmount clear deps
+			 */
+			error = vfs_busy(mp, MBF_NOWAIT);
+			if (error != 0)
+				goto finish_write;
+			error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
+			     FFSV_FORCEINSMQ);
+			vfs_unbusy(mp);
+			if (error != 0) {
 				softdep_error("clear_remove: vget", error);
-				vn_finished_write(mp);
-				ACQUIRE_LOCK(&lk);
-				return;
+				goto finish_write;
 			}
 			if ((error = ffs_syncvnode(vp, MNT_NOWAIT)))
 				softdep_error("clear_remove: fsync", error);
@@ -5991,6 +5998,7 @@ clear_remove(td)
 			drain_output(vp);
 			BO_UNLOCK(bo);
 			vput(vp);
+		finish_write:
 			vn_finished_write(mp);
 			ACQUIRE_LOCK(&lk);
 			return;
@@ -6050,13 +6058,21 @@ clear_inodedeps(td)
 		if (vn_start_write(NULL, &mp, V_NOWAIT) != 0)
 			continue;
 		FREE_LOCK(&lk);
+		error = vfs_busy(mp, MBF_NOWAIT); /* Let unmount clear deps */
+		if (error != 0) {
+			vn_finished_write(mp);
+			ACQUIRE_LOCK(&lk);
+			return;
+		}
 		if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
 		    FFSV_FORCEINSMQ)) != 0) {
 			softdep_error("clear_inodedeps: vget", error);
+			vfs_unbusy(mp);
 			vn_finished_write(mp);
 			ACQUIRE_LOCK(&lk);
 			return;
 		}
+		vfs_unbusy(mp);
 		if (ino == lastino) {
 			if ((error = ffs_syncvnode(vp, MNT_WAIT)))
 				softdep_error("clear_inodedeps: fsync1", error);



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