diff options
| -rw-r--r-- | fs/xfs/xfs_super.c | 30 | ||||
| -rw-r--r-- | fs/xfs/xfs_sync.c | 36 | ||||
| -rw-r--r-- | fs/xfs/xfs_sync.h | 2 |
3 files changed, 43 insertions, 25 deletions
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 3eca58f51ae9..8a899496fd5f 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
| @@ -869,27 +869,6 @@ xfs_fs_dirty_inode( | |||
| 869 | } | 869 | } |
| 870 | 870 | ||
| 871 | STATIC int | 871 | STATIC int |
| 872 | xfs_log_inode( | ||
| 873 | struct xfs_inode *ip) | ||
| 874 | { | ||
| 875 | struct xfs_mount *mp = ip->i_mount; | ||
| 876 | struct xfs_trans *tp; | ||
| 877 | int error; | ||
| 878 | |||
| 879 | tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); | ||
| 880 | error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); | ||
| 881 | if (error) { | ||
| 882 | xfs_trans_cancel(tp, 0); | ||
| 883 | return error; | ||
| 884 | } | ||
| 885 | |||
| 886 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 887 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
| 888 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
| 889 | return xfs_trans_commit(tp, 0); | ||
| 890 | } | ||
| 891 | |||
| 892 | STATIC int | ||
| 893 | xfs_fs_write_inode( | 872 | xfs_fs_write_inode( |
| 894 | struct inode *inode, | 873 | struct inode *inode, |
| 895 | struct writeback_control *wbc) | 874 | struct writeback_control *wbc) |
| @@ -902,10 +881,8 @@ xfs_fs_write_inode( | |||
| 902 | 881 | ||
| 903 | if (XFS_FORCED_SHUTDOWN(mp)) | 882 | if (XFS_FORCED_SHUTDOWN(mp)) |
| 904 | return -XFS_ERROR(EIO); | 883 | return -XFS_ERROR(EIO); |
| 905 | if (!ip->i_update_core) | ||
| 906 | return 0; | ||
| 907 | 884 | ||
| 908 | if (wbc->sync_mode == WB_SYNC_ALL) { | 885 | if (wbc->sync_mode == WB_SYNC_ALL || wbc->for_kupdate) { |
| 909 | /* | 886 | /* |
| 910 | * Make sure the inode has made it it into the log. Instead | 887 | * Make sure the inode has made it it into the log. Instead |
| 911 | * of forcing it all the way to stable storage using a | 888 | * of forcing it all the way to stable storage using a |
| @@ -913,11 +890,14 @@ xfs_fs_write_inode( | |||
| 913 | * ->sync_fs call do that for thus, which reduces the number | 890 | * ->sync_fs call do that for thus, which reduces the number |
| 914 | * of synchronous log forces dramatically. | 891 | * of synchronous log forces dramatically. |
| 915 | */ | 892 | */ |
| 916 | error = xfs_log_inode(ip); | 893 | error = xfs_log_dirty_inode(ip, NULL, 0); |
| 917 | if (error) | 894 | if (error) |
| 918 | goto out; | 895 | goto out; |
| 919 | return 0; | 896 | return 0; |
| 920 | } else { | 897 | } else { |
| 898 | if (!ip->i_update_core) | ||
| 899 | return 0; | ||
| 900 | |||
| 921 | /* | 901 | /* |
| 922 | * We make this non-blocking if the inode is contended, return | 902 | * We make this non-blocking if the inode is contended, return |
| 923 | * EAGAIN to indicate to the caller that they did not succeed. | 903 | * EAGAIN to indicate to the caller that they did not succeed. |
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( | |||
| 336 | return error; | 336 | return error; |
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | int | ||
| 340 | xfs_log_dirty_inode( | ||
| 341 | struct xfs_inode *ip, | ||
| 342 | struct xfs_perag *pag, | ||
| 343 | int flags) | ||
| 344 | { | ||
| 345 | struct xfs_mount *mp = ip->i_mount; | ||
| 346 | struct xfs_trans *tp; | ||
| 347 | int error; | ||
| 348 | |||
| 349 | if (!ip->i_update_core) | ||
| 350 | return 0; | ||
| 351 | |||
| 352 | tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); | ||
| 353 | error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); | ||
| 354 | if (error) { | ||
| 355 | xfs_trans_cancel(tp, 0); | ||
| 356 | return error; | ||
| 357 | } | ||
| 358 | |||
| 359 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 360 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
| 361 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
| 362 | return xfs_trans_commit(tp, 0); | ||
| 363 | } | ||
| 364 | |||
| 339 | /* | 365 | /* |
| 340 | * When remounting a filesystem read-only or freezing the filesystem, we have | 366 | * When remounting a filesystem read-only or freezing the filesystem, we have |
| 341 | * two phases to execute. This first phase is syncing the data before we | 367 | * two phases to execute. This first phase is syncing the data before we |
| @@ -359,6 +385,16 @@ xfs_quiesce_data( | |||
| 359 | { | 385 | { |
| 360 | int error, error2 = 0; | 386 | int error, error2 = 0; |
| 361 | 387 | ||
| 388 | /* | ||
| 389 | * Log all pending size and timestamp updates. The vfs writeback | ||
| 390 | * code is supposed to do this, but due to its overagressive | ||
| 391 | * livelock detection it will skip inodes where appending writes | ||
| 392 | * were written out in the first non-blocking sync phase if their | ||
| 393 | * completion took long enough that it happened after taking the | ||
| 394 | * timestamp for the cut-off in the blocking phase. | ||
| 395 | */ | ||
| 396 | xfs_inode_ag_iterator(mp, xfs_log_dirty_inode, 0); | ||
| 397 | |||
| 362 | xfs_qm_sync(mp, SYNC_TRYLOCK); | 398 | xfs_qm_sync(mp, SYNC_TRYLOCK); |
| 363 | xfs_qm_sync(mp, SYNC_WAIT); | 399 | xfs_qm_sync(mp, SYNC_WAIT); |
| 364 | 400 | ||
diff --git a/fs/xfs/xfs_sync.h b/fs/xfs/xfs_sync.h index 941202e7ac6e..fa965479d788 100644 --- a/fs/xfs/xfs_sync.h +++ b/fs/xfs/xfs_sync.h | |||
| @@ -34,6 +34,8 @@ void xfs_quiesce_attr(struct xfs_mount *mp); | |||
| 34 | 34 | ||
| 35 | void xfs_flush_inodes(struct xfs_inode *ip); | 35 | void xfs_flush_inodes(struct xfs_inode *ip); |
| 36 | 36 | ||
| 37 | int xfs_log_dirty_inode(struct xfs_inode *ip, struct xfs_perag *pag, int flags); | ||
| 38 | |||
| 37 | int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); | 39 | int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); |
| 38 | int xfs_reclaim_inodes_count(struct xfs_mount *mp); | 40 | int xfs_reclaim_inodes_count(struct xfs_mount *mp); |
| 39 | void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan); | 41 | void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan); |
