aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/incore.h2
-rw-r--r--fs/gfs2/log.c57
-rw-r--r--fs/gfs2/lops.c160
-rw-r--r--fs/gfs2/ops_address.c50
-rw-r--r--fs/gfs2/ops_fstype.c1
5 files changed, 143 insertions, 127 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 23b611aa70d2..388dc1bd736f 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -612,13 +612,13 @@ struct gfs2_sbd {
612 unsigned int sd_log_num_revoke; 612 unsigned int sd_log_num_revoke;
613 unsigned int sd_log_num_rg; 613 unsigned int sd_log_num_rg;
614 unsigned int sd_log_num_databuf; 614 unsigned int sd_log_num_databuf;
615 unsigned int sd_log_num_jdata;
616 615
617 struct list_head sd_log_le_gl; 616 struct list_head sd_log_le_gl;
618 struct list_head sd_log_le_buf; 617 struct list_head sd_log_le_buf;
619 struct list_head sd_log_le_revoke; 618 struct list_head sd_log_le_revoke;
620 struct list_head sd_log_le_rg; 619 struct list_head sd_log_le_rg;
621 struct list_head sd_log_le_databuf; 620 struct list_head sd_log_le_databuf;
621 struct list_head sd_log_le_ordered;
622 622
623 unsigned int sd_log_blks_free; 623 unsigned int sd_log_blks_free;
624 struct mutex sd_log_reserve_mutex; 624 struct mutex sd_log_reserve_mutex;
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index d8232ec25397..20fa528d457d 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -620,6 +620,57 @@ static void log_flush_commit(struct gfs2_sbd *sdp)
620 } 620 }
621} 621}
622 622
623static void gfs2_ordered_write(struct gfs2_sbd *sdp)
624{
625 struct gfs2_bufdata *bd;
626 struct buffer_head *bh;
627 LIST_HEAD(written);
628
629 gfs2_log_lock(sdp);
630 while (!list_empty(&sdp->sd_log_le_ordered)) {
631 bd = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_bufdata, bd_le.le_list);
632 list_move(&bd->bd_le.le_list, &written);
633 bh = bd->bd_bh;
634 if (!buffer_dirty(bh))
635 continue;
636 get_bh(bh);
637 gfs2_log_unlock(sdp);
638 lock_buffer(bh);
639 if (test_clear_buffer_dirty(bh)) {
640 bh->b_end_io = end_buffer_write_sync;
641 submit_bh(WRITE, bh);
642 } else {
643 unlock_buffer(bh);
644 brelse(bh);
645 }
646 gfs2_log_lock(sdp);
647 }
648 list_splice(&written, &sdp->sd_log_le_ordered);
649 gfs2_log_unlock(sdp);
650}
651
652static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
653{
654 struct gfs2_bufdata *bd;
655 struct buffer_head *bh;
656
657 gfs2_log_lock(sdp);
658 while (!list_empty(&sdp->sd_log_le_ordered)) {
659 bd = list_entry(sdp->sd_log_le_ordered.prev, struct gfs2_bufdata, bd_le.le_list);
660 bh = bd->bd_bh;
661 if (buffer_locked(bh)) {
662 get_bh(bh);
663 gfs2_log_unlock(sdp);
664 wait_on_buffer(bh);
665 brelse(bh);
666 gfs2_log_lock(sdp);
667 continue;
668 }
669 list_del_init(&bd->bd_le.le_list);
670 }
671 gfs2_log_unlock(sdp);
672}
673
623/** 674/**
624 * gfs2_log_flush - flush incore transaction(s) 675 * gfs2_log_flush - flush incore transaction(s)
625 * @sdp: the filesystem 676 * @sdp: the filesystem
@@ -648,7 +699,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
648 INIT_LIST_HEAD(&ai->ai_ail2_list); 699 INIT_LIST_HEAD(&ai->ai_ail2_list);
649 700
650 gfs2_assert_withdraw(sdp, 701 gfs2_assert_withdraw(sdp,
651 sdp->sd_log_num_buf + sdp->sd_log_num_jdata == 702 sdp->sd_log_num_buf + sdp->sd_log_num_databuf ==
652 sdp->sd_log_commited_buf + 703 sdp->sd_log_commited_buf +
653 sdp->sd_log_commited_databuf); 704 sdp->sd_log_commited_databuf);
654 gfs2_assert_withdraw(sdp, 705 gfs2_assert_withdraw(sdp,
@@ -658,7 +709,10 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
658 sdp->sd_log_flush_wrapped = 0; 709 sdp->sd_log_flush_wrapped = 0;
659 ai->ai_first = sdp->sd_log_flush_head; 710 ai->ai_first = sdp->sd_log_flush_head;
660 711
712 gfs2_ordered_write(sdp);
661 lops_before_commit(sdp); 713 lops_before_commit(sdp);
714 gfs2_ordered_wait(sdp);
715
662 if (!list_empty(&sdp->sd_log_flush_list)) 716 if (!list_empty(&sdp->sd_log_flush_list))
663 log_flush_commit(sdp); 717 log_flush_commit(sdp);
664 else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ 718 else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
@@ -751,7 +805,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
751 gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); 805 gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved);
752 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl); 806 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl);
753 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf); 807 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf);
754 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_jdata);
755 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); 808 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
756 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); 809 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
757 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf); 810 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf);
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);
562out: 563out:
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
591static void databuf_lo_before_commit(struct gfs2_sbd *sdp) 589static 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
760static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, 682static 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
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 8407d1db4eac..dd1ea491ddcb 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -616,13 +616,50 @@ static sector_t gfs2_bmap(struct address_space *mapping, sector_t lblock)
616 return dblock; 616 return dblock;
617} 617}
618 618
619static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh)
620{
621 struct gfs2_bufdata *bd;
622
623 lock_buffer(bh);
624 gfs2_log_lock(sdp);
625 clear_buffer_dirty(bh);
626 bd = bh->b_private;
627 if (bd) {
628 if (!list_empty(&bd->bd_le.le_list)) {
629 if (!buffer_pinned(bh))
630 list_del_init(&bd->bd_le.le_list);
631 }
632 }
633 bh->b_bdev = NULL;
634 clear_buffer_mapped(bh);
635 clear_buffer_req(bh);
636 clear_buffer_new(bh);
637 gfs2_log_unlock(sdp);
638 unlock_buffer(bh);
639}
640
619static void gfs2_invalidatepage(struct page *page, unsigned long offset) 641static void gfs2_invalidatepage(struct page *page, unsigned long offset)
620{ 642{
643 struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
644 struct buffer_head *bh, *head;
645 unsigned long pos = 0;
646
621 BUG_ON(!PageLocked(page)); 647 BUG_ON(!PageLocked(page));
622 if (offset == 0) 648 if (offset == 0)
623 ClearPageChecked(page); 649 ClearPageChecked(page);
650 if (!page_has_buffers(page))
651 goto out;
624 652
625 block_invalidatepage(page, offset); 653 bh = head = page_buffers(page);
654 do {
655 if (offset <= pos)
656 gfs2_discard(sdp, bh);
657 pos += bh->b_size;
658 bh = bh->b_this_page;
659 } while (bh != head);
660out:
661 if (offset == 0)
662 try_to_release_page(page, 0);
626} 663}
627 664
628/** 665/**
@@ -732,9 +769,14 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
732 if (bd) { 769 if (bd) {
733 gfs2_assert_warn(sdp, bd->bd_bh == bh); 770 gfs2_assert_warn(sdp, bd->bd_bh == bh);
734 gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr)); 771 gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr));
735 bd->bd_bh = NULL; 772 if (!list_empty(&bd->bd_le.le_list)) {
736 if (!list_empty(&bd->bd_le.le_list)) 773 if (!buffer_pinned(bh))
737 bd = NULL; 774 list_del_init(&bd->bd_le.le_list);
775 else
776 bd = NULL;
777 }
778 if (bd)
779 bd->bd_bh = NULL;
738 bh->b_private = NULL; 780 bh->b_private = NULL;
739 } 781 }
740 gfs2_log_unlock(sdp); 782 gfs2_log_unlock(sdp);
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 314c1134d12d..35f3dfa9bfb1 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -82,6 +82,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
82 INIT_LIST_HEAD(&sdp->sd_log_le_revoke); 82 INIT_LIST_HEAD(&sdp->sd_log_le_revoke);
83 INIT_LIST_HEAD(&sdp->sd_log_le_rg); 83 INIT_LIST_HEAD(&sdp->sd_log_le_rg);
84 INIT_LIST_HEAD(&sdp->sd_log_le_databuf); 84 INIT_LIST_HEAD(&sdp->sd_log_le_databuf);
85 INIT_LIST_HEAD(&sdp->sd_log_le_ordered);
85 86
86 mutex_init(&sdp->sd_log_reserve_mutex); 87 mutex_init(&sdp->sd_log_reserve_mutex);
87 INIT_LIST_HEAD(&sdp->sd_ail1_list); 88 INIT_LIST_HEAD(&sdp->sd_ail1_list);