Re: [Cluster-devel] [PATCH dlm/next 8/9] fs: dlm: check on dlm header size

2021-02-05 Thread Alexander Ahring Oder Aring
Hi,

On Thu, Feb 4, 2021 at 4:51 PM Alexander Aring  wrote:
>
> This patch adds checks for the dlm header size that the parsing loop
> will not stop on messages which are dlm header only and rejects msglen
> field of the dlm header which are less than dlm header size. A msglen
> field cannot be less than the dlm header size because the field is
> inclusive header lengths.
>
> Signed-off-by: Alexander Aring 
> ---
>  fs/dlm/midcomms.c | 9 +
>  1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c
> index fde3a6afe4be..7cda8e4be6fc 100644
> --- a/fs/dlm/midcomms.c
> +++ b/fs/dlm/midcomms.c
> @@ -42,16 +42,17 @@ int dlm_process_incoming_buffer(int nodeid, unsigned char 
> *buf, int len)
> uint16_t msglen;
> int ret = 0;
>
> -   while (len >= sizeof(struct dlm_header)) {
> +   while (len > sizeof(struct dlm_header)) {

I am sorry, I fixed that in 4798cbbfbd00c498339bdcf4cc2429f53eb374ec
("fs: dlm: rework receive handling") already, the correct condition is
">=".
I will send a v2 for this one. Took me some time to debug this "again"
if it's ">" then sometimes ACK messages don't get parsed and I get
hangs at connection termination because ACK messages are only
dlm_header size long.

- Alex



Re: [Cluster-devel] [PATCH 1/2] gfs2: Enable rgrplvb for sb_fs_format 1802

2021-02-05 Thread Bob Peterson
- Original Message -
> Turn on rgrplvb by default for sb_fs_format > 1801.
> 
> Mount options still have to override this so a new args field to
> differentiate between 'off' and 'not specified' is added, and the new
> default is applied only when it's not specified.
> 
> Signed-off-by: Andrew Price 
> ---
>  fs/gfs2/incore.h |  1 +
>  fs/gfs2/ops_fstype.c | 13 ++---
>  fs/gfs2/super.h  |  4 
>  3 files changed, 15 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
> index 8e1ab8ed4abc..ac4d5e619ecf 100644
> --- a/fs/gfs2/incore.h
> +++ b/fs/gfs2/incore.h
> @@ -585,6 +585,7 @@ struct gfs2_args {
>   unsigned int ar_errors:2;   /* errors=withdraw | panic */
>   unsigned int ar_nobarrier:1;/* do not send barriers */
>   unsigned int ar_rgrplvb:1;  /* use lvbs for rgrp info */
> + unsigned int ar_got_rgrplvb:1;  /* Was the rgrplvb opt given? */
>   unsigned int ar_loccookie:1;/* use location based readdir
>  cookies */
>   s32 ar_commit;  /* Commit interval */
> diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
> index 61fce59cb4d3..52fe78378faa 100644
> --- a/fs/gfs2/ops_fstype.c
> +++ b/fs/gfs2/ops_fstype.c
> @@ -171,7 +171,8 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int
> silent)
>   return -EINVAL;
>   }
>  
> - if (sb->sb_fs_format != GFS2_FORMAT_FS ||
> + if (sb->sb_fs_format < GFS2_FS_FORMAT_MIN ||
> + sb->sb_fs_format > GFS2_FS_FORMAT_MAX ||
>   sb->sb_multihost_format != GFS2_FORMAT_MULTI) {
>   fs_warn(sdp, "Unknown on-disk format, unable to mount\n");
>   return -EINVAL;
> @@ -1032,13 +1033,14 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int
> silent)
>   }
>  
>   if (lm->lm_mount == NULL) {
> - fs_info(sdp, "Now mounting FS...\n");
> + fs_info(sdp, "Now mounting FS (format %u)...\n", 
> sdp->sd_sb.sb_fs_format);
>   complete_all(>sd_locking_init);
>   return 0;
>   }
>   ret = lm->lm_mount(sdp, table);
>   if (ret == 0)
> - fs_info(sdp, "Joined cluster. Now mounting FS...\n");
> + fs_info(sdp, "Joined cluster. Now mounting FS (format %u)...\n",
> + sdp->sd_sb.sb_fs_format);
>   complete_all(>sd_locking_init);
>   return ret;
>  }
> @@ -1156,6 +1158,10 @@ static int gfs2_fill_super(struct super_block *sb,
> struct fs_context *fc)
>   if (error)
>   goto fail_locking;
>  
> + /* Turn rgrplvb on by default if fs format is recent enough */
> + if (!sdp->sd_args.ar_got_rgrplvb && sdp->sd_sb.sb_fs_format > 1801)
> + sdp->sd_args.ar_rgrplvb = 1;
> +
>   error = wait_on_journal(sdp);
>   if (error)
>   goto fail_sb;
> @@ -1456,6 +1462,7 @@ static int gfs2_parse_param(struct fs_context *fc,
> struct fs_parameter *param)
>   break;
>   case Opt_rgrplvb:
>   args->ar_rgrplvb = result.boolean;
> + args->ar_got_rgrplvb = 1;
>   break;
>   case Opt_loccookie:
>   args->ar_loccookie = result.boolean;
> diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
> index c9fb2a654181..977079693bdc 100644
> --- a/fs/gfs2/super.h
> +++ b/fs/gfs2/super.h
> @@ -11,6 +11,10 @@
>  #include 
>  #include "incore.h"
>  
> +/* Supported fs format version range */
> +#define GFS2_FS_FORMAT_MIN (1801)
> +#define GFS2_FS_FORMAT_MAX (1802)
> +
>  extern void gfs2_lm_unmount(struct gfs2_sbd *sdp);
>  
>  static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
> --
> 2.29.2
> 
> 
Looks good. Thanks, Andy!
Reviewed-by: Bob Peterson 

