diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index da37beb76f6e..c2d04ff8876b 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -1109,27 +1109,10 @@ xlog_verify_head( | |||
1109 | bool tmp_wrapped; | 1109 | bool tmp_wrapped; |
1110 | 1110 | ||
1111 | /* | 1111 | /* |
1112 | * Search backwards through the log looking for the log record header | 1112 | * Check the head of the log for torn writes. Search backwards from the |
1113 | * block. This wraps all the way back around to the head so something is | 1113 | * head until we hit the tail or the maximum number of log record I/Os |
1114 | * seriously wrong if we can't find it. | 1114 | * that could have been in flight at one time. Use a temporary buffer so |
1115 | */ | 1115 | * we don't trash the rhead/bp pointers from the caller. |
1116 | found = xlog_rseek_logrec_hdr(log, *head_blk, *head_blk, 1, bp, rhead_blk, | ||
1117 | rhead, wrapped); | ||
1118 | if (found < 0) | ||
1119 | return found; | ||
1120 | if (!found) { | ||
1121 | xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__); | ||
1122 | return -EIO; | ||
1123 | } | ||
1124 | |||
1125 | *tail_blk = BLOCK_LSN(be64_to_cpu((*rhead)->h_tail_lsn)); | ||
1126 | |||
1127 | /* | ||
1128 | * Now that we have a tail block, check the head of the log for torn | ||
1129 | * writes. Search again until we hit the tail or the maximum number of | ||
1130 | * log record I/Os that could have been in flight at one time. Use a | ||
1131 | * temporary buffer so we don't trash the rhead/bp pointer from the | ||
1132 | * call above. | ||
1133 | */ | 1116 | */ |
1134 | tmp_bp = xlog_get_bp(log, 1); | 1117 | tmp_bp = xlog_get_bp(log, 1); |
1135 | if (!tmp_bp) | 1118 | if (!tmp_bp) |
@@ -1254,6 +1237,7 @@ xlog_find_tail( | |||
1254 | */ | 1237 | */ |
1255 | if ((error = xlog_find_head(log, head_blk))) | 1238 | if ((error = xlog_find_head(log, head_blk))) |
1256 | return error; | 1239 | return error; |
1240 | ASSERT(*head_blk < INT_MAX); | ||
1257 | 1241 | ||
1258 | bp = xlog_get_bp(log, 1); | 1242 | bp = xlog_get_bp(log, 1); |
1259 | if (!bp) | 1243 | if (!bp) |
@@ -1271,12 +1255,26 @@ xlog_find_tail( | |||
1271 | } | 1255 | } |
1272 | 1256 | ||
1273 | /* | 1257 | /* |
1258 | * Search backwards through the log looking for the log record header | ||
1259 | * block. This wraps all the way back around to the head so something is | ||
1260 | * seriously wrong if we can't find it. | ||
1261 | */ | ||
1262 | error = xlog_rseek_logrec_hdr(log, *head_blk, *head_blk, 1, bp, | ||
1263 | &rhead_blk, &rhead, &wrapped); | ||
1264 | if (error < 0) | ||
1265 | return error; | ||
1266 | if (!error) { | ||
1267 | xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__); | ||
1268 | return -EIO; | ||
1269 | } | ||
1270 | *tail_blk = BLOCK_LSN(be64_to_cpu(rhead->h_tail_lsn)); | ||
1271 | |||
1272 | /* | ||
1274 | * Trim the head block back to skip over torn records. We can have | 1273 | * Trim the head block back to skip over torn records. We can have |
1275 | * multiple log I/Os in flight at any time, so we assume CRC failures | 1274 | * multiple log I/Os in flight at any time, so we assume CRC failures |
1276 | * back through the previous several records are torn writes and skip | 1275 | * back through the previous several records are torn writes and skip |
1277 | * them. | 1276 | * them. |
1278 | */ | 1277 | */ |
1279 | ASSERT(*head_blk < INT_MAX); | ||
1280 | error = xlog_verify_head(log, head_blk, tail_blk, bp, &rhead_blk, | 1278 | error = xlog_verify_head(log, head_blk, tail_blk, bp, &rhead_blk, |
1281 | &rhead, &wrapped); | 1279 | &rhead, &wrapped); |
1282 | if (error) | 1280 | if (error) |