From 2e1ddcb5660c34e607974e7c57f48441b634d984 Mon Sep 17 00:00:00 2001 From: kib Date: Sun, 6 Sep 2009 11:46:51 +0000 Subject: 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 --- sys/ufs/ffs/ffs_softdep.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'sys/ufs/ffs/ffs_softdep.c') diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 5f16280..4d652c1 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -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); -- cgit v1.1