diff options
| author | Jan Kara <jack@suse.cz> | 2012-04-07 06:33:03 -0400 |
|---|---|---|
| committer | Jan Kara <jack@suse.cz> | 2012-05-15 17:34:36 -0400 |
| commit | 9754e39c7bc51328f145e933bfb0df47cd67b6e9 (patch) | |
| tree | d2fa043f74939d049d6934aea6ab7b1c272be8a5 /fs | |
| parent | f72cf5e223a28d3b3ea7dc9e40464fd534e359e8 (diff) | |
jbd: Split updating of journal superblock and marking journal empty
There are three case of updating journal superblock. In the first case, we want
to mark journal as empty (setting s_sequence to 0), in the second case we want
to update log tail, in the third case we want to update s_errno. Split these
cases into separate functions. It makes the code slightly more straightforward
and later patches will make the distinction even more important.
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/jbd/checkpoint.c | 2 | ||||
| -rw-r--r-- | fs/jbd/commit.c | 2 | ||||
| -rw-r--r-- | fs/jbd/journal.c | 164 |
3 files changed, 99 insertions, 69 deletions
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 05f0754f2b46..80c85f3e087f 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c | |||
| @@ -540,7 +540,7 @@ int cleanup_journal_tail(journal_t *journal) | |||
| 540 | journal->j_tail = blocknr; | 540 | journal->j_tail = blocknr; |
| 541 | spin_unlock(&journal->j_state_lock); | 541 | spin_unlock(&journal->j_state_lock); |
| 542 | if (!(journal->j_flags & JFS_ABORT)) | 542 | if (!(journal->j_flags & JFS_ABORT)) |
| 543 | journal_update_superblock(journal, 1); | 543 | journal_update_sb_log_tail(journal); |
| 544 | return 0; | 544 | return 0; |
| 545 | } | 545 | } |
| 546 | 546 | ||
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 9d31e6a39205..dba9cfd75f1a 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
| @@ -308,7 +308,7 @@ void journal_commit_transaction(journal_t *journal) | |||
| 308 | /* Do we need to erase the effects of a prior journal_flush? */ | 308 | /* Do we need to erase the effects of a prior journal_flush? */ |
| 309 | if (journal->j_flags & JFS_FLUSHED) { | 309 | if (journal->j_flags & JFS_FLUSHED) { |
| 310 | jbd_debug(3, "super block updated\n"); | 310 | jbd_debug(3, "super block updated\n"); |
| 311 | journal_update_superblock(journal, 1); | 311 | journal_update_sb_log_tail(journal); |
| 312 | } else { | 312 | } else { |
| 313 | jbd_debug(3, "superblock not updated\n"); | 313 | jbd_debug(3, "superblock not updated\n"); |
| 314 | } | 314 | } |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 2047fd77bf38..44c104abfb36 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
| @@ -923,8 +923,22 @@ static int journal_reset(journal_t *journal) | |||
| 923 | 923 | ||
| 924 | journal->j_max_transaction_buffers = journal->j_maxlen / 4; | 924 | journal->j_max_transaction_buffers = journal->j_maxlen / 4; |
| 925 | 925 | ||
| 926 | /* Add the dynamic fields and write it to disk. */ | 926 | /* |
| 927 | journal_update_superblock(journal, 1); | 927 | * As a special case, if the on-disk copy is already marked as needing |
| 928 | * no recovery (s_start == 0), then we can safely defer the superblock | ||
| 929 | * update until the next commit by setting JFS_FLUSHED. This avoids | ||
| 930 | * attempting a write to a potential-readonly device. | ||
| 931 | */ | ||
| 932 | if (sb->s_start == 0) { | ||
| 933 | jbd_debug(1,"JBD: Skipping superblock update on recovered sb " | ||
| 934 | "(start %u, seq %d, errno %d)\n", | ||
| 935 | journal->j_tail, journal->j_tail_sequence, | ||
| 936 | journal->j_errno); | ||
| 937 | journal->j_flags |= JFS_FLUSHED; | ||
| 938 | } else { | ||
| 939 | /* Add the dynamic fields and write it to disk. */ | ||
| 940 | journal_update_sb_log_tail(journal); | ||
| 941 | } | ||
| 928 | return journal_start_thread(journal); | 942 | return journal_start_thread(journal); |
| 929 | } | 943 | } |
| 930 | 944 | ||
| @@ -1001,35 +1015,11 @@ int journal_create(journal_t *journal) | |||
| 1001 | return journal_reset(journal); | 1015 | return journal_reset(journal); |
| 1002 | } | 1016 | } |
| 1003 | 1017 | ||
| 1004 | /** | 1018 | static void journal_write_superblock(journal_t *journal) |
| 1005 | * void journal_update_superblock() - Update journal sb on disk. | ||
| 1006 | * @journal: The journal to update. | ||
| 1007 | * @wait: Set to '0' if you don't want to wait for IO completion. | ||
| 1008 | * | ||
| 1009 | * Update a journal's dynamic superblock fields and write it to disk, | ||
| 1010 | * optionally waiting for the IO to complete. | ||
| 1011 | */ | ||
| 1012 | void journal_update_superblock(journal_t *journal, int wait) | ||
| 1013 | { | 1019 | { |
| 1014 | journal_superblock_t *sb = journal->j_superblock; | ||
| 1015 | struct buffer_head *bh = journal->j_sb_buffer; | 1020 | struct buffer_head *bh = journal->j_sb_buffer; |
| 1016 | 1021 | ||
| 1017 | /* | 1022 | trace_journal_write_superblock(journal); |
| 1018 | * As a special case, if the on-disk copy is already marked as needing | ||
| 1019 | * no recovery (s_start == 0) and there are no outstanding transactions | ||
| 1020 | * in the filesystem, then we can safely defer the superblock update | ||
| 1021 | * until the next commit by setting JFS_FLUSHED. This avoids | ||
| 1022 | * attempting a write to a potential-readonly device. | ||
| 1023 | */ | ||
| 1024 | if (sb->s_start == 0 && journal->j_tail_sequence == | ||
| 1025 | journal->j_transaction_sequence) { | ||
| 1026 | jbd_debug(1,"JBD: Skipping superblock update on recovered sb " | ||
| 1027 | "(start %u, seq %d, errno %d)\n", | ||
| 1028 | journal->j_tail, journal->j_tail_sequence, | ||
| 1029 | journal->j_errno); | ||
| 1030 | goto out; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | if (buffer_write_io_error(bh)) { | 1023 | if (buffer_write_io_error(bh)) { |
| 1034 | char b[BDEVNAME_SIZE]; | 1024 | char b[BDEVNAME_SIZE]; |
| 1035 | /* | 1025 | /* |
| @@ -1047,44 +1037,94 @@ void journal_update_superblock(journal_t *journal, int wait) | |||
| 1047 | set_buffer_uptodate(bh); | 1037 | set_buffer_uptodate(bh); |
| 1048 | } | 1038 | } |
| 1049 | 1039 | ||
| 1040 | BUFFER_TRACE(bh, "marking dirty"); | ||
| 1041 | mark_buffer_dirty(bh); | ||
| 1042 | sync_dirty_buffer(bh); | ||
| 1043 | if (buffer_write_io_error(bh)) { | ||
| 1044 | char b[BDEVNAME_SIZE]; | ||
| 1045 | printk(KERN_ERR "JBD: I/O error detected " | ||
| 1046 | "when updating journal superblock for %s.\n", | ||
| 1047 | journal_dev_name(journal, b)); | ||
| 1048 | clear_buffer_write_io_error(bh); | ||
| 1049 | set_buffer_uptodate(bh); | ||
| 1050 | } | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | /** | ||
| 1054 | * journal_update_sb_log_tail() - Update log tail in journal sb on disk. | ||
| 1055 | * @journal: The journal to update. | ||
| 1056 | * | ||
| 1057 | * Update a journal's superblock information about log tail and write it to | ||
| 1058 | * disk, waiting for the IO to complete. | ||
| 1059 | */ | ||
| 1060 | void journal_update_sb_log_tail(journal_t *journal) | ||
| 1061 | { | ||
| 1062 | journal_superblock_t *sb = journal->j_superblock; | ||
| 1063 | |||
| 1050 | spin_lock(&journal->j_state_lock); | 1064 | spin_lock(&journal->j_state_lock); |
| 1051 | jbd_debug(1,"JBD: updating superblock (start %u, seq %d, errno %d)\n", | 1065 | jbd_debug(1,"JBD: updating superblock (start %u, seq %d, errno %d)\n", |
| 1052 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); | 1066 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); |
| 1053 | 1067 | ||
| 1054 | sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); | 1068 | sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); |
| 1055 | sb->s_start = cpu_to_be32(journal->j_tail); | 1069 | sb->s_start = cpu_to_be32(journal->j_tail); |
| 1056 | sb->s_errno = cpu_to_be32(journal->j_errno); | ||
| 1057 | spin_unlock(&journal->j_state_lock); | 1070 | spin_unlock(&journal->j_state_lock); |
| 1058 | 1071 | ||
| 1059 | BUFFER_TRACE(bh, "marking dirty"); | 1072 | journal_write_superblock(journal); |
| 1060 | mark_buffer_dirty(bh); | ||
| 1061 | if (wait) { | ||
| 1062 | sync_dirty_buffer(bh); | ||
| 1063 | if (buffer_write_io_error(bh)) { | ||
| 1064 | char b[BDEVNAME_SIZE]; | ||
| 1065 | printk(KERN_ERR "JBD: I/O error detected " | ||
| 1066 | "when updating journal superblock for %s.\n", | ||
| 1067 | journal_dev_name(journal, b)); | ||
| 1068 | clear_buffer_write_io_error(bh); | ||
| 1069 | set_buffer_uptodate(bh); | ||
| 1070 | } | ||
| 1071 | } else | ||
| 1072 | write_dirty_buffer(bh, WRITE); | ||
| 1073 | 1073 | ||
| 1074 | trace_jbd_update_superblock_end(journal, wait); | 1074 | /* Log is no longer empty */ |
| 1075 | out: | 1075 | spin_lock(&journal->j_state_lock); |
| 1076 | /* If we have just flushed the log (by marking s_start==0), then | 1076 | WARN_ON(!sb->s_sequence); |
| 1077 | * any future commit will have to be careful to update the | 1077 | journal->j_flags &= ~JFS_FLUSHED; |
| 1078 | * superblock again to re-record the true start of the log. */ | 1078 | spin_unlock(&journal->j_state_lock); |
| 1079 | } | ||
| 1080 | |||
| 1081 | /** | ||
| 1082 | * mark_journal_empty() - Mark on disk journal as empty. | ||
| 1083 | * @journal: The journal to update. | ||
| 1084 | * | ||
| 1085 | * Update a journal's dynamic superblock fields to show that journal is empty. | ||
| 1086 | * Write updated superblock to disk waiting for IO to complete. | ||
| 1087 | */ | ||
| 1088 | static void mark_journal_empty(journal_t *journal) | ||
| 1089 | { | ||
| 1090 | journal_superblock_t *sb = journal->j_superblock; | ||
| 1079 | 1091 | ||
| 1080 | spin_lock(&journal->j_state_lock); | 1092 | spin_lock(&journal->j_state_lock); |
| 1081 | if (sb->s_start) | 1093 | jbd_debug(1, "JBD: Marking journal as empty (seq %d)\n", |
| 1082 | journal->j_flags &= ~JFS_FLUSHED; | 1094 | journal->j_tail_sequence); |
| 1083 | else | 1095 | |
| 1084 | journal->j_flags |= JFS_FLUSHED; | 1096 | sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); |
| 1097 | sb->s_start = cpu_to_be32(0); | ||
| 1098 | spin_unlock(&journal->j_state_lock); | ||
| 1099 | |||
| 1100 | journal_write_superblock(journal); | ||
| 1101 | |||
| 1102 | spin_lock(&journal->j_state_lock); | ||
| 1103 | /* Log is empty */ | ||
| 1104 | journal->j_flags |= JFS_FLUSHED; | ||
| 1085 | spin_unlock(&journal->j_state_lock); | 1105 | spin_unlock(&journal->j_state_lock); |
| 1086 | } | 1106 | } |
| 1087 | 1107 | ||
| 1108 | /** | ||
| 1109 | * journal_update_sb_errno() - Update error in the journal. | ||
| 1110 | * @journal: The journal to update. | ||
| 1111 | * | ||
| 1112 | * Update a journal's errno. Write updated superblock to disk waiting for IO | ||
| 1113 | * to complete. | ||
| 1114 | */ | ||
| 1115 | static void journal_update_sb_errno(journal_t *journal) | ||
| 1116 | { | ||
| 1117 | journal_superblock_t *sb = journal->j_superblock; | ||
| 1118 | |||
| 1119 | spin_lock(&journal->j_state_lock); | ||
| 1120 | jbd_debug(1, "JBD: updating superblock error (errno %d)\n", | ||
| 1121 | journal->j_errno); | ||
| 1122 | sb->s_errno = cpu_to_be32(journal->j_errno); | ||
| 1123 | spin_unlock(&journal->j_state_lock); | ||
| 1124 | |||
| 1125 | journal_write_superblock(journal); | ||
| 1126 | } | ||
| 1127 | |||
| 1088 | /* | 1128 | /* |
| 1089 | * Read the superblock for a given journal, performing initial | 1129 | * Read the superblock for a given journal, performing initial |
| 1090 | * validation of the format. | 1130 | * validation of the format. |
| @@ -1268,14 +1308,11 @@ int journal_destroy(journal_t *journal) | |||
| 1268 | 1308 | ||
| 1269 | if (journal->j_sb_buffer) { | 1309 | if (journal->j_sb_buffer) { |
| 1270 | if (!is_journal_aborted(journal)) { | 1310 | if (!is_journal_aborted(journal)) { |
| 1271 | /* We can now mark the journal as empty. */ | ||
| 1272 | journal->j_tail = 0; | ||
| 1273 | journal->j_tail_sequence = | 1311 | journal->j_tail_sequence = |
| 1274 | ++journal->j_transaction_sequence; | 1312 | ++journal->j_transaction_sequence; |
| 1275 | journal_update_superblock(journal, 1); | 1313 | mark_journal_empty(journal); |
| 1276 | } else { | 1314 | } else |
| 1277 | err = -EIO; | 1315 | err = -EIO; |
| 1278 | } | ||
| 1279 | brelse(journal->j_sb_buffer); | 1316 | brelse(journal->j_sb_buffer); |
| 1280 | } | 1317 | } |
| 1281 | 1318 | ||
| @@ -1457,7 +1494,6 @@ int journal_flush(journal_t *journal) | |||
| 1457 | { | 1494 | { |
| 1458 | int err = 0; | 1495 | int err = 0; |
| 1459 | transaction_t *transaction = NULL; | 1496 | transaction_t *transaction = NULL; |
| 1460 | unsigned int old_tail; | ||
| 1461 | 1497 | ||
| 1462 | spin_lock(&journal->j_state_lock); | 1498 | spin_lock(&journal->j_state_lock); |
| 1463 | 1499 | ||
| @@ -1499,14 +1535,8 @@ int journal_flush(journal_t *journal) | |||
| 1499 | * the magic code for a fully-recovered superblock. Any future | 1535 | * the magic code for a fully-recovered superblock. Any future |
| 1500 | * commits of data to the journal will restore the current | 1536 | * commits of data to the journal will restore the current |
| 1501 | * s_start value. */ | 1537 | * s_start value. */ |
| 1538 | mark_journal_empty(journal); | ||
| 1502 | spin_lock(&journal->j_state_lock); | 1539 | spin_lock(&journal->j_state_lock); |
| 1503 | old_tail = journal->j_tail; | ||
| 1504 | journal->j_tail = 0; | ||
| 1505 | spin_unlock(&journal->j_state_lock); | ||
| 1506 | journal_update_superblock(journal, 1); | ||
| 1507 | spin_lock(&journal->j_state_lock); | ||
| 1508 | journal->j_tail = old_tail; | ||
| 1509 | |||
| 1510 | J_ASSERT(!journal->j_running_transaction); | 1540 | J_ASSERT(!journal->j_running_transaction); |
| 1511 | J_ASSERT(!journal->j_committing_transaction); | 1541 | J_ASSERT(!journal->j_committing_transaction); |
| 1512 | J_ASSERT(!journal->j_checkpoint_transactions); | 1542 | J_ASSERT(!journal->j_checkpoint_transactions); |
| @@ -1547,7 +1577,7 @@ int journal_wipe(journal_t *journal, int write) | |||
| 1547 | 1577 | ||
| 1548 | err = journal_skip_recovery(journal); | 1578 | err = journal_skip_recovery(journal); |
| 1549 | if (write) | 1579 | if (write) |
| 1550 | journal_update_superblock(journal, 1); | 1580 | mark_journal_empty(journal); |
| 1551 | 1581 | ||
| 1552 | no_recovery: | 1582 | no_recovery: |
| 1553 | return err; | 1583 | return err; |
| @@ -1615,7 +1645,7 @@ static void __journal_abort_soft (journal_t *journal, int errno) | |||
| 1615 | __journal_abort_hard(journal); | 1645 | __journal_abort_hard(journal); |
| 1616 | 1646 | ||
| 1617 | if (errno) | 1647 | if (errno) |
| 1618 | journal_update_superblock(journal, 1); | 1648 | journal_update_sb_errno(journal); |
| 1619 | } | 1649 | } |
| 1620 | 1650 | ||
| 1621 | /** | 1651 | /** |
