aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jbd2/transaction.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index f3d06174b051..a6eec9747c74 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,41 @@ 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 /*
1325 * This and the following assertions are unreliable since we may see jh
1326 * in inconsistent state unless we grab bh_state lock. But this is
1327 * crucial to catch bugs so let's do a reliable check until the
1328 * lockless handling is fully proven.
1329 */
1330 if (jh->b_transaction != transaction &&
1331 jh->b_next_transaction != transaction) {
1332 jbd_lock_bh_state(bh);
1333 J_ASSERT_JH(jh, jh->b_transaction == transaction ||
1334 jh->b_next_transaction == transaction);
1335 jbd_unlock_bh_state(bh);
1336 }
1337 if (jh->b_modified == 1) {
1338 /* If it's in our transaction it must be in BJ_Metadata list. */
1339 if (jh->b_transaction == transaction &&
1340 jh->b_jlist != BJ_Metadata) {
1341 jbd_lock_bh_state(bh);
1342 J_ASSERT_JH(jh, jh->b_transaction != transaction ||
1343 jh->b_jlist == BJ_Metadata);
1344 jbd_unlock_bh_state(bh);
1345 }
1346 goto out;
1347 }
1348
1349 journal = transaction->t_journal;
1323 jbd_debug(5, "journal_head %p\n", jh); 1350 jbd_debug(5, "journal_head %p\n", jh);
1324 JBUFFER_TRACE(jh, "entry"); 1351 JBUFFER_TRACE(jh, "entry");
1325 1352
@@ -1410,7 +1437,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
1410 spin_unlock(&journal->j_list_lock); 1437 spin_unlock(&journal->j_list_lock);
1411out_unlock_bh: 1438out_unlock_bh:
1412 jbd_unlock_bh_state(bh); 1439 jbd_unlock_bh_state(bh);
1413 jbd2_journal_put_journal_head(jh);
1414out: 1440out:
1415 JBUFFER_TRACE(jh, "exit"); 1441 JBUFFER_TRACE(jh, "exit");
1416 return ret; 1442 return ret;