Bob Peterson



Re: [Cluster-devel] [PATCH 2/2] gfs2: Add trusted xattr support

2021-02-05 Thread Bob Peterson
Hi,

Comments below.

- Original Message -
> From: Andreas Gruenbacher 
> 
> Add support for an additional filesystem version (sb_fs_format = 1802).
> When a filesystem with the new version is mounted, the filesystem
> supports "trusted.*" xattrs.
> 
> In addition, version 1802 filesystems implement a form of forward
> compatibility for xattrs: when xattrs with an unknown prefix (ea_type)
> are found on a version 1802 filesystem, those attributes are not shown
> by listxattr, and they are not accessible by getxattr, setxattr, or
> removexattr.
> 
> This mechanism might turn out to be what we need in the future, but if
> not, we can always bump the filesystem version and break compatibility
> instead.
> 
> Signed-off-by: Andrew Price 

If this is from Andreas, it should have his Signed-off-by:

> ---
>  fs/gfs2/ops_fstype.c | 14 +-
>  fs/gfs2/super.h  |  4 ++-
>  fs/gfs2/xattr.c  | 48 +---
>  include/uapi/linux/gfs2_ondisk.h |  5 ++--
>  4 files changed, 63 insertions(+), 8 deletions(-)
> 
> diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
> index 52fe78378faa..64ad19bb978c 100644
> --- a/fs/gfs2/ops_fstype.c
> +++ b/fs/gfs2/ops_fstype.c
> @@ -489,6 +489,19 @@ static int init_sb(struct gfs2_sbd *sdp, int silent)
>   goto out;
>   }
>  
> + switch(sdp->sd_sb.sb_fs_format) {
> + case GFS2_FS_FORMAT_MAX:
> + sb->s_xattr = gfs2_xattr_handlers_max;
> + break;
> +
> + case GFS2_FS_FORMAT_MIN:
> + sb->s_xattr = gfs2_xattr_handlers_min;
> + break;
> +
> + default:
> + BUG();
> + }
> +
>   /* Set up the buffer cache and SB for real */
>   if (sdp->sd_sb.sb_bsize < bdev_logical_block_size(sb->s_bdev)) {
>   ret = -EINVAL;
> @@ -1109,7 +1122,6 @@ static int gfs2_fill_super(struct super_block *sb,
> struct fs_context *fc)
>   sb->s_op = _super_ops;
>   sb->s_d_op = _dops;
>   sb->s_export_op = _export_ops;
> - sb->s_xattr = gfs2_xattr_handlers;
>   sb->s_qcop = _quotactl_ops;
>   sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
>   sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
> diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
> index 977079693bdc..08e502dec7ec 100644
> --- a/fs/gfs2/super.h
> +++ b/fs/gfs2/super.h
> @@ -58,7 +58,9 @@ extern struct file_system_type gfs2meta_fs_type;
>  extern const struct export_operations gfs2_export_ops;
>  extern const struct super_operations gfs2_super_ops;
>  extern const struct dentry_operations gfs2_dops;
> -extern const struct xattr_handler *gfs2_xattr_handlers[];
> +
> +extern const struct xattr_handler *gfs2_xattr_handlers_max[];
> +extern const struct xattr_handler **gfs2_xattr_handlers_min;
>  
>  #endif /* __SUPER_DOT_H__ */
>  
> diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
> index 9d7667bc4292..a860a144f3d4 100644
> --- a/fs/gfs2/xattr.c
> +++ b/fs/gfs2/xattr.c
> @@ -70,6 +70,20 @@ static int ea_check_size(struct gfs2_sbd *sdp, unsigned
> int nsize, size_t dsize)
>   return 0;
>  }
>  
> +bool gfs2_eatype_valid(struct gfs2_sbd *sdp, u8 type)

