aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jbd2/transaction.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index f3d06174b051..cbe8b3aece5b 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -1280,8 +1280,6 @@ void jbd2_buffer_abort_trigger(struct journal_head *jh,
1280 triggers->t_abort(triggers, jh2bh(jh)); 1280 triggers->t_abort(triggers, jh2bh(jh));
1281} 1281}
1282 1282
1283
1284
1285/** 1283/**
1286 * int jbd2_journal_dirty_metadata() - mark a buffer as containing dirty metadata 1284 * int jbd2_journal_dirty_metadata() - mark a buffer as containing dirty metadata
1287 * @handle: transaction to add buffer to. 1285 * @handle: transaction to add buffer to.
@@ -1314,12 +1312,36 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
1314 1312
1315 if (is_handle_aborted(handle)) 1313 if (is_handle_aborted(handle))
1316 return -EROFS; 1314 return -EROFS;
1317 journal = transaction->t_journal; 1315 if (!buffer_jbd(bh)) {
1318 jh = jbd2_journal_grab_journal_head(bh);
1319 if (!jh) {
1320 ret = -EUCLEAN; 1316 ret = -EUCLEAN;
1321 goto out; 1317 goto out;
1322 } 1318 }
1319 /*
1320 * We don't grab jh reference here since the buffer must be part
1321 * of the running transaction.
1322 */
1323 jh = bh2jh(bh);
1324 J_ASSERT_JH(jh, jh->b_transaction == transaction ||
1325 jh->b_next_transaction == transaction);
1326 if (jh->b_modified == 1) {
1327 /*
1328 * If it's in our transaction it must be in BJ_Metadata list.
1329 * The assertion is unreliable since we may see jh in
1330 * inconsistent state unless we grab bh_state lock. But this
1331 * is crutial to catch bugs so let's do a reliable check until
1332 * the lockless handling is fully proven.
1333 */
1334 if (jh->b_transaction == transaction &&
1335 jh->b_jlist != BJ_Metadata) {
1336 jbd_lock_bh_state(bh);
1337 J_ASSERT_JH(jh, jh->b_transaction != transaction ||
1338 jh->b_jlist == BJ_Metadata);
1339 jbd_unlock_bh_state(bh);
1340 }
1341 goto out;
1342 }
1343
1344 journal = transaction->t_journal;
1323 jbd_debug(5, "journal_head %p\n", jh); 1345 jbd_debug(5, "journal_head %p\n", jh);
1324 JBUFFER_TRACE(jh, "entry"); 1346 JBUFFER_TRACE(jh, "entry");
1325 1347
@@ -1410,7 +1432,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
1410 spin_unlock(&journal->j_list_lock); 1432 spin_unlock(&journal->j_list_lock);
1411out_unlock_bh: 1433out_unlock_bh:
1412 jbd_unlock_bh_state(bh); 1434 jbd_unlock_bh_state(bh);
1413 jbd2_journal_put_journal_head(jh);
1414out: 1435out:
1415 JBUFFER_TRACE(jh, "exit"); 1436 JBUFFER_TRACE(jh, "exit");
1416 return ret; 1437 return ret;