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 | |
| 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>
| -rw-r--r-- | fs/jbd2/checkpoint.c | 2 | ||||
| -rw-r--r-- | fs/jbd2/commit.c | 2 | ||||
| -rw-r--r-- | fs/jbd2/journal.c | 163 | ||||
| -rw-r--r-- | include/linux/jbd2.h | 2 | ||||
| -rw-r--r-- | include/trace/events/jbd2.h | 12 |
5 files changed, 102 insertions, 79 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 | } |
| 120 | |||
