diff options
Diffstat (limited to 'fs/gfs2/lops.c')
-rw-r--r-- | fs/gfs2/lops.c | 160 |
1 files changed, 40 insertions, 120 deletions
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 3ec587135d46..7e2d4e692b50 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -555,10 +555,11 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
555 | if (gfs2_is_jdata(ip)) { | 555 | if (gfs2_is_jdata(ip)) { |
556 | gfs2_pin(sdp, bd->bd_bh); | 556 | gfs2_pin(sdp, bd->bd_bh); |
557 | tr->tr_num_databuf_new++; | 557 | tr->tr_num_databuf_new++; |
558 | sdp->sd_log_num_jdata++; | 558 | sdp->sd_log_num_databuf++; |
559 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | ||
560 | } else { | ||
561 | list_add(&le->le_list, &sdp->sd_log_le_ordered); | ||
559 | } | 562 | } |
560 | sdp->sd_log_num_databuf++; | ||
561 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | ||
562 | out: | 563 | out: |
563 | gfs2_log_unlock(sdp); | 564 | gfs2_log_unlock(sdp); |
564 | unlock_buffer(bd->bd_bh); | 565 | unlock_buffer(bd->bd_bh); |
@@ -583,114 +584,59 @@ static int gfs2_check_magic(struct buffer_head *bh) | |||
583 | /** | 584 | /** |
584 | * databuf_lo_before_commit - Scan the data buffers, writing as we go | 585 | * databuf_lo_before_commit - Scan the data buffers, writing as we go |
585 | * | 586 | * |
586 | * Here we scan through the lists of buffers and make the assumption | ||
587 | * that any buffer thats been pinned is being journaled, and that | ||
588 | * any unpinned buffer is an ordered write data buffer and therefore | ||
589 | * will be written back rather than journaled. | ||
590 | */ | 587 | */ |
588 | |||
591 | static void databuf_lo_before_commit(struct gfs2_sbd *sdp) | 589 | static void databuf_lo_before_commit(struct gfs2_sbd *sdp) |
592 | { | 590 | { |
593 | LIST_HEAD(started); | 591 | struct gfs2_bufdata *bd1 = NULL, *bd2; |
594 | struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt; | ||
595 | struct buffer_head *bh = NULL,*bh1 = NULL; | 592 | struct buffer_head *bh = NULL,*bh1 = NULL; |
596 | struct gfs2_log_descriptor *ld; | 593 | struct gfs2_log_descriptor *ld; |
597 | unsigned int limit; | 594 | unsigned int limit; |
598 | unsigned int total_dbuf; | 595 | unsigned int total; |
599 | unsigned int total_jdata; | ||
600 | unsigned int num, n; | 596 | unsigned int num, n; |
601 | __be64 *ptr = NULL; | 597 | __be64 *ptr = NULL; |
598 | int magic; | ||
599 | |||
602 | 600 | ||
603 | limit = databuf_limit(sdp); | 601 | limit = databuf_limit(sdp); |
604 | 602 | ||
605 | /* | ||
606 | * Start writing ordered buffers, write journaled buffers | ||
607 | * into the log along with a header | ||
608 | */ | ||
609 | gfs2_log_lock(sdp); | 603 | gfs2_log_lock(sdp); |
610 | total_dbuf = sdp->sd_log_num_databuf; | 604 | total = sdp->sd_log_num_databuf; |
611 | total_jdata = sdp->sd_log_num_jdata; | ||
612 | bd2 = bd1 = list_prepare_entry(bd1, &sdp->sd_log_le_databuf, | 605 | bd2 = bd1 = list_prepare_entry(bd1, &sdp->sd_log_le_databuf, |
613 | bd_le.le_list); | 606 | bd_le.le_list); |
614 | while(total_dbuf) { | 607 | while(total) { |
615 | num = total_jdata; | 608 | num = total; |
616 | if (num > limit) | 609 | if (num > limit) |
617 | num = limit; | 610 | num = limit; |
611 | |||
612 | gfs2_log_unlock(sdp); | ||
613 | bh = gfs2_log_get_buf(sdp); | ||
614 | gfs2_log_lock(sdp); | ||
615 | |||
616 | ld = (struct gfs2_log_descriptor *)bh->b_data; | ||
617 | ptr = (__be64 *)(bh->b_data + DATABUF_OFFSET); | ||
618 | ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | ||
619 | ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD); | ||
620 | ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD); | ||
621 | ld->ld_type = cpu_to_be32(GFS2_LOG_DESC_JDATA); | ||
622 | ld->ld_length = cpu_to_be32(num + 1); | ||
623 | ld->ld_data1 = cpu_to_be32(num); | ||
624 | ld->ld_data2 = cpu_to_be32(0); | ||
625 | memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); | ||
626 | |||
618 | n = 0; | 627 | n = 0; |
619 | list_for_each_entry_safe_continue(bd1, bdt, | 628 | list_for_each_entry_continue(bd1, &sdp->sd_log_le_databuf, |
620 | &sdp->sd_log_le_databuf, | 629 | bd_le.le_list) { |
621 | bd_le.le_list) { | ||
622 | /* store off the buffer head in a local ptr since | ||
623 | * gfs2_bufdata might change when we drop the log lock | ||
624 | */ | ||
625 | bh1 = bd1->bd_bh; | 630 | bh1 = bd1->bd_bh; |
626 | 631 | ||
627 | /* An ordered write buffer */ | 632 | magic = gfs2_check_magic(bh1); |
628 | if (bh1 && !buffer_pinned(bh1)) { | 633 | *ptr++ = cpu_to_be64(bh1->b_blocknr); |
629 | list_move(&bd1->bd_le.le_list, &started); | 634 | *ptr++ = cpu_to_be64((__u64)magic); |
630 | if (bd1 == bd2) { | 635 | clear_buffer_escaped(bh1); |
631 | bd2 = NULL; | 636 | if (unlikely(magic != 0)) |
632 | bd2 = list_prepare_entry(bd2, | 637 | set_buffer_escaped(bh1); |
633 | &sdp->sd_log_le_databuf, | 638 | if (++n >= num) |
634 | bd_le.le_list); | 639 | break; |
635 | } | ||
636 | total_dbuf--; | ||
637 | if (bh1) { | ||
638 | if (buffer_dirty(bh1)) { | ||
639 | get_bh(bh1); | ||
640 | |||
641 | gfs2_log_unlock(sdp); | ||
642 | |||
643 | ll_rw_block(SWRITE, 1, &bh1); | ||
644 | brelse(bh1); | ||
645 | |||
646 | gfs2_log_lock(sdp); | ||
647 | } | ||
648 | continue; | ||
649 | } | ||
650 | continue; | ||
651 | } else if (bh1) { /* A journaled buffer */ | ||
652 | int magic; | ||
653 | gfs2_log_unlock(sdp); | ||
654 | if (!bh) { | ||
655 | bh = gfs2_log_get_buf(sdp); | ||
656 | ld = (struct gfs2_log_descriptor *) | ||
657 | bh->b_data; | ||
658 | ptr = (__be64 *)(bh->b_data + | ||
659 | DATABUF_OFFSET); | ||
660 | ld->ld_header.mh_magic = | ||
661 | cpu_to_be32(GFS2_MAGIC); | ||
662 | ld->ld_header.mh_type = | ||
663 | cpu_to_be32(GFS2_METATYPE_LD); | ||
664 | ld->ld_header.mh_format = | ||
665 | cpu_to_be32(GFS2_FORMAT_LD); | ||
666 | ld->ld_type = | ||
667 | cpu_to_be32(GFS2_LOG_DESC_JDATA); | ||
668 | ld->ld_length = cpu_to_be32(num + 1); | ||
669 | ld->ld_data1 = cpu_to_be32(num); | ||
670 | ld->ld_data2 = cpu_to_be32(0); | ||
671 | memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); | ||
672 | } | ||
673 | magic = gfs2_check_magic(bh1); | ||
674 | *ptr++ = cpu_to_be64(bh1->b_blocknr); | ||
675 | *ptr++ = cpu_to_be64((__u64)magic); | ||
676 | clear_buffer_escaped(bh1); | ||
677 | if (unlikely(magic != 0)) | ||
678 | set_buffer_escaped(bh1); | ||
679 | gfs2_log_lock(sdp); | ||
680 | if (++n >= num) | ||
681 | break; | ||
682 | } else if (!bh1) { | ||
683 | total_dbuf--; | ||
684 | sdp->sd_log_num_databuf--; | ||
685 | list_del_init(&bd1->bd_le.le_list); | ||
686 | if (bd1 == bd2) { | ||
687 | bd2 = NULL; | ||
688 | bd2 = list_prepare_entry(bd2, | ||
689 | &sdp->sd_log_le_databuf, | ||
690 | bd_le.le_list); | ||
691 | } | ||
692 | kmem_cache_free(gfs2_bufdata_cachep, bd1); | ||
693 | } | ||
694 | } | 640 | } |
695 | gfs2_log_unlock(sdp); | 641 | gfs2_log_unlock(sdp); |
696 | if (bh) { | 642 | if (bh) { |
@@ -727,34 +673,10 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) | |||
727 | break; | 673 | break; |
728 | } | 674 | } |
729 | bh = NULL; | 675 | bh = NULL; |
730 | BUG_ON(total_dbuf < num); | 676 | BUG_ON(total < num); |
731 | total_dbuf -= num; | 677 | total -= num; |
732 | total_jdata -= num; | ||
733 | } | 678 | } |
734 | gfs2_log_unlock(sdp); | 679 | gfs2_log_unlock(sdp); |
735 | |||
736 | /* Wait on all ordered buffers */ | ||
737 | while (!list_empty(&started)) { | ||
738 | gfs2_log_lock(sdp); | ||
739 | bd1 = list_entry(started.next, struct gfs2_bufdata, | ||
740 | bd_le.le_list); | ||
741 | list_del_init(&bd1->bd_le.le_list); | ||
742 | sdp->sd_log_num_databuf--; | ||
743 | bh = bd1->bd_bh; | ||
744 | if (bh) { | ||
745 | bh->b_private = NULL; | ||
746 | get_bh(bh); | ||
747 | gfs2_log_unlock(sdp); | ||
748 | wait_on_buffer(bh); | ||
749 | brelse(bh); | ||
750 | } else | ||
751 | gfs2_log_unlock(sdp); | ||
752 | |||
753 | kmem_cache_free(gfs2_bufdata_cachep, bd1); | ||
754 | } | ||
755 | |||
756 | /* We've removed all the ordered write bufs here, so only jdata left */ | ||
757 | gfs2_assert_warn(sdp, sdp->sd_log_num_databuf == sdp->sd_log_num_jdata); | ||
758 | } | 680 | } |
759 | 681 | ||
760 | static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, | 682 | static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, |
@@ -838,11 +760,9 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
838 | bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list); | 760 | bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list); |
839 | list_del_init(&bd->bd_le.le_list); | 761 | list_del_init(&bd->bd_le.le_list); |
840 | sdp->sd_log_num_databuf--; | 762 | sdp->sd_log_num_databuf--; |
841 | sdp->sd_log_num_jdata--; | ||
842 | gfs2_unpin(sdp, bd->bd_bh, ai); | 763 | gfs2_unpin(sdp, bd->bd_bh, ai); |
843 | } | 764 | } |
844 | gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf); | 765 | gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf); |
845 | gfs2_assert_warn(sdp, !sdp->sd_log_num_jdata); | ||
846 | } | 766 | } |
847 | 767 | ||
848 | 768 | ||