diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_super.c')
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 59 |
1 files changed, 41 insertions, 18 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index bdd41c8c342f..18a4b8e11df2 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
| @@ -977,6 +977,28 @@ xfs_fs_inode_init_once( | |||
| 977 | } | 977 | } |
| 978 | 978 | ||
| 979 | /* | 979 | /* |
| 980 | * Dirty the XFS inode when mark_inode_dirty_sync() is called so that | ||
| 981 | * we catch unlogged VFS level updates to the inode. Care must be taken | ||
| 982 | * here - the transaction code calls mark_inode_dirty_sync() to mark the | ||
| 983 | * VFS inode dirty in a transaction and clears the i_update_core field; | ||
| 984 | * it must clear the field after calling mark_inode_dirty_sync() to | ||
| 985 | * correctly indicate that the dirty state has been propagated into the | ||
| 986 | * inode log item. | ||
| 987 | * | ||
| 988 | * We need the barrier() to maintain correct ordering between unlogged | ||
| 989 | * updates and the transaction commit code that clears the i_update_core | ||
| 990 | * field. This requires all updates to be completed before marking the | ||
| 991 | * inode dirty. | ||
| 992 | */ | ||
| 993 | STATIC void | ||
| 994 | xfs_fs_dirty_inode( | ||
| 995 | struct inode *inode) | ||
| 996 | { | ||
| 997 | barrier(); | ||
| 998 | XFS_I(inode)->i_update_core = 1; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | /* | ||
| 980 | * Attempt to flush the inode, this will actually fail | 1002 | * Attempt to flush the inode, this will actually fail |
| 981 | * if the inode is pinned, but we dirty the inode again | 1003 | * if the inode is pinned, but we dirty the inode again |
| 982 | * at the point when it is unpinned after a log write, | 1004 | * at the point when it is unpinned after a log write, |
| @@ -1126,7 +1148,7 @@ xfs_fs_put_super( | |||
| 1126 | } | 1148 | } |
| 1127 | 1149 | ||
| 1128 | STATIC int | 1150 | STATIC int |
| 1129 | xfs_fs_sync_super( | 1151 | xfs_fs_sync_fs( |
| 1130 | struct super_block *sb, | 1152 | struct super_block *sb, |
| 1131 | int wait) | 1153 | int wait) |
| 1132 | { | 1154 | { |
| @@ -1134,23 +1156,23 @@ xfs_fs_sync_super( | |||
| 1134 | int error; | 1156 | int error; |
| 1135 | 1157 | ||
| 1136 | /* | 1158 | /* |
| 1137 | * Treat a sync operation like a freeze. This is to work | 1159 | * Not much we can do for the first async pass. Writing out the |
| 1138 | * around a race in sync_inodes() which works in two phases | 1160 | * superblock would be counter-productive as we are going to redirty |
| 1139 | * - an asynchronous flush, which can write out an inode | 1161 | * when writing out other data and metadata (and writing out a single |
| 1140 | * without waiting for file size updates to complete, and a | 1162 | * block is quite fast anyway). |
| 1141 | * synchronous flush, which wont do anything because the | 1163 | * |
| 1142 | * async flush removed the inode's dirty flag. Also | 1164 | * Try to asynchronously kick off quota syncing at least. |
| 1143 | * sync_inodes() will not see any files that just have | ||
| 1144 | * outstanding transactions to be flushed because we don't | ||
| 1145 | * dirty the Linux inode until after the transaction I/O | ||
| 1146 | * completes. | ||
| 1147 | */ | 1165 | */ |
| 1148 | if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) | 1166 | if (!wait) { |
| 1149 | error = xfs_quiesce_data(mp); | 1167 | xfs_qm_sync(mp, SYNC_TRYLOCK); |
| 1150 | else | 1168 | return 0; |
| 1151 | error = xfs_sync_fsdata(mp, 0); | 1169 | } |
| 1170 | |||
| 1171 | error = xfs_quiesce_data(mp); | ||
| 1172 | if (error) | ||
| 1173 | return -error; | ||
| 1152 | 1174 | ||
| 1153 | if (unlikely(laptop_mode)) { | 1175 | if (laptop_mode) { |
| 1154 | int prev_sync_seq = mp->m_sync_seq; | 1176 | int prev_sync_seq = mp->m_sync_seq; |
| 1155 | 1177 | ||
| 1156 | /* | 1178 | /* |
| @@ -1169,7 +1191,7 @@ xfs_fs_sync_super( | |||
| 1169 | mp->m_sync_seq != prev_sync_seq); | 1191 | mp->m_sync_seq != prev_sync_seq); |
| 1170 | } | 1192 | } |
| 1171 | 1193 | ||
| 1172 | return -error; | 1194 | return 0; |
| 1173 | } | 1195 | } |
| 1174 | 1196 | ||
| 1175 | STATIC int | 1197 | STATIC int |
| @@ -1539,10 +1561,11 @@ xfs_fs_get_sb( | |||
| 1539 | static const struct super_operations xfs_super_operations = { | 1561 | static const struct super_operations xfs_super_operations = { |
| 1540 | .alloc_inode = xfs_fs_alloc_inode, | 1562 | .alloc_inode = xfs_fs_alloc_inode, |
| 1541 | .destroy_inode = xfs_fs_destroy_inode, | 1563 | .destroy_inode = xfs_fs_destroy_inode, |
| 1564 | .dirty_inode = xfs_fs_dirty_inode, | ||
| 1542 | .write_inode = xfs_fs_write_inode, | 1565 | .write_inode = xfs_fs_write_inode, |
| 1543 | .clear_inode = xfs_fs_clear_inode, | 1566 | .clear_inode = xfs_fs_clear_inode, |
| 1544 | .put_super = xfs_fs_put_super, | 1567 | .put_super = xfs_fs_put_super, |
| 1545 | .sync_fs = xfs_fs_sync_super, | 1568 | .sync_fs = xfs_fs_sync_fs, |
| 1546 | .freeze_fs = xfs_fs_freeze, | 1569 | .freeze_fs = xfs_fs_freeze, |
| 1547 | .statfs = xfs_fs_statfs, | 1570 | .statfs = xfs_fs_statfs, |
| 1548 | .remount_fs = xfs_fs_remount, | 1571 | .remount_fs = xfs_fs_remount, |
