diff options
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, |