diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-02-29 04:53:52 -0500 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-03-13 18:01:15 -0400 |
commit | 8a9c9980f24f6d86e0ec0150ed35fba45d0c9f88 (patch) | |
tree | df976343a603bad7e6bdc20db31c64f752312434 /fs/xfs/xfs_super.c | |
parent | 281627df3eb55e1b729b9bb06fff5ff112929646 (diff) |
xfs: log timestamp updates
Timestamps on regular files are the last metadata that XFS does not update
transactionally. Now that we use the delaylog mode exclusively and made
the log scode scale extremly well there is no need to bypass that code for
timestamp updates. Logging all updates allows to drop a lot of code, and
will allow for further performance improvements later on.
Note that this patch drops optimized handling of fdatasync - it will be
added back in a separate commit.
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_super.c')
-rw-r--r-- | fs/xfs/xfs_super.c | 108 |
1 files changed, 37 insertions, 71 deletions
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index c7f7bc2855a4..e602c8c67c5c 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
@@ -863,91 +863,58 @@ xfs_fs_inode_init_once( | |||
863 | } | 863 | } |
864 | 864 | ||
865 | /* | 865 | /* |
866 | * Dirty the XFS inode when mark_inode_dirty_sync() is called so that | 866 | * This is called by the VFS when dirtying inode metadata. This can happen |
867 | * we catch unlogged VFS level updates to the inode. | 867 | * for a few reasons, but we only care about timestamp updates, given that |
868 | * we handled the rest ourselves. In theory no other calls should happen, | ||
869 | * but for example generic_write_end() keeps dirtying the inode after | ||
870 | * updating i_size. Thus we check that the flags are exactly I_DIRTY_SYNC, | ||
871 | * and skip this call otherwise. | ||
868 | * | 872 | * |
869 | * We need the barrier() to maintain correct ordering between unlogged | 873 | * We'll hopefull get a different method just for updating timestamps soon, |
870 | * updates and the transaction commit code that clears the i_update_core | 874 | * at which point this hack can go away, and maybe we'll also get real |
871 | * field. This requires all updates to be completed before marking the | 875 | * error handling here. |
872 | * inode dirty. | ||
873 | */ | 876 | */ |
874 | STATIC void | 877 | STATIC void |
875 | xfs_fs_dirty_inode( | 878 | xfs_fs_dirty_inode( |
876 | struct inode *inode, | ||
877 | int flags) | ||
878 | { | ||
879 | barrier(); | ||
880 | XFS_I(inode)->i_update_core = 1; | ||
881 | } | ||
882 | |||
883 | STATIC int | ||
884 | xfs_fs_write_inode( | ||
885 | struct inode *inode, | 879 | struct inode *inode, |
886 | struct writeback_control *wbc) | 880 | int flags) |
887 | { | 881 | { |
888 | struct xfs_inode *ip = XFS_I(inode); | 882 | struct xfs_inode *ip = XFS_I(inode); |
889 | struct xfs_mount *mp = ip->i_mount; | 883 | struct xfs_mount *mp = ip->i_mount; |
890 | int error = EAGAIN; | 884 | struct xfs_trans *tp; |
891 | 885 | int error; | |
892 | trace_xfs_write_inode(ip); | ||
893 | |||
894 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
895 | return -XFS_ERROR(EIO); | ||
896 | |||
897 | if (wbc->sync_mode == WB_SYNC_ALL || wbc->for_kupdate) { | ||
898 | /* | ||
899 | * Make sure the inode has made it it into the log. Instead | ||
900 | * of forcing it all the way to stable storage using a | ||
901 | * synchronous transaction we let the log force inside the | ||
902 | * ->sync_fs call do that for thus, which reduces the number | ||
903 | * of synchronous log forces dramatically. | ||
904 | */ | ||
905 | error = xfs_log_dirty_inode(ip, NULL, 0); | ||
906 | if (error) | ||
907 | goto out; | ||
908 | return 0; | ||
909 | } else { | ||
910 | if (!ip->i_update_core) | ||
911 | return 0; | ||
912 | 886 | ||
913 | /* | 887 | if (flags != I_DIRTY_SYNC) |
914 | * We make this non-blocking if the inode is contended, return | 888 | return; |
915 | * EAGAIN to indicate to the caller that they did not succeed. | ||
916 | * This prevents the flush path from blocking on inodes inside | ||
917 | * another operation right now, they get caught later by | ||
918 | * xfs_sync. | ||
919 | */ | ||
920 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) | ||
921 | goto out; | ||
922 | 889 | ||
923 | if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) | 890 | trace_xfs_dirty_inode(ip); |
924 | goto out_unlock; | ||
925 | 891 | ||
926 | /* | 892 | tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); |
927 | * Now we have the flush lock and the inode is not pinned, we | 893 | error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); |
928 | * can check if the inode is really clean as we know that | 894 | if (error) { |
929 | * there are no pending transaction completions, it is not | 895 | xfs_trans_cancel(tp, 0); |
930 | * waiting on the delayed write queue and there is no IO in | 896 | goto trouble; |
931 | * progress. | ||
932 | */ | ||
933 | if (xfs_inode_clean(ip)) { | ||
934 | xfs_ifunlock(ip); | ||
935 | error = 0; | ||
936 | goto out_unlock; | ||
937 | } | ||
938 | error = xfs_iflush(ip, SYNC_TRYLOCK); | ||
939 | } | 897 | } |
940 | 898 | xfs_ilock(ip, XFS_ILOCK_EXCL); | |
941 | out_unlock: | ||
942 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
943 | out: | ||
944 | /* | 899 | /* |
945 | * if we failed to write out the inode then mark | 900 | * Grab all the latest timestamps from the Linux inode. |
946 | * it dirty again so we'll try again later. | ||
947 | */ | 901 | */ |
902 | ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; | ||
903 | ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; | ||
904 | ip->i_d.di_ctime.t_sec = (__int32_t)inode->i_ctime.tv_sec; | ||
905 | ip->i_d.di_ctime.t_nsec = (__int32_t)inode->i_ctime.tv_nsec; | ||
906 | ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec; | ||
907 | ip->i_d.di_mtime.t_nsec = (__int32_t)inode->i_mtime.tv_nsec; | ||
908 | |||
909 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
910 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
911 | error = xfs_trans_commit(tp, 0); | ||
948 | if (error) | 912 | if (error) |
949 | xfs_mark_inode_dirty_sync(ip); | 913 | goto trouble; |
950 | return -error; | 914 | return; |
915 | |||
916 | trouble: | ||
917 | xfs_warn(mp, "failed to update timestamps for inode 0x%llx", ip->i_ino); | ||
951 | } | 918 | } |
952 | 919 | ||
953 | STATIC void | 920 | STATIC void |
@@ -1466,7 +1433,6 @@ static const struct super_operations xfs_super_operations = { | |||
1466 | .alloc_inode = xfs_fs_alloc_inode, | 1433 | .alloc_inode = xfs_fs_alloc_inode, |
1467 | .destroy_inode = xfs_fs_destroy_inode, | 1434 | .destroy_inode = xfs_fs_destroy_inode, |
1468 | .dirty_inode = xfs_fs_dirty_inode, | 1435 | .dirty_inode = xfs_fs_dirty_inode, |
1469 | .write_inode = xfs_fs_write_inode, | ||
1470 | .evict_inode = xfs_fs_evict_inode, | 1436 | .evict_inode = xfs_fs_evict_inode, |
1471 | .put_super = xfs_fs_put_super, | 1437 | .put_super = xfs_fs_put_super, |
1472 | .sync_fs = xfs_fs_sync_fs, | 1438 | .sync_fs = xfs_fs_sync_fs, |