aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2012-05-30 00:01:09 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2012-06-08 06:50:01 -0400
commit90306c41dc3d8e5f12ecd0193dae99e0e7f6e896 (patch)
tree344d0e0f62620dee784a824f30679e9a5d87696d
parentba1ddcb6ca0c46edd275790d1e4e2cfd6219ce19 (diff)
GFS2: Use lvbs for storing rgrp information with mount option
Instead of reading in the resource groups when gfs2 is checking for free space to allocate from, gfs2 can store the necessary infromation in the resource group's lvb. Also, instead of searching for unlinked inodes in every resource group that's checked for free space, gfs2 can store the number of unlinked but inodes in the lvb, and only check for unlinked inodes if it will find some. The first time a resource group is locked, the lvb must initialized. Since this involves counting the unlinked inodes in the resource group, this takes a little extra time. But after that, if the resource group is locked with GL_SKIP, the buffer head won't be read in unless it's actually needed. Enabling the resource groups lvbs is done via the rgrplvb mount option. If this option isn't set, the lvbs will still be set and updated, but they won't be verfied or used by the filesystem. To safely turn on this option, all of the nodes mounting the filesystem must be running code with this patch, and the filesystem must have been completely unmounted since they were updated. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/glock.c1
-rw-r--r--fs/gfs2/incore.h2
-rw-r--r--fs/gfs2/rgrp.c147
-rw-r--r--fs/gfs2/super.c12
-rw-r--r--include/linux/gfs2_ondisk.h10
5 files changed, 163 insertions, 9 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 3ad8cb3eeb88..10ae1645d9a5 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -769,6 +769,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
769 gl->gl_stats.stats[GFS2_LKS_DCOUNT] = 0; 769 gl->gl_stats.stats[GFS2_LKS_DCOUNT] = 0;
770 gl->gl_stats.stats[GFS2_LKS_QCOUNT] = 0; 770 gl->gl_stats.stats[GFS2_LKS_QCOUNT] = 0;
771 memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb)); 771 memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb));
772 memset(gl->gl_lvb, 0, 32 * sizeof(char));
772 gl->gl_lksb.sb_lvbptr = gl->gl_lvb; 773 gl->gl_lksb.sb_lvbptr = gl->gl_lvb;
773 gl->gl_tchange = jiffies; 774 gl->gl_tchange = jiffies;
774 gl->gl_object = NULL; 775 gl->gl_object = NULL;
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 5cda51a3e3bd..dc730700b3b4 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -89,6 +89,7 @@ struct gfs2_rgrpd {
89 u64 rd_igeneration; 89 u64 rd_igeneration;
90 struct gfs2_bitmap *rd_bits; 90 struct gfs2_bitmap *rd_bits;
91 struct gfs2_sbd *rd_sbd; 91 struct gfs2_sbd *rd_sbd;
92 struct gfs2_rgrp_lvb *rd_rgl;
92 u32 rd_last_alloc; 93 u32 rd_last_alloc;
93 u32 rd_flags; 94 u32 rd_flags;
94#define GFS2_RDF_CHECK 0x10000000 /* check for unlinked inodes */ 95#define GFS2_RDF_CHECK 0x10000000 /* check for unlinked inodes */
@@ -470,6 +471,7 @@ struct gfs2_args {
470 unsigned int ar_discard:1; /* discard requests */ 471 unsigned int ar_discard:1; /* discard requests */
471 unsigned int ar_errors:2; /* errors=withdraw | panic */ 472 unsigned int ar_errors:2; /* errors=withdraw | panic */
472 unsigned int ar_nobarrier:1; /* do not send barriers */ 473 unsigned int ar_nobarrier:1; /* do not send barriers */
474 unsigned int ar_rgrplvb:1; /* use lvbs for rgrp info */
473 int ar_commit; /* Commit interval */ 475 int ar_commit; /* Commit interval */
474 int ar_statfs_quantum; /* The fast statfs interval */ 476 int ar_statfs_quantum; /* The fast statfs interval */
475 int ar_quota_quantum; /* The quota interval */ 477 int ar_quota_quantum; /* The quota interval */
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 9eca6a9cff8f..3c6f7ed16a3b 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -660,6 +660,7 @@ static int read_rindex_entry(struct gfs2_inode *ip)
660 goto fail; 660 goto fail;
661 661
662 rgd->rd_gl->gl_object = rgd; 662 rgd->rd_gl->gl_object = rgd;
663 rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lvb;
663 rgd->rd_flags &= ~GFS2_RDF_UPTODATE; 664 rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
664 if (rgd->rd_data > sdp->sd_max_rg_data) 665 if (rgd->rd_data > sdp->sd_max_rg_data)
665 sdp->sd_max_rg_data = rgd->rd_data; 666 sdp->sd_max_rg_data = rgd->rd_data;
@@ -769,9 +770,65 @@ static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
769 memset(&str->rg_reserved, 0, sizeof(str->rg_reserved)); 770 memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
770} 771}
771 772
773static int gfs2_rgrp_lvb_valid(struct gfs2_rgrpd *rgd)
774{
775 struct gfs2_rgrp_lvb *rgl = rgd->rd_rgl;
776 struct gfs2_rgrp *str = (struct gfs2_rgrp *)rgd->rd_bits[0].bi_bh->b_data;
777
778 if (rgl->rl_flags != str->rg_flags || rgl->rl_free != str->rg_free ||
779 rgl->rl_dinodes != str->rg_dinodes ||
780 rgl->rl_igeneration != str->rg_igeneration)
781 return 0;
782 return 1;
783}
784
785static void gfs2_rgrp_ondisk2lvb(struct gfs2_rgrp_lvb *rgl, const void *buf)
786{
787 const struct gfs2_rgrp *str = buf;
788
789 rgl->rl_magic = cpu_to_be32(GFS2_MAGIC);
790 rgl->rl_flags = str->rg_flags;
791 rgl->rl_free = str->rg_free;
792 rgl->rl_dinodes = str->rg_dinodes;
793 rgl->rl_igeneration = str->rg_igeneration;
794 rgl->__pad = 0UL;
795}
796
797static void update_rgrp_lvb_unlinked(struct gfs2_rgrpd *rgd, u32 change)
798{
799 struct gfs2_rgrp_lvb *rgl = rgd->rd_rgl;
800 u32 unlinked = be32_to_cpu(rgl->rl_unlinked) + change;
801 rgl->rl_unlinked = cpu_to_be32(unlinked);
802}
803
804static u32 count_unlinked(struct gfs2_rgrpd *rgd)
805{
806 struct gfs2_bitmap *bi;
807 const u32 length = rgd->rd_length;
808 const u8 *buffer = NULL;
809 u32 i, goal, count = 0;
810
811 for (i = 0, bi = rgd->rd_bits; i < length; i++, bi++) {
812 goal = 0;
813 buffer = bi->bi_bh->b_data + bi->bi_offset;
814 WARN_ON(!buffer_uptodate(bi->bi_bh));
815 while (goal < bi->bi_len * GFS2_NBBY) {
816 goal = gfs2_bitfit(buffer, bi->bi_len, goal,
817 GFS2_BLKST_UNLINKED);
818 if (goal == BFITNOENT)
819 break;
820 count++;
821 goal++;
822 }
823 }
824
825 return count;
826}
827
828
772/** 829/**
773 * gfs2_rgrp_go_lock - Read in a RG's header and bitmaps 830 * gfs2_rgrp_bh_get - Read in a RG's header and bitmaps
774 * @gh: The glock holder for the resource group 831 * @rgd: the struct gfs2_rgrpd describing the RG to read in
775 * 832 *
776 * Read in all of a Resource Group's header and bitmap blocks. 833 * Read in all of a Resource Group's header and bitmap blocks.
777 * Caller must eventually call gfs2_rgrp_relse() to free the bitmaps. 834 * Caller must eventually call gfs2_rgrp_relse() to free the bitmaps.
@@ -779,9 +836,8 @@ static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
779 * Returns: errno 836 * Returns: errno
780 */ 837 */
781 838
782int gfs2_rgrp_go_lock(struct gfs2_holder *gh) 839int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
783{ 840{
784 struct gfs2_rgrpd *rgd = gh->gh_gl->gl_object;
785 struct gfs2_sbd *sdp = rgd->rd_sbd; 841 struct gfs2_sbd *sdp = rgd->rd_sbd;
786 struct gfs2_glock *gl = rgd->rd_gl; 842 struct gfs2_glock *gl = rgd->rd_gl;
787 unsigned int length = rgd->rd_length; 843 unsigned int length = rgd->rd_length;
@@ -789,6 +845,9 @@ int gfs2_rgrp_go_lock(struct gfs2_holder *gh)
789 unsigned int x, y; 845 unsigned int x, y;
790 int error; 846 int error;
791 847
848 if (rgd->rd_bits[0].bi_bh != NULL)
849 return 0;
850
792 for (x = 0; x < length; x++) { 851 for (x = 0; x < length; x++) {
793 bi = rgd->rd_bits + x; 852 bi = rgd->rd_bits + x;
794 error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh); 853 error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh);
@@ -815,7 +874,20 @@ int gfs2_rgrp_go_lock(struct gfs2_holder *gh)
815 rgd->rd_flags |= (GFS2_RDF_UPTODATE | GFS2_RDF_CHECK); 874 rgd->rd_flags |= (GFS2_RDF_UPTODATE | GFS2_RDF_CHECK);
816 rgd->rd_free_clone = rgd->rd_free; 875 rgd->rd_free_clone = rgd->rd_free;
817 } 876 }
818 877 if (be32_to_cpu(GFS2_MAGIC) != rgd->rd_rgl->rl_magic) {
878 rgd->rd_rgl->rl_unlinked = cpu_to_be32(count_unlinked(rgd));
879 gfs2_rgrp_ondisk2lvb(rgd->rd_rgl,
880 rgd->rd_bits[0].bi_bh->b_data);
881 }
882 else if (sdp->sd_args.ar_rgrplvb) {
883 if (!gfs2_rgrp_lvb_valid(rgd)){
884 gfs2_consist_rgrpd(rgd);
885 error = -EIO;
886 goto fail;
887 }
888 if (rgd->rd_rgl->rl_unlinked == 0)
889 rgd->rd_flags &= ~GFS2_RDF_CHECK;
890 }
819 return 0; 891 return 0;
820 892
821fail: 893fail:
@@ -829,6 +901,39 @@ fail:
829 return error; 901 return error;
830} 902}
831 903
904int update_rgrp_lvb(struct gfs2_rgrpd *rgd)
905{
906 u32 rl_flags;
907
908 if (rgd->rd_flags & GFS2_RDF_UPTODATE)
909 return 0;
910
911 if (be32_to_cpu(GFS2_MAGIC) != rgd->rd_rgl->rl_magic)
912 return gfs2_rgrp_bh_get(rgd);
913
914 rl_flags = be32_to_cpu(rgd->rd_rgl->rl_flags);
915 rl_flags &= ~GFS2_RDF_MASK;
916 rgd->rd_flags &= GFS2_RDF_MASK;
917 rgd->rd_flags |= (rl_flags | GFS2_RDF_UPTODATE | GFS2_RDF_CHECK);
918 if (rgd->rd_rgl->rl_unlinked == 0)
9