Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=516b2e7c2661615ba5d5ad9fb584f068363502d3
Commit:     516b2e7c2661615ba5d5ad9fb584f068363502d3
Parent:     957d0ebed04239b734552c7da3fae9094b6f090c
Author:     David Chinner <[EMAIL PROTECTED]>
AuthorDate: Mon Jun 18 16:50:48 2007 +1000
Committer:  Tim Shimmin <[EMAIL PROTECTED]>
CommitDate: Sat Jul 14 15:35:58 2007 +1000

    [XFS] Fix remount,readonly path to flush everything correctly.
    
    The remount readonly path can fail to writeback properly because we still
    have active transactions after calling xfs_quiesce_fs(). Further
    investigation shows that this path is broken in the same ways that the xfs
    freeze path was broken so fix it the same way.
    
    SGI-PV: 964464
    SGI-Modid: xfs-linux-melb:xfs-kern:28869a
    
    Signed-off-by: David Chinner <[EMAIL PROTECTED]>
    Signed-off-by: Christoph Hellwig <[EMAIL PROTECTED]>
    Signed-off-by: Tim Shimmin <[EMAIL PROTECTED]>
---
 fs/xfs/linux-2.6/xfs_super.c |    2 +-
 fs/xfs/linux-2.6/xfs_vfs.h   |   14 +++++++++++
 fs/xfs/xfs_vfsops.c          |   53 ++++++++++++++++++++++++-----------------
 3 files changed, 46 insertions(+), 23 deletions(-)

diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 05f188e..06894cf 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -664,7 +664,7 @@ xfs_fs_sync_super(
                 * occur here so don't bother flushing the buftarg (i.e
                 * SYNC_QUIESCE) because it'll just get dirty again.
                 */
-               flags = SYNC_FSDATA | SYNC_DELWRI | SYNC_WAIT | SYNC_IOWAIT;
+               flags = SYNC_DATA_QUIESCE;
        } else
                flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
 
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index cb7b0d6..dca3481 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -94,6 +94,20 @@ typedef enum {
 #define SYNC_IOWAIT            0x0100  /* wait for all I/O to complete */
 #define SYNC_SUPER             0x0200  /* flush superblock to disk */
 
+/*
+ * When remounting a filesystem read-only or freezing the filesystem,
+ * we have two phases to execute. This first phase is syncing the data
+ * before we quiesce the fielsystem, and the second is flushing all the
+ * inodes out after we've waited for all the transactions created by
+ * the first phase to complete. The second phase uses SYNC_INODE_QUIESCE
+ * to ensure that the inodes are written to their location on disk
+ * rather than just existing in transactions in the log. This means
+ * after a quiesce there is no log replay required to write the inodes
+ * to disk (this is the main difference between a sync and a quiesce).
+ */
+#define SYNC_DATA_QUIESCE      (SYNC_DELWRI|SYNC_FSDATA|SYNC_WAIT|SYNC_IOWAIT)
+#define SYNC_INODE_QUIESCE     (SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)
+
 #define SHUTDOWN_META_IO_ERROR 0x0001  /* write attempt to metadata failed */
 #define SHUTDOWN_LOG_IO_ERROR  0x0002  /* write attempt to the log failed */
 #define SHUTDOWN_FORCE_UMOUNT  0x0004  /* shutdown from a forced unmount */
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 3a64733..c343fde 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -640,7 +640,7 @@ xfs_quiesce_fs(
         * we can write the unmount record.
         */
        do {
-               xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, NULL);
+               xfs_syncsub(mp, SYNC_INODE_QUIESCE, NULL);
                pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
                if (!pincount) {
                        delay(50);
@@ -651,6 +651,30 @@ xfs_quiesce_fs(
        return 0;
 }
 
+/*
+ * Second stage of a quiesce. The data is already synced, now we have to take
+ * care of the metadata. New transactions are already blocked, so we need to
+ * wait for any remaining transactions to drain out before proceding.
+ */
+STATIC void
+xfs_attr_quiesce(
+       xfs_mount_t     *mp)
+{
+       /* wait for all modifications to complete */
+       while (atomic_read(&mp->m_active_trans) > 0)
+               delay(100);
+
+       /* flush inodes and push all remaining buffers out to disk */
+       xfs_quiesce_fs(mp);
+
+       ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
+
+       /* Push the superblock and write an unmount record */
+       xfs_log_sbcount(mp, 1);
+       xfs_log_unmount_write(mp);
+       xfs_unmountfs_writesb(mp);
+}
+
 STATIC int
 xfs_mntupdate(
        bhv_desc_t                      *bdp,
@@ -670,11 +694,8 @@ xfs_mntupdate(
                        mp->m_flags &= ~XFS_MOUNT_BARRIER;
                }
        } else if (!(vfsp->vfs_flag & VFS_RDONLY)) {    /* rw -> ro */
-               bhv_vfs_sync(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL);
-               xfs_quiesce_fs(mp);
-               xfs_log_sbcount(mp, 1);
-               xfs_log_unmount_write(mp);
-               xfs_unmountfs_writesb(mp);
+               bhv_vfs_sync(vfsp, SYNC_DATA_QUIESCE, NULL);
+               xfs_attr_quiesce(mp);
                vfsp->vfs_flag |= VFS_RDONLY;
        }
        return 0;
@@ -1952,9 +1973,9 @@ xfs_showargs(
 }
 
 /*
- * Second stage of a freeze. The data is already frozen, now we have to take
- * care of the metadata. New transactions are already blocked, so we need to
- * wait for any remaining transactions to drain out before proceding.
+ * Second stage of a freeze. The data is already frozen so we only
+ * need to take care of themetadata. Once that's done write a dummy
+ * record to dirty the log in case of a crash while frozen.
  */
 STATIC void
 xfs_freeze(
@@ -1962,19 +1983,7 @@ xfs_freeze(
 {
        xfs_mount_t     *mp = XFS_BHVTOM(bdp);
 
-       /* wait for all modifications to complete */
-       while (atomic_read(&mp->m_active_trans) > 0)
-               delay(100);
-
-       /* flush inodes and push all remaining buffers out to disk */
-       xfs_quiesce_fs(mp);
-
-       ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
-
-       /* Push the superblock and write an unmount record */
-       xfs_log_sbcount(mp, 1);
-       xfs_log_unmount_write(mp);
-       xfs_unmountfs_writesb(mp);
+       xfs_attr_quiesce(mp);
        xfs_fs_log_dummy(mp);
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to