diff options
Diffstat (limited to 'fs/xfs/xfs_log.c')
-rw-r--r-- | fs/xfs/xfs_log.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 7f4f9370d0e7..4dad756962d0 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -2387,14 +2387,27 @@ xlog_state_do_callback( | |||
2387 | 2387 | ||
2388 | 2388 | ||
2389 | /* | 2389 | /* |
2390 | * update the last_sync_lsn before we drop the | 2390 | * Completion of a iclog IO does not imply that |
2391 | * a transaction has completed, as transactions | ||
2392 | * can be large enough to span many iclogs. We | ||
2393 | * cannot change the tail of the log half way | ||
2394 | * through a transaction as this may be the only | ||
2395 | * transaction in the log and moving th etail to | ||
2396 | * point to the middle of it will prevent | ||
2397 | * recovery from finding the start of the | ||
2398 | * transaction. Hence we should only update the | ||
2399 | * last_sync_lsn if this iclog contains | ||
2400 | * transaction completion callbacks on it. | ||
2401 | * | ||
2402 | * We have to do this before we drop the | ||
2391 | * icloglock to ensure we are the only one that | 2403 | * icloglock to ensure we are the only one that |
2392 | * can update it. | 2404 | * can update it. |
2393 | */ | 2405 | */ |
2394 | ASSERT(XFS_LSN_CMP(atomic64_read(&log->l_last_sync_lsn), | 2406 | ASSERT(XFS_LSN_CMP(atomic64_read(&log->l_last_sync_lsn), |
2395 | be64_to_cpu(iclog->ic_header.h_lsn)) <= 0); | 2407 | be64_to_cpu(iclog->ic_header.h_lsn)) <= 0); |
2396 | atomic64_set(&log->l_last_sync_lsn, | 2408 | if (iclog->ic_callback) |
2397 | be64_to_cpu(iclog->ic_header.h_lsn)); | 2409 | atomic64_set(&log->l_last_sync_lsn, |
2410 | be64_to_cpu(iclog->ic_header.h_lsn)); | ||
2398 | 2411 | ||
2399 | } else | 2412 | } else |
2400 | ioerrors++; | 2413 | ioerrors++; |