xfs: ensure log covering transactions are synchronous
authorDave Chinner <dchinner@redhat.com>
Tue, 4 Jan 2011 04:49:29 +0000 (04:49 +0000)
committerAlex Elder <aelder@sgi.com>
Wed, 12 Jan 2011 02:28:17 +0000 (20:28 -0600)
To ensure the log is covered and the filesystem idles correctly, we
need to ensure that dummy transactions hit the disk and do not stay
pinned in memory.  If the superblock is pinned in memory, it can't
be flushed so the log covering cannot make progress. The result is
dependent on timing - more oftent han not we continue to issues a
log covering transaction every 36s rather than idling after ~90s.

Fix this by making the log covering transaction synchronous. To
avoid additional log force from xfssyncd, make the log covering
transaction take the place of the existing log force in the xfssyncd
background sync process.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_fsops.h

index c51faaa5e2918db636a2dc8d12a8a3ce1533d215..af32f375ca961d73fbb25233133c9931fba8b97b 100644 (file)
@@ -1413,7 +1413,7 @@ xfs_fs_freeze(
 
        xfs_save_resvblks(mp);
        xfs_quiesce_attr(mp);
-       return -xfs_fs_log_dummy(mp, SYNC_WAIT);
+       return -xfs_fs_log_dummy(mp);
 }
 
 STATIC int
index a02480de97599936e21389dae8e6e98a51883740..e22f0057d21fa8d2d3e04c11a2e62438ac17a3e9 100644 (file)
@@ -362,7 +362,7 @@ xfs_quiesce_data(
 
        /* mark the log as covered if needed */
        if (xfs_log_need_covered(mp))
-               error2 = xfs_fs_log_dummy(mp, SYNC_WAIT);
+               error2 = xfs_fs_log_dummy(mp);
 
        /* flush data-only devices */
        if (mp->m_rtdev_targp)
@@ -503,13 +503,14 @@ xfs_sync_worker(
        int             error;
 
        if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
-               xfs_log_force(mp, 0);
-               xfs_reclaim_inodes(mp, 0);
                /* dgc: errors ignored here */
-               error = xfs_qm_sync(mp, SYNC_TRYLOCK);
                if (mp->m_super->s_frozen == SB_UNFROZEN &&
                    xfs_log_need_covered(mp))
-                       error = xfs_fs_log_dummy(mp, 0);
+                       error = xfs_fs_log_dummy(mp);
+               else
+                       xfs_log_force(mp, 0);
+               xfs_reclaim_inodes(mp, 0);
+               error = xfs_qm_sync(mp, SYNC_TRYLOCK);
        }
        mp->m_sync_seq++;
        wake_up(&mp->m_wait_single_sync_task);
index f56d30e8040cdef5120895a2499ed7c05e23b923..cec89dd5d7d28262ae064e257ec941a815cbb09f 100644 (file)
@@ -612,12 +612,13 @@ out:
  *
  * We cannot use an inode here for this - that will push dirty state back up
  * into the VFS and then periodic inode flushing will prevent log covering from
- * making progress. Hence we log a field in the superblock instead.
+ * making progress. Hence we log a field in the superblock instead and use a
+ * synchronous transaction to ensure the superblock is immediately unpinned
+ * and can be written back.
  */
 int
 xfs_fs_log_dummy(
-       xfs_mount_t     *mp,
-       int             flags)
+       xfs_mount_t     *mp)
 {
        xfs_trans_t     *tp;
        int             error;
@@ -632,8 +633,7 @@ xfs_fs_log_dummy(
 
        /* log the UUID because it is an unchanging field */
        xfs_mod_sb(tp, XFS_SB_UUID);
-       if (flags & SYNC_WAIT)
-               xfs_trans_set_sync(tp);
+       xfs_trans_set_sync(tp);
        return xfs_trans_commit(tp, 0);
 }
 
index a786c5212c1e478677e46f2725105a010ebd1262..1b6a98b66886c76d1fab032673ec88f4cb11afa0 100644 (file)
@@ -25,6 +25,6 @@ extern int xfs_fs_counts(xfs_mount_t *mp, xfs_fsop_counts_t *cnt);
 extern int xfs_reserve_blocks(xfs_mount_t *mp, __uint64_t *inval,
                                xfs_fsop_resblks_t *outval);
 extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags);
-extern int xfs_fs_log_dummy(xfs_mount_t *mp, int flags);
+extern int xfs_fs_log_dummy(struct xfs_mount *mp);
 
 #endif /* __XFS_FSOPS_H__ */