diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-12-30 05:05:45 +0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-12-30 05:05:45 +0400 |
| commit | d2bac6ab932a407008a95d1993702f0a92f8f35e (patch) | |
| tree | d09fb1504fa650200e761a54f6ebc05a4a60623b /fs/xfs/xfs_sync.c | |
| parent | 1cac8e884fbea0b10ee5692cd97e456b58c34ce5 (diff) | |
| parent | be4f1ac828776bbc7868a68b465cd8eedb733cfd (diff) | |
| download | linux-d2bac6ab932a407008a95d1993702f0a92f8f35e.tar.xz | |
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs:
xfs: log all dirty inodes in xfs_fs_sync_fs
xfs: log the inode in ->write_inode calls for kupdate
Diffstat (limited to 'fs/xfs/xfs_sync.c')
| -rw-r--r-- | fs/xfs/xfs_sync.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index be5c51d8f757..f0994aedcd15 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c @@ -336,6 +336,32 @@ xfs_sync_fsdata( return error; } +int +xfs_log_dirty_inode( + struct xfs_inode *ip, + struct xfs_perag *pag, + int flags) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + int error; + + if (!ip->i_update_core) + return 0; + + tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); + error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); + if (error) { + xfs_trans_cancel(tp, 0); + return error; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + return xfs_trans_commit(tp, 0); +} + /* * 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 @@ -359,6 +385,16 @@ xfs_quiesce_data( { int error, error2 = 0; + /* + * Log all pending size and timestamp updates. The vfs writeback + * code is supposed to do this, but due to its overagressive + * livelock detection it will skip inodes where appending writes + * were written out in the first non-blocking sync phase if their + * completion took long enough that it happened after taking the + * timestamp for the cut-off in the blocking phase. + */ + xfs_inode_ag_iterator(mp, xfs_log_dirty_inode, 0); + xfs_qm_sync(mp, SYNC_TRYLOCK); xfs_qm_sync(mp, SYNC_WAIT); |
