aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd2
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2015-06-20 21:44:17 -0400
committerTheodore Ts'o <tytso@mit.edu>2015-06-20 21:44:17 -0400
commit2143c1965a761332ae417b22fd477b636e4f54ec (patch)
treea4cf50f078a0c94d76e363bedc7be91bde7125f6 /fs/jbd2
parent7b506b1035326543b7cd2d768449ccbd1ef3f368 (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. 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.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;