diff options
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r-- | fs/gfs2/log.c | 129 |
1 files changed, 102 insertions, 27 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 291415ddfe51..f49a12e24086 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -83,6 +83,11 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
83 | 83 | ||
84 | gfs2_assert(sdp, bd->bd_ail == ai); | 84 | gfs2_assert(sdp, bd->bd_ail == ai); |
85 | 85 | ||
86 | if (!bh){ | ||
87 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | ||
88 | continue; | ||
89 | } | ||
90 | |||
86 | if (!buffer_busy(bh)) { | 91 | if (!buffer_busy(bh)) { |
87 | if (!buffer_uptodate(bh)) { | 92 | if (!buffer_uptodate(bh)) { |
88 | gfs2_log_unlock(sdp); | 93 | gfs2_log_unlock(sdp); |
@@ -125,6 +130,11 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl | |||
125 | bd_ail_st_list) { | 130 | bd_ail_st_list) { |
126 | bh = bd->bd_bh; | 131 | bh = bd->bd_bh; |
127 | 132 | ||
133 | if (!bh){ | ||
134 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | ||
135 | continue; | ||
136 | } | ||
137 | |||
128 | gfs2_assert(sdp, bd->bd_ail == ai); | 138 | gfs2_assert(sdp, bd->bd_ail == ai); |
129 | 139 | ||
130 | if (buffer_busy(bh)) { | 140 | if (buffer_busy(bh)) { |
@@ -262,8 +272,8 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) | |||
262 | * @sdp: The GFS2 superblock | 272 | * @sdp: The GFS2 superblock |
263 | * @blks: The number of blocks to reserve | 273 | * @blks: The number of blocks to reserve |
264 | * | 274 | * |
265 | * Note that we never give out the last 6 blocks of the journal. Thats | 275 | * Note that we never give out the last few blocks of the journal. Thats |
266 | * due to the fact that there is are a small number of header blocks | 276 | * due to the fact that there is a small number of header blocks |
267 | * associated with each log flush. The exact number can't be known until | 277 | * associated with each log flush. The exact number can't be known until |
268 | * flush time, so we ensure that we have just enough free blocks at all | 278 | * flush time, so we ensure that we have just enough free blocks at all |
269 | * times to avoid running out during a log flush. | 279 | * times to avoid running out during a log flush. |
@@ -274,6 +284,7 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) | |||
274 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) | 284 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) |
275 | { | 285 | { |
276 | unsigned int try = 0; | 286 | unsigned int try = 0; |
287 | unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize); | ||
277 | 288 | ||
278 | if (gfs2_assert_warn(sdp, blks) || | 289 | if (gfs2_assert_warn(sdp, blks) || |
279 | gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks)) | 290 | gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks)) |
@@ -281,7 +292,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) | |||
281 | 292 | ||
282 | mutex_lock(&sdp->sd_log_reserve_mutex); | 293 | mutex_lock(&sdp->sd_log_reserve_mutex); |
283 | gfs2_log_lock(sdp); | 294 | gfs2_log_lock(sdp); |
284 | while(sdp->sd_log_blks_free <= (blks + 6)) { | 295 | while(sdp->sd_log_blks_free <= (blks + reserved_blks)) { |
285 | gfs2_log_unlock(sdp); | 296 | gfs2_log_unlock(sdp); |
286 | gfs2_ail1_empty(sdp, 0); | 297 | gfs2_ail1_empty(sdp, 0); |
287 | gfs2_log_flush(sdp, NULL); | 298 | gfs2_log_flush(sdp, NULL); |
@@ -357,6 +368,58 @@ static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer | |||
357 | return dist; | 368 | return dist; |
358 | } | 369 | } |
359 | 370 | ||
371 | /** | ||
372 | * calc_reserved - Calculate the number of blocks to reserve when | ||
373 | * refunding a transaction's unused buffers. | ||
374 | * @sdp: The GFS2 superblock | ||
375 | * | ||
376 | * This is complex. We need to reserve room for all our currently used | ||
377 | * metadata buffers (e.g. normal file I/O rewriting file time stamps) and | ||
378 | * all our journaled data buffers for journaled files (e.g. files in the | ||
379 | * meta_fs like rindex, or files for which chattr +j was done.) | ||
380 | * If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush | ||
381 | * will count it as free space (sd_log_blks_free) and corruption will follow. | ||
382 | * | ||
383 | * We can have metadata bufs and jdata bufs in the same journal. So each | ||
384 | * type gets its own log header, for which we need to reserve a block. | ||
385 | * In fact, each type has the potential for needing more than one header | ||
386 | * in cases where we have more buffers than will fit on a journal page. | ||
387 | * Metadata journal entries take up half the space of journaled buffer entries. | ||
388 | * Thus, metadata entries have buf_limit (502) and journaled buffers have | ||
389 | * databuf_limit (251) before they cause a wrap around. | ||
390 | * | ||
391 | * Also, we need to reserve blocks for revoke journal entries and one for an | ||
392 | * overall header for the lot. | ||
393 | * | ||
394 | * Returns: the number of blocks reserved | ||
395 | */ | ||
396 | static unsigned int calc_reserved(struct gfs2_sbd *sdp) | ||
397 | { | ||
398 | unsigned int reserved = 0; | ||
399 | unsigned int mbuf_limit, metabufhdrs_needed; | ||
400 | unsigned int dbuf_limit, databufhdrs_needed; | ||
401 | unsigned int revokes = 0; | ||
402 | |||
403 | mbuf_limit = buf_limit(sdp); | ||
404 | metabufhdrs_needed = (sdp->sd_log_commited_buf + | ||
405 | (mbuf_limit - 1)) / mbuf_limit; | ||
406 | dbuf_limit = databuf_limit(sdp); | ||
407 | databufhdrs_needed = (sdp->sd_log_commited_databuf + | ||
408 | (dbuf_limit - 1)) / dbuf_limit; | ||
409 | |||
410 | if (sdp->sd_log_commited_revoke) | ||
411 | revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke, | ||
412 | sizeof(u64)); | ||
413 | |||
414 | reserved = sdp->sd_log_commited_buf + metabufhdrs_needed + | ||
415 | sdp->sd_log_commited_databuf + databufhdrs_needed + | ||
416 | revokes; | ||
417 | /* One for the overall header */ | ||
418 | if (reserved) | ||
419 | reserved++; | ||
420 | return reserved; | ||
421 | } | ||
422 | |||
360 | static unsigned int current_tail(struct gfs2_sbd *sdp) | 423 | static unsigned int current_tail(struct gfs2_sbd *sdp) |
361 | { | 424 | { |
362 | struct gfs2_ail *ai; | 425 | struct gfs2_ail *ai; |
@@ -447,14 +510,14 @@ struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, | |||
447 | return bh; | 510 | return bh; |
448 | } | 511 | } |
449 | 512 | ||
450 | static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail, int pull) | 513 | static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail) |
451 | { | 514 | { |
452 | unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail); | 515 | unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail); |
453 | 516 | ||
454 | ail2_empty(sdp, new_tail); | 517 | ail2_empty(sdp, new_tail); |
455 | 518 | ||
456 | gfs2_log_lock(sdp); | 519 | gfs2_log_lock(sdp); |
457 | sdp->sd_log_blks_free += dist - (pull ? 1 : 0); | 520 | sdp->sd_log_blks_free += dist; |
458 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks); | 521 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks); |
459 | gfs2_log_unlock(sdp); | 522 | gfs2_log_unlock(sdp); |
460 | 523 | ||
@@ -504,7 +567,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull) | |||
504 | brelse(bh); | 567 | brelse(bh); |
505 | 568 | ||
506 | if (sdp->sd_log_tail != tail) | 569 | if (sdp->sd_log_tail != tail) |
507 | log_pull_tail(sdp, tail, pull); | 570 | log_pull_tail(sdp, tail); |
508 | else | 571 | else |
509 | gfs2_assert_withdraw(sdp, !pull); | 572 | gfs2_assert_withdraw(sdp, !pull); |
510 | 573 | ||
@@ -517,6 +580,7 @@ static void log_flush_commit(struct gfs2_sbd *sdp) | |||
517 | struct list_head *head = &sdp->sd_log_flush_list; | 580 | struct list_head *head = &sdp->sd_log_flush_list; |
518 | struct gfs2_log_buf *lb; | 581 | struct gfs2_log_buf *lb; |
519 | struct buffer_head *bh; | 582 | struct buffer_head *bh; |
583 | int flushcount = 0; | ||
520 | 584 | ||
521 | while (!list_empty(head)) { | 585 | while (!list_empty(head)) { |
522 | lb = list_entry(head->next, struct gfs2_log_buf, lb_list); | 586 | lb = list_entry(head->next, struct gfs2_log_buf, lb_list); |
@@ -533,9 +597,20 @@ static void log_flush_commit(struct gfs2_sbd *sdp) | |||
533 | } else | 597 | } else |
534 | brelse(bh); | 598 | brelse(bh); |
535 | kfree(lb); | 599 | kfree(lb); |
600 | flushcount++; | ||
536 | } | 601 | } |
537 | 602 | ||
538 | log_write_header(sdp, 0, 0); | 603 | /* If nothing was journaled, the header is unplanned and unwanted. */ |
604 | if (flushcount) { | ||
605 | log_write_header(sdp, 0, 0); | ||
606 | } else { | ||
607 | unsigned int tail; | ||
608 | tail = current_tail(sdp); | ||
609 | |||
610 | gfs2_ail1_empty(sdp, 0); | ||
611 | if (sdp->sd_log_tail != tail) | ||
612 | log_pull_tail(sdp, tail); | ||
613 | } | ||
539 | } | 614 | } |
540 | 615 | ||
541 | /** | 616 | /** |
@@ -565,7 +640,10 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
565 | INIT_LIST_HEAD(&ai->ai_ail1_list); | 640 | INIT_LIST_HEAD(&ai->ai_ail1_list); |
566 | INIT_LIST_HEAD(&ai->ai_ail2_list); | 641 | INIT_LIST_HEAD(&ai->ai_ail2_list); |
567 | 642 | ||
568 | gfs2_assert_withdraw(sdp, sdp->sd_log_num_buf == sdp->sd_log_commited_buf); | 643 | gfs2_assert_withdraw(sdp, |
644 | sdp->sd_log_num_buf + sdp->sd_log_num_jdata == | ||
645 | sdp->sd_log_commited_buf + | ||
646 | sdp->sd_log_commited_databuf); | ||
569 | gfs2_assert_withdraw(sdp, | 647 | gfs2_assert_withdraw(sdp, |
570 | sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); | 648 | sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); |
571 | 649 | ||
@@ -576,16 +654,19 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
576 | lops_before_commit(sdp); | 654 | lops_before_commit(sdp); |
577 | if (!list_empty(&sdp->sd_log_flush_list)) | 655 | if (!list_empty(&sdp->sd_log_flush_list)) |
578 | log_flush_commit(sdp); | 656 | log_flush_commit(sdp); |
579 | else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle) | 657 | else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ |
658 | gfs2_log_lock(sdp); | ||
659 | sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */ | ||
660 | gfs2_log_unlock(sdp); | ||
580 | log_write_header(sdp, 0, PULL); | 661 | log_write_header(sdp, 0, PULL); |
662 | } | ||
581 | lops_after_commit(sdp, ai); | 663 | lops_after_commit(sdp, ai); |
582 | 664 | ||
583 | gfs2_log_lock(sdp); | 665 | gfs2_log_lock(sdp); |
584 | sdp->sd_log_head = sdp->sd_log_flush_head; | 666 | sdp->sd_log_head = sdp->sd_log_flush_head; |
585 | sdp->sd_log_blks_free -= sdp->sd_log_num_hdrs; | ||
586 | sdp->sd_log_blks_reserved = 0; | 667 | sdp->sd_log_blks_reserved = 0; |
587 | sdp->sd_log_commited_buf = 0; | 668 | sdp->sd_log_commited_buf = 0; |
588 | sdp->sd_log_num_hdrs = 0; | 669 | sdp->sd_log_commited_databuf = 0; |
589 | sdp->sd_log_commited_revoke = 0; | 670 | sdp->sd_log_commited_revoke = 0; |
590 | 671 | ||
591 | if (!list_empty(&ai->ai_ail1_list)) { | 672 | if (!list_empty(&ai->ai_ail1_list)) { |
@@ -602,32 +683,26 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
602 | 683 | ||
603 | static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | 684 | static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
604 | { | 685 | { |
605 | unsigned int reserved = 0; | 686 | unsigned int reserved; |
606 | unsigned int old; | 687 | unsigned int old; |
607 | 688 | ||
608 | gfs2_log_lock(sdp); | 689 | gfs2_log_lock(sdp); |
609 | 690 | ||
610 | sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm; | 691 | sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm; |
611 | gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_buf) >= 0); | 692 | sdp->sd_log_commited_databuf += tr->tr_num_databuf_new - |
693 | tr->tr_num_databuf_rm; | ||
694 | gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) || | ||
695 | (((int)sdp->sd_log_commited_databuf) >= 0)); | ||
612 | sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; | 696 | sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; |
613 | gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); | 697 | gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); |
614 | 698 | reserved = calc_reserved(sdp); | |
615 | if (sdp->sd_log_commited_buf) | ||
616 | reserved += sdp->sd_log_commited_buf; | ||
617 | if (sdp->sd_log_commited_revoke) | ||
618 | reserved += gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke, | ||
619 | sizeof(u64)); | ||
620 | if (reserved) | ||
621 | reserved++; | ||
622 | |||
623 | old = sdp->sd_log_blks_free; | 699 | old = sdp->sd_log_blks_free; |
624 | sdp->sd_log_blks_free += tr->tr_reserved - | 700 | sdp->sd_log_blks_free += tr->tr_reserved - |
625 | (reserved - sdp->sd_log_blks_reserved); | 701 | (reserved - sdp->sd_log_blks_reserved); |
626 | 702 | ||
627 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old); | 703 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old); |
628 | gfs2_assert_withdraw(sdp, | 704 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= |
629 | sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks + | 705 | sdp->sd_jdesc->jd_blocks); |
630 | sdp->sd_log_num_hdrs); | ||
631 | 706 | ||
632 | sdp->sd_log_blks_reserved = reserved; | 707 | sdp->sd_log_blks_reserved = reserved; |
633 | 708 | ||
@@ -673,13 +748,13 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp) | |||
673 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); | 748 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); |
674 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); | 749 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); |
675 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf); | 750 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf); |
676 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_hdrs); | ||
677 | gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list)); | 751 | gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list)); |
678 | 752 | ||
679 | sdp->sd_log_flush_head = sdp->sd_log_head; | 753 | sdp->sd_log_flush_head = sdp->sd_log_head; |
680 | sdp->sd_log_flush_wrapped = 0; | 754 | sdp->sd_log_flush_wrapped = 0; |
681 | 755 | ||
682 | log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, 0); | 756 | log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, |
757 | (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL); | ||
683 | 758 | ||
684 | gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks); | 759 | gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks); |
685 | gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail); | 760 | gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail); |