aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/lops.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2007-09-02 05:48:13 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2007-10-10 03:56:03 -0400
commitd7b616e252b125f12b007c392f7644053bb6f140 (patch)
tree0794272905a1876ef74144a993f7a76400893813 /fs/gfs2/lops.c
parent9b9107a5a8b190e6cf09bbdf893869c6a9c482cc (diff)
[GFS2] Clean up ordered write code
The following patch removes the ordered write processing from databuf_lo_before_commit() and moves it to log.c. This has the effect of greatly simplyfying databuf_lo_before_commit() and well as potentially making the ordered write code more efficient. As a side effect of this, its now possible to remove ordered buffers from the ordered buffer list at any time, so we now make use of this in invalidatepage and releasepage to ensure timely release of these buffers. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/lops.c')
-rw-r--r--fs/gfs2/lops.c160
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);
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