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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to