aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd2
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2015-07-12 18:11:30 -0400
committerTheodore Ts'o <tytso@mit.edu>2015-07-12 18:11:30 -0400
commit6e06ae88edae77379bef7c0cb7d3c2dd88676867 (patch)
tree7a8fd3e3ccbb6d65bb420ddc48454cb5a72efb5c /fs/jbd2
parentbc0195aad0daa2ad5b0d76cce22b167bc3435590 (diff)
jbd2: speedup jbd2_journal_dirty_metadata()
It is often the case that we mark buffer as having dirty metadata when the buffer is already in that state (frequent for bitmaps, inode table blocks, superblock). Thus it is unnecessary to contend on grabbing journal head reference and bh_state lock. Avoid that by checking whether any modification to the buffer is needed before grabbing any locks or references. [ Note: this is a fixed version of commit 2143c1965a761, which was reverted in ebeaa8ddb3663b5 due to a false positive triggering of an assertion check. -- Ted ] Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/jbd2')
-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;