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 3ad8cb3eeb8..10ae1645d9a 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 5cda51a3e3b..dc730700b3b 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 9eca6a9cff8..3c6f7ed16a3 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)
919 rgd->rd_flags &= ~GFS2_RDF_CHECK;
920 rgd->rd_free = be32_to_cpu(rgd->rd_rgl->rl_free);
921 rgd->rd_free_clone = rgd->rd_free;
922 rgd->rd_dinodes = be32_to_cpu(rgd->rd_rgl->rl_dinodes);
923 rgd->rd_igeneration = be64_to_cpu(rgd->rd_rgl->rl_igeneration);
924 return 0;
925}
926
927int gfs2_rgrp_go_lock(struct gfs2_holder *gh)
928{
929 struct gfs2_rgrpd *rgd = gh->gh_gl->gl_object;
930 struct gfs2_sbd *sdp = rgd->rd_sbd;
931
932 if (gh->gh_flags & GL_SKIP && sdp->sd_args.ar_rgrplvb)
933 return 0;
934 return gfs2_rgrp_bh_get((struct gfs2_rgrpd *)gh->gh_gl->gl_object);
935}
936
832/** 937/**
833 * gfs2_rgrp_go_unlock - Release RG bitmaps read in with gfs2_rgrp_bh_get() 938 * gfs2_rgrp_go_unlock - Release RG bitmaps read in with gfs2_rgrp_bh_get()
834 * @gh: The glock holder for the resource group 939 * @gh: The glock holder for the resource group
@@ -842,8 +947,10 @@ void gfs2_rgrp_go_unlock(struct gfs2_holder *gh)
842 947
843 for (x = 0; x < length; x++) { 948 for (x = 0; x < length; x++) {
844 struct gfs2_bitmap *bi = rgd->rd_bits + x; 949 struct gfs2_bitmap *bi = rgd->rd_bits + x;
845 brelse(bi->bi_bh); 950 if (bi->bi_bh) {
846 bi->bi_bh = NULL; 951 brelse(bi->bi_bh);
952 bi->bi_bh = NULL;
953 }
847 } 954 }
848 955
849} 956}
@@ -987,6 +1094,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
987 rgd->rd_flags |= GFS2_RGF_TRIMMED; 1094 rgd->rd_flags |= GFS2_RGF_TRIMMED;
988 gfs2_trans_add_bh(rgd->rd_gl, bh, 1); 1095 gfs2_trans_add_bh(rgd->rd_gl, bh, 1);
989 gfs2_rgrp_out(rgd, bh->b_data); 1096 gfs2_rgrp_out(rgd, bh->b_data);
1097 gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, bh->b_data);
990 gfs2_trans_end(sdp); 1098 gfs2_trans_end(sdp);
991 } 1099 }
992 } 1100 }
@@ -1116,6 +1224,9 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1116 int error, rg_locked, flags = LM_FLAG_TRY; 1224 int error, rg_locked, flags = LM_FLAG_TRY;
1117 int loops = 0; 1225 int loops = 0;
1118 1226
1227 if (sdp->sd_args.ar_rgrplvb)
1228 flags |= GL_SKIP;
1229
1119 if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal)) 1230 if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal))
1120 rgd = begin = ip->i_rgd; 1231 rgd = begin = ip->i_rgd;
1121 else 1232 else
@@ -1133,22 +1244,34 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1133 } else { 1244 } else {
1134 error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 1245 error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE,
1135 flags, &rs->rs_rgd_gh); 1246 flags, &rs->rs_rgd_gh);
1247 if (!error && sdp->sd_args.ar_rgrplvb) {
1248 error = update_rgrp_lvb(rgd);
1249 if (error) {
1250 gfs2_glock_dq_uninit(&rs->rs_rgd_gh);
1251 return error;
1252 }
1253 }
1136 } 1254 }
1137 switch (error) { 1255 switch (error) {
1138 case 0: 1256 case 0:
1139 if (try_rgrp_fit(rgd, ip)) { 1257 if (try_rgrp_fit(rgd, ip)) {
1258 if (sdp->sd_args.ar_rgrplvb)
1259 gfs2_rgrp_bh_get(rgd);
1140 ip->i_rgd = rgd; 1260 ip->i_rgd = rgd;
1141 return 0; 1261 return 0;
1142 } 1262 }
1143 if (rgd->rd_flags & GFS2_RDF_CHECK) 1263 if (rgd->rd_flags & GFS2_RDF_CHECK) {
1264 if (sdp->sd_args.ar_rgrplvb)
1265 gfs2_rgrp_bh_get(rgd);
1144 try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); 1266 try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr);
1267 }
1145 if (!rg_locked) 1268 if (!rg_locked)
1146 gfs2_glock_dq_uninit(&rs->rs_rgd_gh); 1269 gfs2_glock_dq_uninit(&rs->rs_rgd_gh);
1147 /* fall through */ 1270 /* fall through */
1148 case GLR_TRYFAILED: 1271 case GLR_TRYFAILED:
1149 rgd = gfs2_rgrpd_get_next(rgd); 1272 rgd = gfs2_rgrpd_get_next(rgd);
1150 if (rgd == begin) { 1273 if (rgd == begin) {
1151 flags = 0; 1274 flags &= ~LM_FLAG_TRY;
1152 loops++; 1275 loops++;
1153 } 1276 }
1154 break; 1277 break;
@@ -1529,6 +1652,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
1529 1652
1530 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); 1653 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
1531 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); 1654 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
1655 gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);
1532 1656
1533 gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0); 1657 gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0);
1534 if (dinode) 1658 if (dinode)
@@ -1575,6 +1699,7 @@ void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta)
1575 rgd->rd_flags &= ~GFS2_RGF_TRIMMED; 1699 rgd->rd_flags &= ~GFS2_RGF_TRIMMED;
1576 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); 1700 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
1577 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); 1701 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
1702 gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);
1578 1703
1579 /* Directories keep their data in the metadata address space */ 1704 /* Directories keep their data in the metadata address space */
1580 if (meta || ip->i_depth) 1705 if (meta || ip->i_depth)
@@ -1611,6 +1736,8 @@ void gfs2_unlink_di(struct inode *inode)
1611 trace_gfs2_block_alloc(ip, rgd, blkno, 1, GFS2_BLKST_UNLINKED); 1736 trace_gfs2_block_alloc(ip, rgd, blkno, 1, GFS2_BLKST_UNLINKED);
1612 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); 1737 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
1613 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); 1738 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
1739 gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);
1740 update_rgrp_lvb_unlinked(rgd, 1);
1614} 1741}
1615 1742
1616static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno) 1743static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
@@ -1630,6 +1757,8 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
1630 1757
1631 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); 1758 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
1632 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); 1759 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
1760 gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);
1761 update_rgrp_lvb_unlinked(rgd, -1);
1633 1762
1634 gfs2_statfs_change(sdp, 0, +1, -1); 1763 gfs2_statfs_change(sdp, 0, +1, -1);
1635} 1764}
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 81fc76264ed..788068758f3 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -78,6 +78,8 @@ enum {
78 Opt_quota_quantum, 78 Opt_quota_quantum,
79 Opt_barrier, 79 Opt_barrier,
80 Opt_nobarrier, 80 Opt_nobarrier,
81 Opt_rgrplvb,
82 Opt_norgrplvb,
81 Opt_error, 83 Opt_error,
82}; 84};
83 85
@@ -115,6 +117,8 @@ static const match_table_t tokens = {
115 {Opt_quota_quantum, "quota_quantum=%d"}, 117 {Opt_quota_quantum, "quota_quantum=%d"},
116 {Opt_barrier, "barrier"}, 118 {Opt_barrier, "barrier"},
117 {Opt_nobarrier, "nobarrier"}, 119 {Opt_nobarrier, "nobarrier"},
120 {Opt_rgrplvb, "rgrplvb"},
121 {Opt_norgrplvb, "norgrplvb"},
118 {Opt_error, NULL} 122 {Opt_error, NULL}
119}; 123};
120 124
@@ -267,6 +271,12 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
267 case Opt_nobarrier: 271 case Opt_nobarrier:
268 args->ar_nobarrier = 1; 272 args->ar_nobarrier = 1;
269 break; 273 break;
274 case Opt_rgrplvb:
275 args->ar_rgrplvb = 1;
276 break;
277 case Opt_norgrplvb:
278 args->ar_rgrplvb = 0;
279 break;
270 case Opt_error: 280 case Opt_error:
271 default: 281 default:
272 printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o); 282 printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o);
@@ -1379,6 +1389,8 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root)
1379 seq_printf(s, ",nobarrier"); 1389 seq_printf(s, ",nobarrier");
1380 if (test_bit(SDF_DEMOTE, &sdp->sd_flags)) 1390 if (test_bit(SDF_DEMOTE, &sdp->sd_flags))
1381 seq_printf(s, ",demote_interface_used"); 1391 seq_printf(s, ",demote_interface_used");
1392 if (args->ar_rgrplvb)
1393 seq_printf(s, ",rgrplvb");
1382 return 0; 1394 return 0;
1383} 1395}
1384 1396
diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h
index e8ccf6ff3b4..b2de1f9a88d 100644
--- a/include/linux/gfs2_ondisk.h
+++ b/include/linux/gfs2_ondisk.h
@@ -170,6 +170,16 @@ struct gfs2_rindex {
170#define GFS2_RGF_NOALLOC 0x00000008 170#define GFS2_RGF_NOALLOC 0x00000008
171#define GFS2_RGF_TRIMMED 0x00000010 171#define GFS2_RGF_TRIMMED 0x00000010
172 172
173struct gfs2_rgrp_lvb {
174 __be32 rl_magic;
175 __be32 rl_flags;
176 __be32 rl_free;
177 __be32 rl_dinodes;
178 __be64 rl_igeneration;
179 __be32 rl_unlinked;
180 __be32 __pad;
181};
182
173struct gfs2_rgrp { 183struct gfs2_rgrp {
174 struct gfs2_meta_header rg_header; 184 struct gfs2_meta_header rg_header;
175 185