summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-09-06 11:46:51 +0000
committerkib <kib@FreeBSD.org>2009-09-06 11:46:51 +0000
commit2e1ddcb5660c34e607974e7c57f48441b634d984 (patch)
treee884d99acd1c1411919d65a14e1a268ee484d9c6 /sys/ufs
parent14578a32762c68f2642b1efa67688539a49d1042 (diff)
downloadFreeBSD-src-2e1ddcb5660c34e607974e7c57f48441b634d984.zip
FreeBSD-src-2e1ddcb5660c34e607974e7c57f48441b634d984.tar.gz
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
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_softdep.c26
1 files changed, 21 insertions, 5 deletions
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);
OpenPOWER on IntegriCloud