|
@@ -1049,6 +1049,10 @@ void jbd2_buffer_abort_trigger(struct journal_head *jh,
|
|
|
* mark dirty metadata which needs to be journaled as part of the current
|
|
|
* transaction.
|
|
|
*
|
|
|
+ * The buffer must have previously had jbd2_journal_get_write_access()
|
|
|
+ * called so that it has a valid journal_head attached to the buffer
|
|
|
+ * head.
|
|
|
+ *
|
|
|
* The buffer is placed on the transaction's metadata list and is marked
|
|
|
* as belonging to the transaction.
|
|
|
*
|
|
@@ -1065,11 +1069,16 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
|
|
|
transaction_t *transaction = handle->h_transaction;
|
|
|
journal_t *journal = transaction->t_journal;
|
|
|
struct journal_head *jh = bh2jh(bh);
|
|
|
+ int ret = 0;
|
|
|
|
|
|
jbd_debug(5, "journal_head %p\n", jh);
|
|
|
JBUFFER_TRACE(jh, "entry");
|
|
|
if (is_handle_aborted(handle))
|
|
|
goto out;
|
|
|
+ if (!buffer_jbd(bh)) {
|
|
|
+ ret = -EUCLEAN;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
jbd_lock_bh_state(bh);
|
|
|
|
|
@@ -1093,8 +1102,20 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
|
|
|
*/
|
|
|
if (jh->b_transaction == transaction && jh->b_jlist == BJ_Metadata) {
|
|
|
JBUFFER_TRACE(jh, "fastpath");
|
|
|
- J_ASSERT_JH(jh, jh->b_transaction ==
|
|
|
- journal->j_running_transaction);
|
|
|
+ if (unlikely(jh->b_transaction !=
|
|
|
+ journal->j_running_transaction)) {
|
|
|
+ printk(KERN_EMERG "JBD: %s: "
|
|
|
+ "jh->b_transaction (%llu, %p, %u) != "
|
|
|
+ "journal->j_running_transaction (%p, %u)",
|
|
|
+ journal->j_devname,
|
|
|
+ (unsigned long long) bh->b_blocknr,
|
|
|
+ jh->b_transaction,
|
|
|
+ jh->b_transaction ? jh->b_transaction->t_tid : 0,
|
|
|
+ journal->j_running_transaction,
|
|
|
+ journal->j_running_transaction ?
|
|
|
+ journal->j_running_transaction->t_tid : 0);
|
|
|
+ ret = -EINVAL;
|
|
|
+ }
|
|
|
goto out_unlock_bh;
|
|
|
}
|
|
|
|
|
@@ -1108,9 +1129,32 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
|
|
|
*/
|
|
|
if (jh->b_transaction != transaction) {
|
|
|
JBUFFER_TRACE(jh, "already on other transaction");
|
|
|
- J_ASSERT_JH(jh, jh->b_transaction ==
|
|
|
- journal->j_committing_transaction);
|
|
|
- J_ASSERT_JH(jh, jh->b_next_transaction == transaction);
|
|
|
+ if (unlikely(jh->b_transaction !=
|
|
|
+ journal->j_committing_transaction)) {
|
|
|
+ printk(KERN_EMERG "JBD: %s: "
|
|
|
+ "jh->b_transaction (%llu, %p, %u) != "
|
|
|
+ "journal->j_committing_transaction (%p, %u)",
|
|
|
+ journal->j_devname,
|
|
|
+ (unsigned long long) bh->b_blocknr,
|
|
|
+ jh->b_transaction,
|
|
|
+ jh->b_transaction ? jh->b_transaction->t_tid : 0,
|
|
|
+ journal->j_committing_transaction,
|
|
|
+ journal->j_committing_transaction ?
|
|
|
+ journal->j_committing_transaction->t_tid : 0);
|
|
|
+ ret = -EINVAL;
|
|
|
+ }
|
|
|
+ if (unlikely(jh->b_next_transaction != transaction)) {
|
|
|
+ printk(KERN_EMERG "JBD: %s: "
|
|
|
+ "jh->b_next_transaction (%llu, %p, %u) != "
|
|
|
+ "transaction (%p, %u)",
|
|
|
+ journal->j_devname,
|
|
|
+ (unsigned long long) bh->b_blocknr,
|
|
|
+ jh->b_next_transaction,
|
|
|
+ jh->b_next_transaction ?
|
|
|
+ jh->b_next_transaction->t_tid : 0,
|
|
|
+ transaction, transaction->t_tid);
|
|
|
+ ret = -EINVAL;
|
|
|
+ }
|
|
|
/* And this case is illegal: we can't reuse another
|
|
|
* transaction's data buffer, ever. */
|
|
|
goto out_unlock_bh;
|
|
@@ -1127,7 +1171,9 @@ out_unlock_bh:
|
|
|
jbd_unlock_bh_state(bh);
|
|
|
out:
|
|
|
JBUFFER_TRACE(jh, "exit");
|
|
|
- return 0;
|
|
|
+ if (ret)
|
|
|
+ __WARN(); /* All errors are bugs, so dump the stack */
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/*
|