aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2012-04-07 06:33:03 -0400
committerJan Kara <jack@suse.cz>2012-05-15 17:34:36 -0400
commit9754e39c7bc51328f145e933bfb0df47cd67b6e9 (patch)
treed2fa043f74939d049d6934aea6ab7b1c272be8a5 /fs/jbd
parentf72cf5e223a28d3b3ea7dc9e40464fd534e359e8 (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/jbd')
-rw-r--r--fs/jbd/checkpoint.c2
-rw-r--r--fs/jbd/commit.c2
-rw-r--r--fs/jbd/journal.c164
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/** 1018static 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 */
1012void 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 */
1060void 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 */
1075out: 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 */
1088static 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 */
1115static 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/**