aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2013-06-04 12:12:57 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-06-04 12:12:57 -0400
commit76c39904561004ac8675f858a290129e439d5168 (patch)
tree46b2c2800ffbad5dd2ebd4ceb66893414630df2b
parent2f387f849b6a5be5b4b914c43a8af0406279db11 (diff)
jbd2: cleanup needed free block estimates when starting a transaction
__jbd2_log_space_left() and jbd_space_needed() were kind of odd. jbd_space_needed() accounted also credits needed for currently committing transaction while it didn't account for credits needed for control blocks. __jbd2_log_space_left() then accounted for control blocks as a fraction of free space. Since results of these two functions are always only compared against each other, this works correct but is somewhat strange. Move the estimates so that jbd_space_needed() returns number of blocks needed for a transaction including control blocks and __jbd2_log_space_left() returns free space in the journal (with the committing transaction already subtracted). Rename functions to jbd2_log_space_left() and jbd2_space_needed() while we are changing them. Reviewed-by: Zheng Liu <wenqing.lz@taobao.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--fs/jbd2/checkpoint.c8
-rw-r--r--fs/jbd2/journal.c29
-rw-r--r--fs/jbd2/transaction.c9
-rw-r--r--include/linux/jbd2.h32
4 files changed, 35 insertions, 43 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 65ec076e41f2..a572383bcf99 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -120,8 +120,8 @@ void __jbd2_log_wait_for_space(journal_t *journal)
120 int nblocks, space_left; 120 int nblocks, space_left;
121 /* assert_spin_locked(&journal->j_state_lock); */ 121 /* assert_spin_locked(&journal->j_state_lock); */
122 122
123 nblocks = jbd_space_needed(journal); 123 nblocks = jbd2_space_needed(journal);
124 while (__jbd2_log_space_left(journal) < nblocks) { 124 while (jbd2_log_space_left(journal) < nblocks) {
125 if (journal->j_flags & JBD2_ABORT) 125 if (journal->j_flags & JBD2_ABORT)
126 return; 126 return;
127 write_unlock(&journal->j_state_lock); 127 write_unlock(&journal->j_state_lock);
@@ -140,8 +140,8 @@ void __jbd2_log_wait_for_space(journal_t *journal)
140 */ 140 */
141 write_lock(&journal->j_state_lock); 141 write_lock(&journal->j_state_lock);
142 spin_lock(&journal->j_list_lock); 142 spin_lock(&journal->j_list_lock);
143 nblocks = jbd_space_needed(journal); 143 nblocks = jbd2_space_needed(journal);
144 space_left = __jbd2_log_space_left(journal); 144 space_left = jbd2_log_space_left(journal);
145 if (space_left < nblocks) { 145 if (space_left < nblocks) {
146 int chkpt = journal->j_checkpoint_transactions != NULL; 146 int chkpt = journal->j_checkpoint_transactions != NULL;
147 tid_t tid = 0; 147 tid_t tid = 0;
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 5ef0712e2f7a..8e5486d62e89 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -478,35 +478,6 @@ repeat:
478 */ 478 */
479 479
480/* 480/*
481 * __jbd2_log_space_left: Return the number of free blocks left in the journal.
482 *
483 * Called with the journal already locked.
484 *
485 * Called under j_state_lock
486 */
487
488int __jbd2_log_space_left(journal_t *journal)
489{
490 int left = journal->j_free;
491
492 /* assert_spin_locked(&journal->j_state_lock); */
493
494 /*
495 * Be pessimistic here about the number of those free blocks which
496 * might be required for log descriptor control blocks.
497 */
498
499#define MIN_LOG_RESERVED_BLOCKS 32 /* Allow for rounding errors */
500
501 left -= MIN_LOG_RESERVED_BLOCKS;
502
503 if (left <= 0)
504 return 0;
505 left -= (left >> 3);
506 return left;
507}
508
509/*
510 * Called with j_state_lock locked for writing. 481 * Called with j_state_lock locked for writing.
511 * Returns true if a transaction commit was started. 482 * Returns true if a transaction commit was started.
512 */ 483 */
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 60361c634b5d..f9cd43190b43 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -283,12 +283,12 @@ repeat:
283 * reduce the free space arbitrarily. Be careful to account for 283 * reduce the free space arbitrarily. Be careful to account for
284 * those buffers when checkpointing. 284 * those buffers when checkpointing.
285 */ 285 */
286 if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) { 286 if (jbd2_log_space_left(journal) < jbd2_space_needed(journal)) {
287 jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle); 287 jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
288 atomic_sub(nblocks, &transaction->t_outstanding_credits); 288 atomic_sub(nblocks, &transaction->t_outstanding_credits);
289 read_unlock(&journal->j_state_lock); 289 read_unlock(&journal->j_state_lock);
290 write_lock(&journal->j_state_lock); 290 write_lock(&journal->j_state_lock);
291 if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) 291 if (jbd2_log_space_left(journal) < jbd2_space_needed(journal))
292 __jbd2_log_wait_for_space(journal); 292 __jbd2_log_wait_for_space(journal);
293 write_unlock(&journal->j_state_lock); 293 write_unlock(&journal->j_state_lock);
294 goto repeat; 294 goto repeat;
@@ -306,7 +306,7 @@ repeat:
306 jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n", 306 jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n",
307 handle, nblocks, 307 handle, nblocks,
308 atomic_read(&transaction->t_outstanding_credits), 308 atomic_read(&transaction->t_outstanding_credits),
309 __jbd2_log_space_left(journal)); 309 jbd2_log_space_left(journal));
310 read_unlock(&journal->j_state_lock); 310 read_unlock(&journal->j_state_lock);
311 311
312 lock_map_acquire(&handle->h_lockdep_map); 312 lock_map_acquire(&handle->h_lockdep_map);
@@ -441,7 +441,8 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
441 goto unlock; 441 goto unlock;
442 } 442 }
443 443
444 if (wanted > __jbd2_log_space_left(journal)) { 444 if (wanted + (wanted >> JBD2_CONTROL_BLOCKS_SHIFT) >
445 jbd2_log_space_left(journal)) {
445 jbd_debug(3, "denied handle %p %d blocks: " 446 jbd_debug(3, "denied handle %p %d blocks: "
446 "insufficient log space\n", handle, nblocks); 447 "insufficient log space\n", handle, nblocks);
447 goto unlock; 448 goto unlock;
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index e33e84b3d5c8..7a1f6cd864c8 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -1220,7 +1220,6 @@ extern void jbd2_clear_buffer_revoked_flags(journal_t *journal);
1220 * transitions on demand. 1220 * transitions on demand.
1221 */ 1221 */
1222 1222
1223int __jbd2_log_space_left(journal_t *); /* Called with journal locked */
1224int jbd2_log_start_commit(journal_t *journal, tid_t tid); 1223int jbd2_log_start_commit(journal_t *journal, tid_t tid);
1225int __jbd2_log_start_commit(journal_t *journal, tid_t tid); 1224int __jbd2_log_start_commit(journal_t *journal, tid_t tid);
1226int jbd2_journal_start_commit(journal_t *journal, tid_t *tid); 1225int jbd2_journal_start_commit(journal_t *journal, tid_t *tid);
@@ -1291,16 +1290,37 @@ extern int jbd2_journal_blocks_per_page(struct inode *inode);
1291extern size_t journal_tag_bytes(journal_t *journal); 1290extern size_t journal_tag_bytes(journal_t *journal);
1292 1291
1293/* 1292/*
1293 * We reserve t_outstanding_credits >> JBD2_CONTROL_BLOCKS_SHIFT for
1294 * transaction control blocks.
1295 */
1296#define JBD2_CONTROL_BLOCKS_SHIFT 5
1297
1298/*
1294 * Return the minimum number of blocks which must be free in the journal 1299 * Return the minimum number of blocks which must be free in the journal
1295 * before a new transaction may be started. Must be called under j_state_lock. 1300 * before a new transaction may be started. Must be called under j_state_lock.
1296 */ 1301 */
1297static inline int jbd_space_needed(journal_t *journal) 1302static inline int jbd2_space_needed(journal_t *journal)
1298{ 1303{
1299 int nblocks = journal->j_max_transaction_buffers; 1304 int nblocks = journal->j_max_transaction_buffers;
1300 if (journal->j_committing_transaction) 1305 return nblocks + (nblocks >> JBD2_CONTROL_BLOCKS_SHIFT);
1301 nblocks += atomic_read(&journal->j_committing_transaction-> 1306}
1302 t_outstanding_credits); 1307
1303 return nblocks; 1308/*
1309 * Return number of free blocks in the log. Must be called under j_state_lock.
1310 */
1311static inline unsigned long jbd2_log_space_left(journal_t *journal)
1312{
1313 /* Allow for rounding errors */
1314 unsigned long free = journal->j_free - 32;
1315
1316 if (journal->j_committing_transaction) {
1317 unsigned long committing = atomic_read(&journal->
1318 j_committing_transaction->t_outstanding_credits);
1319
1320 /* Transaction + control blocks */
1321 free -= committing + (committing >> JBD2_CONTROL_BLOCKS_SHIFT);
1322 }
1323 return free;
1304} 1324}
1305 1325
1306/* 1326/*