Author: kib
Date: Mon Dec 21 11:50:32 2015
New Revision: 292541
URL: https://svnweb.freebsd.org/changeset/base/292541

Log:
  Recheck curthread->td_su after the VFS_SYNC() call, and re-sync if the
  ast was rescheduled during VFS_SYNC().  It is possible that enough
  parallel writes or slow/hung volume result in VFS_SYNC() deferring to
  the ast flushing of workqueue.
  
  Reported and tested by:       pho
  Sponsored by: The FreeBSD Foundation
  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      Mon Dec 21 11:44:54 2015        
(r292540)
+++ head/sys/ufs/ffs/ffs_softdep.c      Mon Dec 21 11:50:32 2015        
(r292541)
@@ -13301,43 +13301,43 @@ softdep_ast_cleanup_proc(void)
        bool req;
 
        td = curthread;
-       mp = td->td_su;
-       if (mp == NULL)
-               return;
-       td->td_su = NULL;
-       error = vfs_busy(mp, MBF_NOWAIT);
-       vfs_rel(mp);
-       if (error != 0)
-               return;
-       if (ffs_own_mount(mp) && MOUNTEDSOFTDEP(mp)) {
-               ump = VFSTOUFS(mp);
-               for (;;) {
-                       req = false;
-                       ACQUIRE_LOCK(ump);
-                       if (softdep_excess_items(ump, D_INODEDEP)) {
-                               req = true;
-                               request_cleanup(mp, FLUSH_INODES);
-                       }
-                       if (softdep_excess_items(ump, D_DIRREM)) {
-                               req = true;
-                               request_cleanup(mp, FLUSH_BLOCKS);
-                       }
-                       FREE_LOCK(ump);
-                       if (softdep_excess_items(ump, D_NEWBLK) ||
-                           softdep_excess_items(ump, D_ALLOCDIRECT) ||
-                           softdep_excess_items(ump, D_ALLOCINDIR)) {
-                               error = vn_start_write(NULL, &mp, V_WAIT);
-                               if (error == 0) {
+       while ((mp = td->td_su) != NULL) {
+               td->td_su = NULL;
+               error = vfs_busy(mp, MBF_NOWAIT);
+               vfs_rel(mp);
+               if (error != 0)
+                       return;
+               if (ffs_own_mount(mp) && MOUNTEDSOFTDEP(mp)) {
+                       ump = VFSTOUFS(mp);
+                       for (;;) {
+                               req = false;
+                               ACQUIRE_LOCK(ump);
+                               if (softdep_excess_items(ump, D_INODEDEP)) {
                                        req = true;
-                                       VFS_SYNC(mp, MNT_WAIT);
-                                       vn_finished_write(mp);
+                                       request_cleanup(mp, FLUSH_INODES);
                                }
+                               if (softdep_excess_items(ump, D_DIRREM)) {
+                                       req = true;
+                                       request_cleanup(mp, FLUSH_BLOCKS);
+                               }
+                               FREE_LOCK(ump);
+                               if (softdep_excess_items(ump, D_NEWBLK) ||
+                                   softdep_excess_items(ump, D_ALLOCDIRECT) ||
+                                   softdep_excess_items(ump, D_ALLOCINDIR)) {
+                                       error = vn_start_write(NULL, &mp,
+                                           V_WAIT);
+                                       if (error == 0) {
+                                               req = true;
+                                               VFS_SYNC(mp, MNT_WAIT);
+                                               vn_finished_write(mp);
+                                       }
+                               }
+                               if ((td->td_pflags & TDP_KTHREAD) != 0 || !req)
+                                       break;
                        }
-                       if ((td->td_pflags & TDP_KTHREAD) != 0 || !req)
-                               break;
                }
+               vfs_unbusy(mp);
        }
-       vfs_unbusy(mp);
 }
 
 /*
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to