aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jbd2/checkpoint.c2
-rw-r--r--fs/jbd2/commit.c2
-rw-r--r--fs/jbd2/journal.c163
-rw-r--r--include/linux/jbd2.h2
-rw-r--r--include/trace/events/jbd2.h12
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 */
1126void 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
1132static 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 */
1172void 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
1188out: 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 */
1200static 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 */
1228static 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
1206static int journal_get_superblock(journal_t *journal) 1245static 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/**
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 46eef77e6ab8..5f05c77438e5 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -1087,7 +1087,7 @@ extern int jbd2_journal_destroy (journal_t *);
1087extern int jbd2_journal_recover (journal_t *journal); 1087extern int jbd2_journal_recover (journal_t *journal);
1088extern int jbd2_journal_wipe (journal_t *, int); 1088extern int jbd2_journal_wipe (journal_t *, int);
1089extern int jbd2_journal_skip_recovery (journal_t *); 1089extern int jbd2_journal_skip_recovery (journal_t *);
1090extern void jbd2_journal_update_superblock (journal_t *, int); 1090extern void jbd2_journal_update_sb_log_tail (journal_t *);
1091extern void __jbd2_journal_abort_hard (journal_t *); 1091extern void __jbd2_journal_abort_hard (journal_t *);
1092extern void jbd2_journal_abort (journal_t *, int); 1092extern void jbd2_journal_abort (journal_t *, int);
1093extern int jbd2_journal_errno (journal_t *); 1093extern int jbd2_journal_errno (journal_t *);
diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
index ae59bc207d70..e05a362bf3f1 100644
--- a/include/trace/events/jbd2.h
+++ b/include/trace/events/jbd2.h
@@ -236,25 +236,21 @@ TRACE_EVENT(jbd2_cleanup_journal_tail,
236 __entry->block_nr, __entry->freed) 236 __entry->block_nr, __entry->freed)
237); 237);
238 238
239TRACE_EVENT(jbd2_update_superblock_end, 239TRACE_EVENT(jbd2_write_superblock,
240 240
241 TP_PROTO(journal_t *journal, int wait), 241 TP_PROTO(journal_t *journal),
242 242
243 TP_ARGS(journal, wait), 243 TP_ARGS(journal),
244 244
245 TP_STRUCT__entry( 245 TP_STRUCT__entry(
246 __field( dev_t, dev ) 246 __field( dev_t, dev )
247 __field( int, wait )
248 ), 247 ),
249 248
250 TP_fast_assign( 249 TP_fast_assign(
251 __entry->dev = journal->j_fs_dev->bd_dev; 250 __entry->dev = journal->j_fs_dev->bd_dev;
252 __entry->wait = wait;
253 ), 251 ),
254 252
255 TP_printk("dev %d,%d wait %d", 253 TP_printk("dev %d,%d", MAJOR(__entry->dev), MINOR(__entry->dev))
256 MAJOR(__entry->dev), MINOR(__entry->dev),
257 __entry->wait)
258); 254);
259 255
260#endif /* _TRACE_JBD2_H */ 256#endif /* _TRACE_JBD2_H */