From b6045bc3343218d0a71037c8680645b801452ec4 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Thu, 30 Oct 2008 17:15:50 +1100 Subject: [PATCH] --- yaml --- r: 124832 b: refs/heads/master c: e9f1c6ee12955fd8657f6f0f9a3d09112b1f1fdd h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/xfs/linux-2.6/xfs_super.c | 25 +++++------------- trunk/fs/xfs/linux-2.6/xfs_sync.c | 42 +++++++++++++++++++++++++++++- trunk/fs/xfs/linux-2.6/xfs_sync.h | 3 +++ trunk/fs/xfs/xfs_vfsops.c | 1 - 5 files changed, 51 insertions(+), 22 deletions(-) diff --git a/[refs] b/[refs] index d503a582c19a..16952b8b9822 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: be97d9d5577f6c8a36588e2f262c772c5422b128 +refs/heads/master: e9f1c6ee12955fd8657f6f0f9a3d09112b1f1fdd diff --git a/trunk/fs/xfs/linux-2.6/xfs_super.c b/trunk/fs/xfs/linux-2.6/xfs_super.c index 38d380a7ca23..376f32d92475 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_super.c +++ b/trunk/fs/xfs/linux-2.6/xfs_super.c @@ -998,7 +998,6 @@ xfs_fs_put_super( int error; xfs_syncd_stop(mp); - xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC); xfs_sync_inodes(mp, SYNC_ATTR|SYNC_DELWRI); #ifdef HAVE_DMAPI @@ -1057,7 +1056,7 @@ xfs_fs_write_super( struct super_block *sb) { if (!(sb->s_flags & MS_RDONLY)) - xfs_sync(XFS_M(sb), SYNC_FSDATA); + xfs_sync_fsdata(XFS_M(sb), 0); sb->s_dirt = 0; } @@ -1068,7 +1067,6 @@ xfs_fs_sync_super( { struct xfs_mount *mp = XFS_M(sb); int error; - int flags; /* * Treat a sync operation like a freeze. This is to work @@ -1082,20 +1080,10 @@ xfs_fs_sync_super( * dirty the Linux inode until after the transaction I/O * completes. */ - if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) { - /* - * First stage of freeze - no more writers will make progress - * now we are here, so we flush delwri and delalloc buffers - * here, then wait for all I/O to complete. Data is frozen at - * that point. Metadata is not frozen, transactions can still - * occur here so don't bother flushing the buftarg (i.e - * SYNC_QUIESCE) because it'll just get dirty again. - */ - flags = SYNC_DATA_QUIESCE; - } else - flags = SYNC_FSDATA; - - error = xfs_sync(mp, flags); + if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) + error = xfs_quiesce_data(mp); + else + error = xfs_sync_fsdata(mp, 0); sb->s_dirt = 0; if (unlikely(laptop_mode)) { @@ -1233,8 +1221,7 @@ xfs_fs_remount( /* rw -> ro */ if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) { - xfs_filestream_flush(mp); - xfs_sync(mp, SYNC_DATA_QUIESCE); + xfs_quiesce_data(mp); xfs_attr_quiesce(mp); mp->m_flags |= XFS_MOUNT_RDONLY; } diff --git a/trunk/fs/xfs/linux-2.6/xfs_sync.c b/trunk/fs/xfs/linux-2.6/xfs_sync.c index 002ccb6f0cbe..838070ce7249 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_sync.c +++ b/trunk/fs/xfs/linux-2.6/xfs_sync.c @@ -217,12 +217,16 @@ xfs_sync_inodes( int error; int last_error; int i; + int lflags = XFS_LOG_FORCE; if (mp->m_flags & XFS_MOUNT_RDONLY) return 0; error = 0; last_error = 0; + if (flags & SYNC_WAIT) + lflags |= XFS_LOG_SYNC; + for (i = 0; i < mp->m_sb.sb_agcount; i++) { if (!mp->m_perag[i].pag_ici_init) continue; @@ -232,6 +236,9 @@ xfs_sync_inodes( if (error == EFSCORRUPTED) break; } + if (flags & SYNC_DELWRI) + xfs_log_force(mp, 0, lflags); + return XFS_ERROR(last_error); } @@ -269,7 +276,7 @@ xfs_commit_dummy_trans( return 0; } -STATIC int +int xfs_sync_fsdata( struct xfs_mount *mp, int flags) @@ -322,6 +329,39 @@ xfs_sync_fsdata( return error; } +/* + * First stage of freeze - no more writers will make progress now we are here, + * so we flush delwri and delalloc buffers here, then wait for all I/O to + * complete. Data is frozen at that point. Metadata is not frozen, + * transactions can still occur here so don't bother flushing the buftarg (i.e + * SYNC_QUIESCE) because it'll just get dirty again. + */ +int +xfs_quiesce_data( + struct xfs_mount *mp) +{ + int error; + + /* push non-blocking */ + xfs_sync_inodes(mp, SYNC_DELWRI|SYNC_BDFLUSH); + XFS_QM_DQSYNC(mp, SYNC_BDFLUSH); + xfs_filestream_flush(mp); + + /* push and block */ + xfs_sync_inodes(mp, SYNC_DELWRI|SYNC_WAIT|SYNC_IOWAIT); + XFS_QM_DQSYNC(mp, SYNC_WAIT); + + /* write superblock and hoover shutdown errors */ + error = xfs_sync_fsdata(mp, 0); + + /* flush devices */ + XFS_bflush(mp->m_ddev_targp); + if (mp->m_rtdev_targp) + XFS_bflush(mp->m_rtdev_targp); + + return error; +} + /* * xfs_sync flushes any pending I/O to file system vfsp. * diff --git a/trunk/fs/xfs/linux-2.6/xfs_sync.h b/trunk/fs/xfs/linux-2.6/xfs_sync.h index 5316915c0834..fcd4040c9ad1 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_sync.h +++ b/trunk/fs/xfs/linux-2.6/xfs_sync.h @@ -55,6 +55,9 @@ void xfs_syncd_stop(struct xfs_mount *mp); int xfs_sync(struct xfs_mount *mp, int flags); int xfs_sync_inodes(struct xfs_mount *mp, int flags); +int xfs_sync_fsdata(struct xfs_mount *mp, int flags); + +int xfs_quiesce_data(struct xfs_mount *mp); void xfs_flush_inode(struct xfs_inode *ip); void xfs_flush_device(struct xfs_inode *ip); diff --git a/trunk/fs/xfs/xfs_vfsops.c b/trunk/fs/xfs/xfs_vfsops.c index c82b9555959b..b55a9bb3a6e3 100644 --- a/trunk/fs/xfs/xfs_vfsops.c +++ b/trunk/fs/xfs/xfs_vfsops.c @@ -75,7 +75,6 @@ xfs_quiesce_fs( * logged before we can write the unmount record. */ do { - xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC); xfs_sync_inodes(mp, SYNC_ATTR|SYNC_WAIT); pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1); if (!pincount) {