diff options
author | Jan Kara <jack@suse.cz> | 2012-03-13 15:41:04 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-03-13 15:41:04 -0400 |
commit | 24bcc89c7e7c64982e6192b4952a0a92379fc341 (patch) | |
tree | 0661b6c83fa9bb681f3aa32264323ce96c264958 /fs/jbd2 | |
parent | 31d4f3a2f3c73f279ff96a7135d7202ef6833f12 (diff) |
jbd2: 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>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/jbd2')
-rw-r--r-- | fs/jbd2/checkpoint.c | 2 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 2 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 163 |
3 files changed, 97 insertions, 70 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 253e91890e71..19dcd0b86bca 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -550,7 +550,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
550 | (journal->j_flags & JBD2_BARRIER)) | 550 | (journal->j_flags & JBD2_BARRIER)) |
551 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); | 551 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); |
552 | if (!(journal->j_flags & JBD2_ABORT)) | 552 | if (!(journal->j_flags & JBD2_ABORT)) |
553 | jbd2_journal_update_superblock(journal, 1); | 553 | jbd2_journal_update_sb_log_tail(journal); |
554 | return 0; | 554 | return 0; |
555 | } | 555 | } |
556 | 556 | ||
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 8adc5d460f56..19371a8a9015 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -340,7 +340,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
340 | /* Do we need to erase the effects of a prior jbd2_journal_flush? */ | 340 | /* Do we need to erase the effects of a prior jbd2_journal_flush? */ |
341 | if (journal->j_flags & JBD2_FLUSHED) { | 341 | if (journal->j_flags & JBD2_FLUSHED) { |
342 | jbd_debug(3, "super block updated\n"); | 342 | jbd_debug(3, "super block updated\n"); |
343 | jbd2_journal_update_superblock(journal, 1); | 343 | jbd2_journal_update_sb_log_tail(journal); |
344 | } else { | 344 | } else { |
345 | jbd_debug(3, "superblock not updated\n"); | 345 | jbd_debug(3, "superblock not updated\n"); |
346 | } | 346 | } |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index cfb36d99f7a4..6e75fbd75bad 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -1110,40 +1110,30 @@ static int journal_reset(journal_t *journal) | |||
1110 | 1110 | ||
1111 | journal->j_max_transaction_buffers = journal->j_maxlen / 4; | 1111 | journal->j_max_transaction_buffers = journal->j_maxlen / 4; |
1112 | 1112 | ||
1113 | /* Add the dynamic fields and write it to disk. */ | ||
1114 | jbd2_journal_update_superblock(journal, 1); | ||
1115 | return jbd2_journal_start_thread(journal); | ||
1116 | } | ||
1117 | |||
1118 | /** | ||
1119 | * void jbd2_journal_update_superblock() - Update journal sb on disk. | ||
1120 | * @journal: The journal to update. | ||
1121 | * @wait: Set to '0' if you don't want to wait for IO completion. | ||
1122 | * | ||
1123 | * Update a journal's dynamic superblock fields and write it to disk, | ||
1124 | * optionally waiting for the IO to complete. | ||
1125 | */ | ||
1126 | void jbd2_journal_update_superblock(journal_t *journal, int wait) | ||
1127 | { | ||
1128 | journal_superblock_t *sb = journal->j_superblock; | ||
1129 | struct buffer_head *bh = journal->j_sb_buffer; | ||
1130 | |||
1131 | /* | 1113 | /* |
1132 | * As a special case, if the on-disk copy is already marked as needing | 1114 | * As a special case, if the on-disk copy is already marked as needing |
1133 | * no recovery (s_start == 0) and there are no outstanding transactions | 1115 | * no recovery (s_start == 0), then we can safely defer the superblock |
1134 | * in the filesystem, then we can safely defer the superblock update | 1116 | * update until the next commit by setting JBD2_FLUSHED. This avoids |
1135 | * until the next commit by setting JBD2_FLUSHED. This avoids | ||
1136 | * attempting a write to a potential-readonly device. | 1117 | * attempting a write to a potential-readonly device. |
1137 | */ | 1118 | */ |
1138 | if (sb->s_start == 0 && journal->j_tail_sequence == | 1119 | if (sb->s_start == 0) { |
1139 | journal->j_transaction_sequence) { | ||
1140 | jbd_debug(1, "JBD2: Skipping superblock update on recovered sb " | 1120 | jbd_debug(1, "JBD2: Skipping superblock update on recovered sb " |
1141 | "(start %ld, seq %d, errno %d)\n", | 1121 | "(start %ld, seq %d, errno %d)\n", |
1142 | journal->j_tail, journal->j_tail_sequence, | 1122 | journal->j_tail, journal->j_tail_sequence, |
1143 | journal->j_errno); | 1123 | journal->j_errno); |
1144 | goto out; | 1124 | journal->j_flags |= JBD2_FLUSHED; |
1125 | } else { | ||
1126 | /* Add the dynamic fields and write it to disk. */ | ||
1127 | jbd2_journal_update_sb_log_tail(journal); | ||
1145 | } | 1128 | } |
1129 | return jbd2_journal_start_thread(journal); | ||
1130 | } | ||
1146 | 1131 | ||
1132 | static void jbd2_write_superblock(journal_t *journal) | ||
1133 | { | ||
1134 | struct buffer_head *bh = journal->j_sb_buffer; | ||
1135 | |||
1136 | trace_jbd2_write_superblock(journal); | ||
1147 | if (buffer_write_io_error(bh)) { | 1137 | if (buffer_write_io_error(bh)) { |
1148 | /* | 1138 | /* |
1149 | * Oh, dear. A previous attempt to write the journal | 1139 | * Oh, dear. A previous attempt to write the journal |
@@ -1160,49 +1150,98 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait) | |||
1160 | set_buffer_uptodate(bh); | 1150 | set_buffer_uptodate(bh); |
1161 | } | 1151 | } |
1162 | 1152 | ||
1153 | BUFFER_TRACE(bh, "marking dirty"); | ||
1154 | mark_buffer_dirty(bh); | ||
1155 | sync_dirty_buffer(bh); | ||
1156 | if (buffer_write_io_error(bh)) { | ||
1157 | printk(KERN_ERR "JBD2: I/O error detected " | ||
1158 | "when updating journal superblock for %s.\n", | ||
1159 | journal->j_devname); | ||
1160 | clear_buffer_write_io_error(bh); | ||
1161 | set_buffer_uptodate(bh); | ||
1162 | } | ||
1163 | } | ||
1164 | |||
1165 | /** | ||
1166 | * jbd2_journal_update_sb_log_tail() - Update log tail in journal sb on disk. | ||
1167 | * @journal: The journal to update. | ||
1168 | * | ||
1169 | * Update a journal's superblock information about log tail and write it to | ||
1170 | * disk, waiting for the IO to complete. | ||
1171 | */ | ||
1172 | void jbd2_journal_update_sb_log_tail(journal_t *journal) | ||
1173 | { | ||
1174 | journal_superblock_t *sb = journal->j_superblock; | ||
1175 | |||
1163 | read_lock(&journal->j_state_lock); | 1176 | read_lock(&journal->j_state_lock); |
1164 | jbd_debug(1, "JBD2: updating superblock (start %ld, seq %d, errno %d)\n", | 1177 | jbd_debug(1, "JBD2: updating superblock (start %ld, seq %d)\n", |
1165 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); | 1178 | journal->j_tail, journal->j_tail_sequence); |
1166 | 1179 | ||
1167 | sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); | 1180 | sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); |
1168 | sb->s_start = cpu_to_be32(journal->j_tail); | 1181 | sb->s_start = cpu_to_be32(journal->j_tail); |
1169 | sb->s_errno = cpu_to_be32(journal->j_errno); | ||
1170 | read_unlock(&journal->j_state_lock); | 1182 | read_unlock(&journal->j_state_lock); |
1171 | 1183 | ||
1172 | BUFFER_TRACE(bh, "marking dirty"); | 1184 | jbd2_write_superblock(journal); |
1173 | mark_buffer_dirty(bh); | ||
1174 | if (wait) { | ||
1175 | sync_dirty_buffer(bh); | ||
1176 | if (buffer_write_io_error(bh)) { | ||
1177 | printk(KERN_ERR "JBD2: I/O error detected " | ||
1178 | "when updating journal superblock for %s.\n", | ||
1179 | journal->j_devname); | ||
1180 | clear_buffer_write_io_error(bh); | ||
1181 | set_buffer_uptodate(bh); | ||
1182 | } | ||
1183 | } else | ||
1184 | write_dirty_buffer(bh, WRITE); | ||
1185 | 1185 | ||
1186 | trace_jbd2_update_superblock_end(journal, wait); | 1186 | /* Log is no longer empty */ |
1187 | write_lock(&journal->j_state_lock); | ||
1188 | WARN_ON(!sb->s_sequence); | ||
1189 | journal->j_flags &= ~JBD2_FLUSHED; | ||
1190 | write_unlock(&journal->j_state_lock); | ||
1191 | } | ||
1187 | 1192 | ||
1188 | out: | 1193 | /** |
1189 | /* If we have just flushed the log (by marking s_start==0), then | 1194 | * jbd2_mark_journal_empty() - Mark on disk journal as empty. |
1190 | * any future commit will have to be careful to update the | 1195 | * @journal: The journal to update. |
1191 | * superblock again to re-record the true start of the log. */ | 1196 | * |
1197 | * Update a journal's dynamic superblock fields to show that journal is empty. | ||
1198 | * Write updated superblock to disk waiting for IO to complete. | ||
1199 | */ | ||
1200 | static void jbd2_mark_journal_empty(journal_t *journal) | ||
1201 | { | ||
1202 | journal_superblock_t *sb = journal->j_superblock; | ||
1203 | |||
1204 | read_lock(&journal->j_state_lock); | ||
1205 | jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n", | ||
1206 | journal->j_tail_sequence); | ||
1207 | |||
1208 | sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); | ||
1209 | sb->s_start = cpu_to_be32(0); | ||
1210 | read_unlock(&journal->j_state_lock); | ||
1211 | |||
1212 | jbd2_write_superblock(journal); | ||
1192 | 1213 | ||
1214 | /* Log is no longer empty */ | ||
1193 | write_lock(&journal->j_state_lock); | 1215 | write_lock(&journal->j_state_lock); |
1194 | if (sb->s_start) | 1216 | journal->j_flags |= JBD2_FLUSHED; |
1195 | journal->j_flags &= ~JBD2_FLUSHED; | ||
1196 | else | ||
1197 | journal->j_flags |= JBD2_FLUSHED; | ||
1198 | write_unlock(&journal->j_state_lock); | 1217 | write_unlock(&journal->j_state_lock); |
1199 | } | 1218 | } |
1200 | 1219 | ||
1220 | |||
1221 | /** | ||
1222 | * jbd2_journal_update_sb_errno() - Update error in the journal. | ||
1223 | * @journal: The journal to update. | ||
1224 | * | ||
1225 | * Update a journal's errno. Write updated superblock to disk waiting for IO | ||
1226 | * to complete. | ||
1227 | */ | ||
1228 | static void jbd2_journal_update_sb_errno(journal_t *journal) | ||
1229 | { | ||
1230 | journal_superblock_t *sb = journal->j_superblock; | ||
1231 | |||
1232 | read_lock(&journal->j_state_lock); | ||
1233 | jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", | ||
1234 | journal->j_errno); | ||
1235 | sb->s_errno = cpu_to_be32(journal->j_errno); | ||
1236 | read_unlock(&journal->j_state_lock); | ||
1237 | |||
1238 | jbd2_write_superblock(journal); | ||
1239 | } | ||
1240 | |||
1201 | /* | 1241 | /* |
1202 | * Read the superblock for a given journal, performing initial | 1242 | * Read the superblock for a given journal, performing initial |
1203 | * validation of the format. | 1243 | * validation of the format. |
1204 | */ | 1244 | */ |
1205 | |||
1206 | static int journal_get_superblock(journal_t *journal) | 1245 | static int journal_get_superblock(journal_t *journal) |
1207 | { | 1246 | { |
1208 | struct buffer_head *bh; | 1247 | struct buffer_head *bh; |
@@ -1395,15 +1434,10 @@ int jbd2_journal_destroy(journal_t *journal) | |||
1395 | spin_unlock(&journal->j_list_lock); | 1434 | spin_unlock(&journal->j_list_lock); |
1396 | 1435 | ||
1397 | if (journal->j_sb_buffer) { | 1436 | if (journal->j_sb_buffer) { |
1398 | if (!is_journal_aborted(journal)) { | 1437 | if (!is_journal_aborted(journal)) |
1399 | /* We can now mark the journal as empty. */ | 1438 | jbd2_mark_journal_empty(journal); |
1400 | journal->j_tail = 0; | 1439 | else |
1401 | journal->j_tail_sequence = | ||
1402 | ++journal->j_transaction_sequence; | ||
1403 | jbd2_journal_update_superblock(journal, 1); | ||
1404 | } else { | ||
1405 | err = -EIO; | 1440 | err = -EIO; |
1406 | } | ||
1407 | brelse(journal->j_sb_buffer); | 1441 | brelse(journal->j_sb_buffer); |
1408 | } | 1442 | } |
1409 | 1443 | ||
@@ -1562,7 +1596,6 @@ int jbd2_journal_flush(journal_t *journal) | |||
1562 | { | 1596 | { |
1563 | int err = 0; | 1597 | int err = 0; |
1564 | transaction_t *transaction = NULL; | 1598 | transaction_t *transaction = NULL; |
1565 | unsigned long old_tail; | ||
1566 | 1599 | ||
1567 | write_lock(&journal->j_state_lock); | 1600 | write_lock(&journal->j_state_lock); |
1568 | 1601 | ||
@@ -1604,14 +1637,8 @@ int jbd2_journal_flush(journal_t *journal) | |||
1604 | * the magic code for a fully-recovered superblock. Any future | 1637 | * the magic code for a fully-recovered superblock. Any future |
1605 | * commits of data to the journal will restore the current | 1638 | * commits of data to the journal will restore the current |
1606 | * s_start value. */ | 1639 | * s_start value. */ |
1640 | jbd2_mark_journal_empty(journal); | ||
1607 | write_lock(&journal->j_state_lock); | 1641 | write_lock(&journal->j_state_lock); |
1608 | old_tail = journal->j_tail; | ||
1609 | journal->j_tail = 0; | ||
1610 | write_unlock(&journal->j_state_lock); | ||
1611 | jbd2_journal_update_superblock(journal, 1); | ||
1612 | write_lock(&journal->j_state_lock); | ||
1613 | journal->j_tail = old_tail; | ||
1614 | |||
1615 | J_ASSERT(!journal->j_running_transaction); | 1642 | J_ASSERT(!journal->j_running_transaction); |
1616 | J_ASSERT(!journal->j_committing_transaction); | 1643 | J_ASSERT(!journal->j_committing_transaction); |
1617 | J_ASSERT(!journal->j_checkpoint_transactions); | 1644 | J_ASSERT(!journal->j_checkpoint_transactions); |
@@ -1652,7 +1679,7 @@ int jbd2_journal_wipe(journal_t *journal, int write) | |||
1652 | 1679 | ||
1653 | err = jbd2_journal_skip_recovery(journal); | 1680 | err = jbd2_journal_skip_recovery(journal); |
1654 | if (write) | 1681 | if (write) |
1655 | jbd2_journal_update_superblock(journal, 1); | 1682 | jbd2_mark_journal_empty(journal); |
1656 | 1683 | ||
1657 | no_recovery: | 1684 | no_recovery: |
1658 | return err; | 1685 | return err; |
@@ -1702,7 +1729,7 @@ static void __journal_abort_soft (journal_t *journal, int errno) | |||
1702 | __jbd2_journal_abort_hard(journal); | 1729 | __jbd2_journal_abort_hard(journal); |
1703 | 1730 | ||
1704 | if (errno) | 1731 | if (errno) |
1705 | jbd2_journal_update_superblock(journal, 1); | 1732 | jbd2_journal_update_sb_errno(journal); |
1706 | } | 1733 | } |
1707 | 1734 | ||
1708 | /** | 1735 | /** |