aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd2
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2014-09-01 21:19:01 -0400
committerTheodore Ts'o <tytso@mit.edu>2014-09-01 21:19:01 -0400
commitbe1158cc615fd723552f0d9912087423c7cadda5 (patch)
treedee7dc2306bb71cdd5c28d3f09b9f04dfd4cc2ff /fs/jbd2
parented8a1a766af7371bfbe41857a3a11496b4165143 (diff)
jbd2: fold __process_buffer() into jbd2_log_do_checkpoint()
__process_buffer() is only called by jbd2_log_do_checkpoint(), and it had a very complex locking protocol where it would be called with the j_list_lock, and sometimes exit with the lock held (if the return code was 0), or release the lock. This was confusing both to humans and to smatch (which erronously complained that the lock was taken twice). Folding __process_buffer() to the caller allows us to simplify the control flow, making the resulting function easier to read and reason about, and dropping the compiled size of fs/jbd2/checkpoint.c by 150 bytes (over 4% of the text size). Signed-off-by: Theodore Ts'o <tytso@mit.edu> Reviewed-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/jbd2')
-rw-r--r--fs/jbd2/checkpoint.c195
1 files changed, 84 insertions, 111 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 7f34f4716165..f1507e5b7c9a 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -255,81 +255,6 @@ __flush_batch(journal_t *journal, int *batch_count)
255} 255}
256 256
257/* 257/*
258 * Try to flush one buffer from the checkpoint list to disk.
259 *
260 * Return 1 if something happened which requires us to abort the current
261 * scan of the checkpoint list. Return <0 if the buffer has failed to
262 * be written out.
263 *
264 * Called with j_list_lock held and drops it if 1 is returned
265 */
266static int __process_buffer(journal_t *journal, struct journal_head *jh,
267 int *batch_count, transaction_t *transaction)
268{
269 struct buffer_head *bh = jh2bh(jh);
270 int ret = 0;
271
272 if (buffer_locked(bh)) {
273 get_bh(bh);
274 spin_unlock(&journal->j_list_lock);
275 wait_on_buffer(bh);
276 /* the journal_head may have gone by now */
277 BUFFER_TRACE(bh, "brelse");
278 __brelse(bh);
279 ret = 1;
280 } else if (jh->b_transaction != NULL) {
281 transaction_t *t = jh->b_transaction;
282 tid_t tid = t->t_tid;
283
284 transaction->t_chp_stats.cs_forced_to_close++;
285 spin_unlock(&journal->j_list_lock);
286 if (unlikely(journal->j_flags & JBD2_UNMOUNT))
287 /*
288 * The journal thread is dead; so starting and
289 * waiting for a commit to finish will cause
290 * us to wait for a _very_ long time.
291 */
292 printk(KERN_ERR "JBD2: %s: "
293 "Waiting for Godot: block %llu\n",
294 journal->j_devname,
295 (unsigned long long) bh->b_blocknr);
296 jbd2_log_start_commit(journal, tid);
297 jbd2_log_wait_commit(journal, tid);
298 ret = 1;
299 } else if (!buffer_dirty(bh)) {
300 ret = 1;
301 if (unlikely(buffer_write_io_error(bh)))
302 ret = -EIO;
303 get_bh(bh);
304 BUFFER_TRACE(bh, "remove from checkpoint");
305 __jbd2_journal_remove_checkpoint(jh);
306 spin_unlock(&journal->j_list_lock);
307 __brelse(bh);
308 } else {
309 /*
310 * Important: we are about to write the buffer, and
311 * possibly block, while still holding the journal lock.
312 * We cannot afford to let the transaction logic start
313 * messing around with this buffer before we write it to
314 * disk, as that would break recoverability.
315 */
316 BUFFER_TRACE(bh, "queue");
317 get_bh(bh);
318 J_ASSERT_BH(bh, !buffer_jwrite(bh));
319 journal->j_chkpt_bhs[*batch_count] = bh;
320 __buffer_relink_io(jh);
321 transaction->t_chp_stats.cs_written++;
322 (*batch_count)++;
323 if (*batch_count == JBD2_NR_BATCH) {
324 spin_unlock(&journal->j_list_lock);
325 __flush_batch(journal, batch_count);
326 ret = 1;
327 }
328 }
329 return ret;
330}
331
332/*
333 * Perform an actual checkpoint. We take the first transaction on the 258 * Perform an actual checkpoint. We take the first transaction on the
334 * list of transactions to be checkpointed and send all its buffers 259 * list of transactions to be checkpointed and send all its buffers
335 * to disk. We submit larger chunks of data at once. 260 * to disk. We submit larger chunks of data at once.
@@ -339,9 +264,11 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
339 */ 264 */
340int jbd2_log_do_checkpoint(journal_t *journal) 265int jbd2_log_do_checkpoint(journal_t *journal)
341{ 266{
342 transaction_t *transaction; 267 struct journal_head *jh;
343 tid_t this_tid; 268 struct buffer_head *bh;
344 int result; 269 transaction_t *transaction;
270 tid_t this_tid;
271 int err, result, batch_count = 0;
345 272
346 jbd_debug(1, "Start checkpoint\n"); 273 jbd_debug(1, "Start checkpoint\n");
347 274
@@ -374,46 +301,92 @@ restart:
374 * done (maybe it's a new transaction, but it fell at the same 301 * done (maybe it's a new transaction, but it fell at the same
375 * address). 302 * address).
376 */ 303 */
377 if (journal->j_checkpoint_transactions == transaction && 304 if (journal->j_checkpoint_transactions != transaction ||
378 transaction->t_tid == this_tid) { 305 transaction->t_tid != this_tid)
379 int batch_count = 0; 306 goto out;
380 struct journal_head *jh;
381 int retry = 0, err;
382
383 while (!retry && transaction->t_checkpoint_list) {
384 jh = transaction->t_checkpoint_list;
385 retry = __process_buffer(journal, jh, &batch_count,
386 transaction);
387 if (retry < 0 && !result)
388 result = retry;
389 if (!retry && (need_resched() ||
390 spin_needbreak(&journal->j_list_lock))) {
391 spin_unlock(&journal->j_list_lock);
392 retry = 1;
393 break;
394 }
395 }
396 307
397 if (batch_count) { 308 /* checkpoint all of the transaction's buffers */
398 if (!retry) { 309 while (transaction->t_checkpoint_list) {
399 spin_unlock(&journal->j_list_lock); 310 jh = transaction->t_checkpoint_list;
400 retry = 1; 311 bh = jh2bh(jh);
401 } 312
402 __flush_batch(journal, &batch_count); 313 if (buffer_locked(bh)) {
314 spin_unlock(&journal->j_list_lock);
315 get_bh(bh);
316 wait_on_buffer(bh);
317 /* the journal_head may have gone by now */
318 BUFFER_TRACE(bh, "brelse");
319 __brelse(bh);
320 goto retry;
403 } 321 }
322 if (jh->b_transaction != NULL) {
323 transaction_t *t = jh->b_transaction;
324 tid_t tid = t->t_tid;
404 325
405 if (retry) { 326 transaction->t_chp_stats.cs_forced_to_close++;
406 spin_lock(&journal->j_list_lock); 327 spin_unlock(&journal->j_list_lock);
407 goto restart; 328 if (unlikely(journal->j_flags & JBD2_UNMOUNT))
329 /*
330 * The journal thread is dead; so
331 * starting and waiting for a commit
332 * to finish will cause us to wait for
333 * a _very_ long time.
334 */
335 printk(KERN_ERR
336 "JBD2: %s: Waiting for Godot: block %llu\n",
337 journal->j_devname, (unsigned long long) bh->b_blocknr);
338
339 jbd2_log_start_commit(journal, tid);
340 jbd2_log_wait_commit(journal, tid);
341 goto retry;
342 }
343 if (!buffer_dirty(bh)) {
344 if (unlikely(buffer_write_io_error(bh)) && !result)
345 result = -EIO;
346 get_bh(bh);
347 BUFFER_TRACE(bh, "remove from checkpoint");
348 __jbd2_journal_remove_checkpoint(jh);
349 spin_unlock(&journal->j_list_lock);
350 __brelse(bh);
351 goto retry;
408 } 352 }
409 /* 353 /*
410 * Now we have cleaned up the first transaction's checkpoint 354 * Important: we are about to write the buffer, and
411 * list. Let's clean up the second one 355 * possibly block, while still holding the journal
356 * lock. We cannot afford to let the transaction
357 * logic start messing around with this buffer before
358 * we write it to disk, as that would break
359 * recoverability.
412 */ 360 */
413 err = __wait_cp_io(journal, transaction); 361 BUFFER_TRACE(bh, "queue");
414 if (!result) 362 get_bh(bh);
415 result = err; 363 J_ASSERT_BH(bh, !buffer_jwrite(bh));
364 journal->j_chkpt_bhs[batch_count++] = bh;
365 __buffer_relink_io(jh);
366 transaction->t_chp_stats.cs_written++;
367 if ((batch_count == JBD2_NR_BATCH) ||
368 need_resched() ||
369 spin_needbreak(&journal->j_list_lock))
370 goto unlock_and_flush;
416 } 371 }
372
373 if (batch_count) {
374 unlock_and_flush:
375 spin_unlock(&journal->j_list_lock);
376 retry:
377 if (batch_count)
378 __flush_batch(journal, &batch_count);
379 spin_lock(&journal->j_list_lock);
380 goto restart;
381 }
382
383 /*
384 * Now we issued all of the transaction's buffers, let's deal
385 * with the buffers that are out for I/O.
386 */
387 err = __wait_cp_io(journal, transaction);
388 if (!result)
389 result = err;
417out: 390out:
418 spin_unlock(&journal->j_list_lock); 391 spin_unlock(&journal->j_list_lock);
419 if (result < 0) 392 if (result < 0)