aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbutalib Aghayev <agayev@gmail.com>2017-02-12 23:55:45 -0500
committerTheodore Ts'o <tytso@mit.edu>2017-02-12 23:55:45 -0500
commitc3a5aefebea108e050865d5bdf9fd11b9c7f6c5e (patch)
treecbe2f6946dae7362697c271beb7ddc565854a879
parent3fe66b893f97e6c70d85da38fb374878d031c77e (diff)
downloadext4-lazy_journal.tar.gz
Do not trim journal. Always recover the tail.lazy_journal
With this commit, after the first write to the journal, journal always starts at block 1 and transaction 2. During mount, we recover and replay all the entries in the journal and we find out the actual tail. Newer transactions are written at this new tail. This is done in preparation for stopping metadata block writeback. The change to commit.c prevents the journal superblock from being updated. The change to super.c prevents wiping of the journal upon mount after a clean unmount. The change to jbd2_mark_journal_empty always sets the journal start from the beginning and the rest of the changes to journal.c and recovery.c is for finding the actual tail after mount (since now we are doing "recovery" on every mount) and updating in-memory journal superblock, so that new updates are written at the actual tail of the journal. Note: this patch is still a work in progress. In particular, the jbd2_metamap_insert() function is no longer present. We need to insert things via the new jbd2_transaction_infos_add. -TYT
-rw-r--r--fs/ext4/super.c4
-rw-r--r--fs/jbd2/commit.c4
-rw-r--r--fs/jbd2/journal.c11
-rw-r--r--fs/jbd2/recovery.c25
4 files changed, 31 insertions, 13 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index b2bd2a31a931df..e8e2bbd1e89824 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4557,8 +4557,8 @@ static int ext4_load_journal(struct super_block *sb,
if (!(journal->j_flags & JBD2_BARRIER))
ext4_msg(sb, KERN_INFO, "barriers disabled");
- if (!ext4_has_feature_journal_needs_recovery(sb))
- err = jbd2_journal_wipe(journal, !really_read_only);
+ /* if (!ext4_has_feature_journal_needs_recovery(sb)) */
+ /* err = jbd2_journal_wipe(journal, !really_read_only); */
if (!err) {
char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL);
if (save)
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 50e1a0b375c52a..bf61fe5f1048e9 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -902,8 +902,8 @@ start_journal_io:
* erase checkpointed transactions from the log by updating journal
* superblock.
*/
- if (update_tail)
- jbd2_update_log_tail(journal, first_tid, first_block);
+ /* if (update_tail) */
+ /* jbd2_update_log_tail(journal, first_tid, first_block); */
/* End of a transaction! Finally, we can do checkpoint
processing: any buffers committed as a result of this
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 2d2743297810f0..e4e3f94e7a9396 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1296,9 +1296,6 @@ static int journal_reset(journal_t *journal)
journal->j_first = first;
journal->j_last = last;
-
- journal->j_head = first;
- journal->j_tail = first;
journal->j_free = last - first;
journal->j_tail_sequence = journal->j_transaction_sequence;
@@ -1314,12 +1311,15 @@ static int journal_reset(journal_t *journal)
* attempting a write to a potential-readonly device.
*/
if (sb->s_start == 0) {
+ journal->j_head = first;
+ journal->j_tail = first;
jbd_debug(1, "JBD2: Skipping superblock update on recovered sb "
"(start %ld, seq %d, errno %d)\n",
journal->j_tail, journal->j_tail_sequence,
journal->j_errno);
journal->j_flags |= JBD2_FLUSHED;
} else {
+ #if 0
/* Lock here to make assertions happy... */
mutex_lock(&journal->j_checkpoint_mutex);
/*
@@ -1333,6 +1333,7 @@ static int journal_reset(journal_t *journal)
journal->j_tail,
REQ_FUA);
mutex_unlock(&journal->j_checkpoint_mutex);
+ #endif
}
return jbd2_journal_start_thread(journal);
}
@@ -1441,8 +1442,8 @@ static void jbd2_mark_journal_empty(journal_t *journal, int write_op)
jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n",
journal->j_tail_sequence);
- sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
- sb->s_start = cpu_to_be32(0);
+ sb->s_sequence = cpu_to_be32(2);
+ sb->s_start = cpu_to_be32(1);
read_unlock(&journal->j_state_lock);
jbd2_write_superblock(journal, write_op);
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
index da100044566ca0..30dc632ccf0ab5 100644
--- a/fs/jbd2/recovery.c
+++ b/fs/jbd2/recovery.c
@@ -32,6 +32,7 @@ struct recovery_info
{
tid_t start_transaction;
tid_t end_transaction;
+ int tail_block;
int nr_replays;
int nr_revokes;
@@ -282,6 +283,8 @@ int jbd2_journal_recover(journal_t *journal)
/* Restart the log at the next transaction ID, thus invalidating
* any existing commit records in the log. */
journal->j_transaction_sequence = info.end_transaction;
+ journal->j_tail = info.tail_block;
+ journal->j_head = info.tail_block;
jbd2_journal_clear_revoke(journal);
err2 = sync_blockdev(journal->j_fs_dev);
@@ -484,9 +487,6 @@ static int do_one_pass(journal_t *journal,
if (err)
goto failed;
- next_log_block++;
- wrap(journal, next_log_block);
-
/* What kind of buffer is it?
*
* If it is a descriptor block, check that it has the
@@ -514,6 +514,9 @@ static int do_one_pass(journal_t *journal,
* all of the sequence number checks. What are we going
* to do with it? That depends on the pass... */
+ next_log_block++;
+ wrap(journal, next_log_block);
+
switch(blocktype) {
case JBD2_DESCRIPTOR_BLOCK:
/* Verify checksum first */
@@ -578,7 +581,7 @@ static int do_one_pass(journal_t *journal,
"block %ld in log\n",
err, io_block);
} else {
- unsigned long long blocknr;
+ unsigned long long blocknr, log_block;
J_ASSERT(obh != NULL);
blocknr = read_tag_block(journal,
@@ -609,6 +612,19 @@ static int do_one_pass(journal_t *journal,
goto skip_write;
}
+ err = jbd2_journal_bmap(journal,
+ io_block,
+ &log_block);
+ J_ASSERT(!err);
+
+#if 0
+ if (!jbd2_metamap_insert(
+ journal,
+ blocknr,
+ log_block))
+ goto failed;
+#endif
+
/* Find a buffer for the new
* data being restored */
nbh = __getblk(journal->j_fs_dev,
@@ -791,6 +807,7 @@ static int do_one_pass(journal_t *journal,
if (pass == PASS_SCAN) {
if (!info->end_transaction)
info->end_transaction = next_commit_ID;
+ info->tail_block = next_log_block;
} else {
/* It's really bad news if different passes end up at
* different places (but possible due to IO errors). */