Merge branch 'work.d_name' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-microblaze.git] / fs / xfs / xfs_log.c
index a613f00..0604183 100644 (file)
@@ -1069,7 +1069,7 @@ xfs_log_need_covered(
        bool                    needed = false;
 
        if (!xlog_cil_empty(log))
-               return 0;
+               return false;
 
        spin_lock(&log->l_icloglock);
        switch (log->l_covered_state) {
@@ -1108,16 +1108,31 @@ static int
 xfs_log_cover(
        struct xfs_mount        *mp)
 {
-       struct xlog             *log = mp->m_log;
        int                     error = 0;
+       bool                    need_covered;
 
-       ASSERT((xlog_cil_empty(log) && xlog_iclogs_empty(log) &&
-               !xfs_ail_min_lsn(log->l_ailp)) ||
+       ASSERT((xlog_cil_empty(mp->m_log) && xlog_iclogs_empty(mp->m_log) &&
+               !xfs_ail_min_lsn(mp->m_log->l_ailp)) ||
               XFS_FORCED_SHUTDOWN(mp));
 
        if (!xfs_log_writable(mp))
                return 0;
 
+       /*
+        * xfs_log_need_covered() is not idempotent because it progresses the
+        * state machine if the log requires covering. Therefore, we must call
+        * this function once and use the result until we've issued an sb sync.
+        * Do so first to make that abundantly clear.
+        *
+        * Fall into the covering sequence if the log needs covering or the
+        * mount has lazy superblock accounting to sync to disk. The sb sync
+        * used for covering accumulates the in-core counters, so covering
+        * handles this for us.
+        */
+       need_covered = xfs_log_need_covered(mp);
+       if (!need_covered && !xfs_sb_version_haslazysbcount(&mp->m_sb))
+               return 0;
+
        /*
         * To cover the log, commit the superblock twice (at most) in
         * independent checkpoints. The first serves as a reference for the
@@ -1127,12 +1142,12 @@ xfs_log_cover(
         * covering the log. Push the AIL one more time to leave it empty, as
         * we found it.
         */
-       while (xfs_log_need_covered(mp)) {
+       do {
                error = xfs_sync_sb(mp, true);
                if (error)
                        break;
                xfs_ail_push_all_sync(mp->m_ail);
-       }
+       } while (xfs_log_need_covered(mp));
 
        return error;
 }
@@ -1477,8 +1492,9 @@ xlog_alloc_log(
        log->l_iclog->ic_prev = prev_iclog;     /* re-write 1st prev ptr */
 
        log->l_ioend_workqueue = alloc_workqueue("xfs-log/%s",
-                       WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_HIGHPRI, 0,
-                       mp->m_super->s_id);
+                       XFS_WQFLAGS(WQ_FREEZABLE | WQ_MEM_RECLAIM |
+                                   WQ_HIGHPRI),
+                       0, mp->m_super->s_id);
        if (!log->l_ioend_workqueue)
                goto out_free_iclog;