diff options
author | David Chinner <dgc@sgi.com> | 2007-05-14 04:24:09 -0400 |
---|---|---|
committer | Tim Shimmin <tes@chook.melbourne.sgi.com> | 2007-07-14 01:22:18 -0400 |
commit | 40095b64f5da601a8ab61fbe4b40feb46830052e (patch) | |
tree | 114402c9280f5677bf1d47f4a933847912e3c314 | |
parent | 4cc929ee305c69573cb842aade059dbe2a93940c (diff) |
[XFS] Sleeping with the ilock waiting for I/O completion is Bad.
Recent fixes to the filesystem freezing code introduced a vn_iowait call
in the middle of the sync code. Unfortunately, at the point where this
call was added we are holding the ilock. The ilock is needed by I/O
completion for unwritten extent conversion and now updating the file size.
Hence I/o cannot complete if we hold the ilock while waiting for I/O
completion.
Fix up the bug and clean the code up around it.
SGI-PV: 963674
SGI-Modid: xfs-linux-melb:xfs-kern:28566a
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Tim Shimmin <tes@sgi.com>
-rw-r--r-- | fs/xfs/xfs_vfsops.c | 73 |
1 files changed, 28 insertions, 45 deletions
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 65c561201cb8..92c1425d06ce 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c | |||
@@ -1128,58 +1128,41 @@ xfs_sync_inodes( | |||
1128 | * in the inode list. | 1128 | * in the inode list. |
1129 | */ | 1129 | */ |
1130 | 1130 | ||
1131 | if ((flags & SYNC_CLOSE) && (vp != NULL)) { | 1131 | /* |
1132 | /* | 1132 | * If we have to flush data or wait for I/O completion |
1133 | * This is the shutdown case. We just need to | 1133 | * we need to drop the ilock that we currently hold. |
1134 | * flush and invalidate all the pages associated | 1134 | * If we need to drop the lock, insert a marker if we |
1135 | * with the inode. Drop the inode lock since | 1135 | * have not already done so. |
1136 | * we can't hold it across calls to the buffer | 1136 | */ |
1137 | * cache. | 1137 | if ((flags & (SYNC_CLOSE|SYNC_IOWAIT)) || |
1138 | * | 1138 | ((flags & SYNC_DELWRI) && VN_DIRTY(vp))) { |
1139 | * We don't set the VREMAPPING bit in the vnode | 1139 | if (mount_locked) { |
1140 | * here, because we don't hold the vnode lock | 1140 | IPOINTER_INSERT(ip, mp); |
1141 | * exclusively. It doesn't really matter, though, | ||
1142 | * because we only come here when we're shutting | ||
1143 | * down anyway. | ||
1144 | */ | ||
1145 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
1146 | |||
1147 | if (XFS_FORCED_SHUTDOWN(mp)) { | ||
1148 | bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF); | ||
1149 | } else { | ||
1150 | error = bhv_vop_flushinval_pages(vp, 0, -1, FI_REMAPF); | ||
1151 | } | 1141 | } |
1142 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
1152 | 1143 | ||
1153 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 1144 | if (flags & SYNC_CLOSE) { |
1154 | 1145 | /* Shutdown case. Flush and invalidate. */ | |
1155 | } else if ((flags & SYNC_DELWRI) && (vp != NULL)) { | 1146 | if (XFS_FORCED_SHUTDOWN(mp)) |
1156 | if (VN_DIRTY(vp)) { | 1147 | bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF); |
1157 | /* We need to have dropped the lock here, | 1148 | else |
1158 | * so insert a marker if we have not already | 1149 | error = bhv_vop_flushinval_pages(vp, 0, |
1159 | * done so. | 1150 | -1, FI_REMAPF); |
1160 | */ | 1151 | } else if ((flags & SYNC_DELWRI) && VN_DIRTY(vp)) { |
1161 | if (mount_locked) { | ||
1162 | IPOINTER_INSERT(ip, mp); | ||
1163 | } | ||
1164 | |||
1165 | /* | ||
1166 | * Drop the inode lock since we can't hold it | ||
1167 | * across calls to the buffer cache. | ||
1168 | */ | ||
1169 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
1170 | error = bhv_vop_flush_pages(vp, (xfs_off_t)0, | 1152 | error = bhv_vop_flush_pages(vp, (xfs_off_t)0, |
1171 | -1, fflag, FI_NONE); | 1153 | -1, fflag, FI_NONE); |
1172 | xfs_ilock(ip, XFS_ILOCK_SHARED); | ||
1173 | } | 1154 | } |
1174 | 1155 | ||
1156 | /* | ||
1157 | * When freezing, we need to wait ensure all I/O (including direct | ||
1158 | * I/O) is complete to ensure no further data modification can take | ||
1159 | * place after this point | ||
1160 | */ | ||
1161 | if (flags & SYNC_IOWAIT) | ||
1162 | vn_iowait(vp); | ||
1163 | |||
1164 | xfs_ilock(ip, XFS_ILOCK_SHARED); | ||
1175 | } | 1165 | } |
1176 | /* | ||
1177 | * When freezing, we need to wait ensure all I/O (including direct | ||
1178 | * I/O) is complete to ensure no further data modification can take | ||
1179 | * place after this point | ||
1180 | */ | ||
1181 | if (flags & SYNC_IOWAIT) | ||
1182 | vn_iowait(vp); | ||
1183 | 1166 | ||
1184 | if (flags & SYNC_BDFLUSH) { | 1167 | if (flags & SYNC_BDFLUSH) { |
1185 | if ((flags & SYNC_ATTR) && | 1168 | if ((flags & SYNC_ATTR) && |