|
@@ -876,9 +876,10 @@ int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid,
|
|
*
|
|
*
|
|
* Requires j_checkpoint_mutex
|
|
* Requires j_checkpoint_mutex
|
|
*/
|
|
*/
|
|
-void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
|
|
|
|
|
|
+int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
|
|
{
|
|
{
|
|
unsigned long freed;
|
|
unsigned long freed;
|
|
|
|
+ int ret;
|
|
|
|
|
|
BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
|
|
BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
|
|
|
|
|
|
@@ -888,7 +889,10 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
|
|
* space and if we lose sb update during power failure we'd replay
|
|
* space and if we lose sb update during power failure we'd replay
|
|
* old transaction with possibly newly overwritten data.
|
|
* old transaction with possibly newly overwritten data.
|
|
*/
|
|
*/
|
|
- jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA);
|
|
|
|
|
|
+ ret = jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
write_lock(&journal->j_state_lock);
|
|
write_lock(&journal->j_state_lock);
|
|
freed = block - journal->j_tail;
|
|
freed = block - journal->j_tail;
|
|
if (block < journal->j_tail)
|
|
if (block < journal->j_tail)
|
|
@@ -904,6 +908,9 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
|
|
journal->j_tail_sequence = tid;
|
|
journal->j_tail_sequence = tid;
|
|
journal->j_tail = block;
|
|
journal->j_tail = block;
|
|
write_unlock(&journal->j_state_lock);
|
|
write_unlock(&journal->j_state_lock);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1322,7 +1329,7 @@ static int journal_reset(journal_t *journal)
|
|
return jbd2_journal_start_thread(journal);
|
|
return jbd2_journal_start_thread(journal);
|
|
}
|
|
}
|
|
|
|
|
|
-static void jbd2_write_superblock(journal_t *journal, int write_op)
|
|
|
|
|
|
+static int jbd2_write_superblock(journal_t *journal, int write_op)
|
|
{
|
|
{
|
|
struct buffer_head *bh = journal->j_sb_buffer;
|
|
struct buffer_head *bh = journal->j_sb_buffer;
|
|
journal_superblock_t *sb = journal->j_superblock;
|
|
journal_superblock_t *sb = journal->j_superblock;
|
|
@@ -1361,7 +1368,10 @@ static void jbd2_write_superblock(journal_t *journal, int write_op)
|
|
printk(KERN_ERR "JBD2: Error %d detected when updating "
|
|
printk(KERN_ERR "JBD2: Error %d detected when updating "
|
|
"journal superblock for %s.\n", ret,
|
|
"journal superblock for %s.\n", ret,
|
|
journal->j_devname);
|
|
journal->j_devname);
|
|
|
|
+ jbd2_journal_abort(journal, ret);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1374,10 +1384,11 @@ static void jbd2_write_superblock(journal_t *journal, int write_op)
|
|
* Update a journal's superblock information about log tail and write it to
|
|
* Update a journal's superblock information about log tail and write it to
|
|
* disk, waiting for the IO to complete.
|
|
* disk, waiting for the IO to complete.
|
|
*/
|
|
*/
|
|
-void jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
|
|
|
|
|
|
+int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
|
|
unsigned long tail_block, int write_op)
|
|
unsigned long tail_block, int write_op)
|
|
{
|
|
{
|
|
journal_superblock_t *sb = journal->j_superblock;
|
|
journal_superblock_t *sb = journal->j_superblock;
|
|
|
|
+ int ret;
|
|
|
|
|
|
BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
|
|
BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
|
|
jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n",
|
|
jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n",
|
|
@@ -1386,13 +1397,18 @@ void jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
|
|
sb->s_sequence = cpu_to_be32(tail_tid);
|
|
sb->s_sequence = cpu_to_be32(tail_tid);
|
|
sb->s_start = cpu_to_be32(tail_block);
|
|
sb->s_start = cpu_to_be32(tail_block);
|
|
|
|
|
|
- jbd2_write_superblock(journal, write_op);
|
|
|
|
|
|
+ ret = jbd2_write_superblock(journal, write_op);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto out;
|
|
|
|
|
|
/* Log is no longer empty */
|
|
/* Log is no longer empty */
|
|
write_lock(&journal->j_state_lock);
|
|
write_lock(&journal->j_state_lock);
|
|
WARN_ON(!sb->s_sequence);
|
|
WARN_ON(!sb->s_sequence);
|
|
journal->j_flags &= ~JBD2_FLUSHED;
|
|
journal->j_flags &= ~JBD2_FLUSHED;
|
|
write_unlock(&journal->j_state_lock);
|
|
write_unlock(&journal->j_state_lock);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1941,7 +1957,14 @@ int jbd2_journal_flush(journal_t *journal)
|
|
return -EIO;
|
|
return -EIO;
|
|
|
|
|
|
mutex_lock(&journal->j_checkpoint_mutex);
|
|
mutex_lock(&journal->j_checkpoint_mutex);
|
|
- jbd2_cleanup_journal_tail(journal);
|
|
|
|
|
|
+ if (!err) {
|
|
|
|
+ err = jbd2_cleanup_journal_tail(journal);
|
|
|
|
+ if (err < 0) {
|
|
|
|
+ mutex_unlock(&journal->j_checkpoint_mutex);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ err = 0;
|
|
|
|
+ }
|
|
|
|
|
|
/* Finally, mark the journal as really needing no recovery.
|
|
/* Finally, mark the journal as really needing no recovery.
|
|
* This sets s_start==0 in the underlying superblock, which is
|
|
* This sets s_start==0 in the underlying superblock, which is
|
|
@@ -1957,7 +1980,8 @@ int jbd2_journal_flush(journal_t *journal)
|
|
J_ASSERT(journal->j_head == journal->j_tail);
|
|
J_ASSERT(journal->j_head == journal->j_tail);
|
|
J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence);
|
|
J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence);
|
|
write_unlock(&journal->j_state_lock);
|
|
write_unlock(&journal->j_state_lock);
|
|
- return 0;
|
|
|
|
|
|
+out:
|
|
|
|
+ return err;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|