This should be "static bool".

> +{
> + switch(sdp->sd_sb.sb_fs_format) {
> + case GFS2_FS_FORMAT_MAX:
> + return true;
> +
> + case GFS2_FS_FORMAT_MIN:
> + return type <= GFS2_EATYPE_SECURITY;
> +
> + default:
> + return false;
> + }
> +}
> +
>  typedef int (*ea_call_t) (struct gfs2_inode *ip, struct buffer_head *bh,
> struct gfs2_ea_header *ea,
> struct gfs2_ea_header *prev, void *private);
> @@ -77,6 +91,7 @@ typedef int (*ea_call_t) (struct gfs2_inode *ip, struct
> buffer_head *bh,
>  static int ea_foreach_i(struct gfs2_inode *ip, struct buffer_head *bh,
>   ea_call_t ea_call, void *data)
>  {
> + struct gfs2_sbd *sdp = GFS2_SB(>i_inode);
>   struct gfs2_ea_header *ea, *prev = NULL;
>   int error = 0;
>  
> @@ -89,9 +104,8 @@ static int ea_foreach_i(struct gfs2_inode *ip, struct
> buffer_head *bh,
>   if (!(bh->b_data <= (char *)ea && (char *)GFS2_EA2NEXT(ea) <=
> bh->b_data + bh->b_size))
>   goto fail;
> - if (!GFS2_EATYPE_VALID(ea->ea_type))
> + if (!gfs2_eatype_valid(sdp, ea->ea_type))
>   goto fail;
> -
>   error = ea_call(ip, bh, ea, prev, data);
>   if (error)
>   return error;
> @@ -344,6 +358,7 @@ static int ea_list_i(struct gfs2_inode *ip, struct
> buffer_head *bh,
>struct gfs2_ea_header *ea, struct gfs2_ea_header *prev,
>void *private)
>  {
> + struct gfs2_sbd *sdp = GFS2_SB(>i_inode);
>   struct ea_list *ei = private;
>   struct gfs2_ea_request *er = ei->ei_er;
>   unsigned int ea_size;
> @@ -353,6 +368,8 @@ static int 

[Cluster-devel] [gfs2 PATCH] gfs2: Don't skip dlm unlock if glock has an lvb

2021-02-05 Thread Bob Peterson
Patch fb6791d100d1bba20b5cdbc4912e1f7086ec60f8 was designed to allow
gfs2 to unmount quicker by skipping the step where it tells dlm to
unlock glocks in EX with lvbs. This was done because when gfs2 unmounts
a file system, it destroys the dlm lockspace shortly after it destroys
the glocks so it doesn't need to unlock them all: the unlock is implied
when the lockspace is destroyed by dlm.

However, that patch introduced a use-after-free in dlm: as part of its
normal dlm_recoverd process, it can call ls_recovery to recover dead
locks. In so doing, it can call recover_rsbs which calls recover_lvb for
any mastered rsbs. Func recover_lvb runs through the list of lkbs queued
to the given rsb (if the glock is cached but unlocked, it will still be
queued to the lkb, but in NL--Unlocked--mode) and if it has an lvb,
copies it to the rsb, thus trying to preserve the lkb. However, when
gfs2 skips the dlm unlock step, it frees the glock and its lvb, which
means dlm's function recover_lvb references the now freed lvb pointer,
copying the freed lvb memory to the rsb.

This patch changes the check in gdlm_put_lock so that it calls dlm_unlock
for all glocks that contain an lvb pointer.

Signed-off-by: Bob Peterson 
Fixes: fb6791d100d1 "GFS2: skip dlm_unlock calls in unmount"
---
 fs/gfs2/lock_dlm.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 9f2b5609f225..153272f82984 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -284,7 +284,6 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
 {
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct lm_lockstruct *ls = >sd_lockstruct;
-   int lvb_needs_unlock = 0;
int error;
 
if (gl->gl_lksb.sb_lkid == 0) {
@@ -297,13 +296,10 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT);
gfs2_update_request_times(gl);
 
-   /* don't want to skip dlm_unlock writing the lvb when lock is ex */
-
-   if (gl->gl_lksb.sb_lvbptr && (gl->gl_state == LM_ST_EXCLUSIVE))
-   lvb_needs_unlock = 1;
+   /* don't want to skip dlm_unlock writing the lvb when lock has one */
 
if (test_bit(SDF_SKIP_DLM_UNLOCK, >sd_flags) &&
-   !lvb_needs_unlock) {
+   !gl->gl_lksb.sb_lvbptr) {
gfs2_glock_free(gl);
return;
}



[Cluster-devel] [PATCH] gfs2: Lock imbalance on error path in gfs2_recover_one

2021-02-05 Thread Andreas Gruenbacher
In gfs2_recover_one, fix a sd_log_flush_lock imbalance when a recovery
pass fails.

Fixes: c9ebc4b73799 ("gfs2: allow journal replay to hold sd_log_flush_lock")
Cc: sta...@vger.kernel.org # v5.7+
Signed-off-by: Andreas Gruenbacher 
---
 fs/gfs2/recovery.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index a3eae2c76b70..f15f9b86e8a7 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -511,8 +511,10 @@ static void gfs2_recover_one(struct gfs2_jdesc *jd)
error = foreach_descriptor(jd, head.lh_tail,
   head.lh_blkno, pass);
lops_after_scan(jd, error, pass);
-   if (error)
+   if (error) {
+   up_read(>sd_log_flush_lock);
goto fail_gunlock_thaw;
+   }
}
 
recover_local_statfs(jd, );
-- 
2.26.2



[Cluster-devel] [PATCH 0/2] gfs2: fs format 1802 features

2021-02-05 Thread Andrew Price
These patches add trusted.* xattr support and switch on rgrplvb by default when 
the sb_fs_format field is greater than 1801 (the current version). Filesystems 
with an 1802 fs format can currently be created with gfs2-utils.git/master 
using -o format=1802 but that will become the default once this has had some 
soak time.

I've tested the patches with several rounds of xfstests single-node, and in a 
clustered configuration with a lot of file operations happening on each node, 
including filling the fs to force resource group contention.

Andreas Gruenbacher (1):
  gfs2: Add trusted xattr support

Andrew Price (1):
  gfs2: Enable rgrplvb for sb_fs_format 1802

 fs/gfs2/incore.h |  1 +
 fs/gfs2/ops_fstype.c | 27 +++---
 fs/gfs2/super.h  |  8 +-
 fs/gfs2/xattr.c  | 48 +---
 include/uapi/linux/gfs2_ondisk.h |  5 ++--
 5 files changed, 78 insertions(+), 11 deletions(-)

-- 
2.29.2



[Cluster-devel] [PATCH 2/2] gfs2: Add trusted xattr support

2021-02-05 Thread Andrew Price
From: Andreas Gruenbacher 

Add support for an additional filesystem version (sb_fs_format = 1802).
When a filesystem with the new version is mounted, the filesystem
supports "trusted.*" xattrs.

In addition, version 1802 filesystems implement a form of forward
compatibility for xattrs: when xattrs with an unknown prefix (ea_type)
are found on a version 1802 filesystem, those attributes are not shown
by listxattr, and they are not accessible by getxattr, setxattr, or
removexattr.

This mechanism might turn out to be what we need in the future, but if
not, we can always bump the filesystem version and break compatibility
instead.

Signed-off-by: Andrew Price 
---
 fs/gfs2/ops_fstype.c | 14 +-
 fs/gfs2/super.h  |  4 ++-
 fs/gfs2/xattr.c  | 48 +---
 include/uapi/linux/gfs2_ondisk.h |  5 ++--
 4 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 52fe78378faa..64ad19bb978c 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -489,6 +489,19 @@ static int init_sb(struct gfs2_sbd *sdp, int silent)
goto out;
}
 
+   switch(sdp->sd_sb.sb_fs_format) {
+   case GFS2_FS_FORMAT_MAX:
+   sb->s_xattr = gfs2_xattr_handlers_max;
+   break;
+
+   case GFS2_FS_FORMAT_MIN:
+   sb->s_xattr = gfs2_xattr_handlers_min;
+   break;
+
+   default:
+   BUG();
+   }
+
/* Set up the buffer cache and SB for real */
if (sdp->sd_sb.sb_bsize < bdev_logical_block_size(sb->s_bdev)) {
ret = -EINVAL;
@@ -1109,7 +1122,6 @@ static int gfs2_fill_super(struct super_block *sb, struct 
fs_context *fc)
sb->s_op = _super_ops;
sb->s_d_op = _dops;
sb->s_export_op = _export_ops;
-   sb->s_xattr = gfs2_xattr_handlers;
sb->s_qcop = _quotactl_ops;
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
index 977079693bdc..08e502dec7ec 100644
--- a/fs/gfs2/super.h
+++ b/fs/gfs2/super.h
@@ -58,7 +58,9 @@ extern struct file_system_type gfs2meta_fs_type;
 extern const struct export_operations gfs2_export_ops;
 extern const struct super_operations gfs2_super_ops;
 extern const struct dentry_operations gfs2_dops;
-extern const struct xattr_handler *gfs2_xattr_handlers[];
+
+extern const struct xattr_handler *gfs2_xattr_handlers_max[];
+extern const struct xattr_handler **gfs2_xattr_handlers_min;
 
 #endif /* __SUPER_DOT_H__ */
 
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 9d7667bc4292..a860a144f3d4 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -70,6 +70,20 @@ static int ea_check_size(struct gfs2_sbd *sdp, unsigned int 
nsize, size_t dsize)
return 0;
 }
 
+bool gfs2_eatype_valid(struct gfs2_sbd *sdp, u8 type)
+{
+   switch(sdp->sd_sb.sb_fs_format) {
+   case GFS2_FS_FORMAT_MAX:
+   return true;
+
+   case GFS2_FS_FORMAT_MIN:
+   return type <= GFS2_EATYPE_SECURITY;
+
+   default:
+   return false;
+   }
+}
+
 typedef int (*ea_call_t) (struct gfs2_inode *ip, struct buffer_head *bh,
  struct gfs2_ea_header *ea,
  struct gfs2_ea_header *prev, void *private);
@@ -77,6 +91,7 @@ typedef int (*ea_call_t) (struct gfs2_inode *ip, struct 
buffer_head *bh,
 static int ea_foreach_i(struct gfs2_inode *ip, struct buffer_head *bh,
ea_call_t ea_call, void *data)
 {
+   struct gfs2_sbd *sdp = GFS2_SB(>i_inode);
struct gfs2_ea_header *ea, *prev = NULL;
int error = 0;
 
@@ -89,9 +104,8 @@ static int ea_foreach_i(struct gfs2_inode *ip, struct 
buffer_head *bh,
if (!(bh->b_data <= (char *)ea && (char *)GFS2_EA2NEXT(ea) <=
  bh->b_data + bh->b_size))
goto fail;
-   if (!GFS2_EATYPE_VALID(ea->ea_type))
+   if (!gfs2_eatype_valid(sdp, ea->ea_type))
goto fail;
-
error = ea_call(ip, bh, ea, prev, data);
if (error)
return error;
@@ -344,6 +358,7 @@ static int ea_list_i(struct gfs2_inode *ip, struct 
buffer_head *bh,
 struct gfs2_ea_header *ea, struct gfs2_ea_header *prev,
 void *private)
 {
+   struct gfs2_sbd *sdp = GFS2_SB(>i_inode);
struct ea_list *ei = private;
struct gfs2_ea_request *er = ei->ei_er;
unsigned int ea_size;
@@ -353,6 +368,8 @@ static int ea_list_i(struct gfs2_inode *ip, struct 
buffer_head *bh,
if (ea->ea_type == GFS2_EATYPE_UNUSED)
return 0;
 
+   BUG_ON(ea->ea_type > GFS2_EATYPE_SECURITY &&
+  sdp->sd_sb.sb_fs_format == GFS2_FS_FORMAT_MIN);
switch (ea->ea_type) {
case 

[Cluster-devel] [PATCH 1/2] gfs2: Enable rgrplvb for sb_fs_format 1802

2021-02-05 Thread Andrew Price
Turn on rgrplvb by default for sb_fs_format > 1801.

Mount options still have to override this so a new args field to
differentiate between 'off' and 'not specified' is added, and the new
default is applied only when it's not specified.

Signed-off-by: Andrew Price 
---
 fs/gfs2/incore.h |  1 +
 fs/gfs2/ops_fstype.c | 13 ++---
 fs/gfs2/super.h  |  4 
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 8e1ab8ed4abc..ac4d5e619ecf 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -585,6 +585,7 @@ struct gfs2_args {
unsigned int ar_errors:2;   /* errors=withdraw | panic */
unsigned int ar_nobarrier:1;/* do not send barriers */
unsigned int ar_rgrplvb:1;  /* use lvbs for rgrp info */
+   unsigned int ar_got_rgrplvb:1;  /* Was the rgrplvb opt given? */
unsigned int ar_loccookie:1;/* use location based readdir
   cookies */
s32 ar_commit;  /* Commit interval */
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 61fce59cb4d3..52fe78378faa 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -171,7 +171,8 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent)
return -EINVAL;
}
 
-   if (sb->sb_fs_format != GFS2_FORMAT_FS ||
+   if (sb->sb_fs_format < GFS2_FS_FORMAT_MIN ||
+   sb->sb_fs_format > GFS2_FS_FORMAT_MAX ||
sb->sb_multihost_format != GFS2_FORMAT_MULTI) {
fs_warn(sdp, "Unknown on-disk format, unable to mount\n");
return -EINVAL;
@@ -1032,13 +1033,14 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int 
silent)
}
 
if (lm->lm_mount == NULL) {
-   fs_info(sdp, "Now mounting FS...\n");
+   fs_info(sdp, "Now mounting FS (format %u)...\n", 
sdp->sd_sb.sb_fs_format);
complete_all(>sd_locking_init);
return 0;
}
ret = lm->lm_mount(sdp, table);
if (ret == 0)
-   fs_info(sdp, "Joined cluster. Now mounting FS...\n");
+   fs_info(sdp, "Joined cluster. Now mounting FS (format %u)...\n",
+   sdp->sd_sb.sb_fs_format);
complete_all(>sd_locking_init);
return ret;
 }
@@ -1156,6 +1158,10 @@ static int gfs2_fill_super(struct super_block *sb, 
struct fs_context *fc)
if (error)
goto fail_locking;
 
+   /* Turn rgrplvb on by default if fs format is recent enough */
+   if (!sdp->sd_args.ar_got_rgrplvb && sdp->sd_sb.sb_fs_format > 1801)
+   sdp->sd_args.ar_rgrplvb = 1;
+
error = wait_on_journal(sdp);
if (error)
goto fail_sb;
@@ -1456,6 +1462,7 @@ static int gfs2_parse_param(struct fs_context *fc, struct 
fs_parameter *param)
break;
case Opt_rgrplvb:
args->ar_rgrplvb = result.boolean;
+   args->ar_got_rgrplvb = 1;
break;
case Opt_loccookie:
args->ar_loccookie = result.boolean;
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
index c9fb2a654181..977079693bdc 100644
--- a/fs/gfs2/super.h
+++ b/fs/gfs2/super.h
@@ -11,6 +11,10 @@
 #include 
 #include "incore.h"
 
+/* Supported fs format version range */
+#define GFS2_FS_FORMAT_MIN (1801)
+#define GFS2_FS_FORMAT_MAX (1802)
+
 extern void gfs2_lm_unmount(struct gfs2_sbd *sdp);
 
 static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
-- 
2.29.2