Excellent - looks really good :-)

Steve.


On 07/12/17 11:53, Andrew Price wrote:
This new field in the resource group headers is set on write and checked
on read so that fsck.gfs2 now considers a resource group with a bad,
non-zero crc to be corrupted. gfs2_grow, gfs2_edit, and mkfs.gfs2 all
now support the rg_crc field, including save/restoremeta.

Signed-off-by: Andrew Price <[email protected]>
---
  gfs2/libgfs2/libgfs2.h   |  2 ++
  gfs2/libgfs2/meta.c      |  1 +
  gfs2/libgfs2/ondisk.c    |  7 +++++--
  gfs2/libgfs2/rgrp.c      | 54 +++++++++++++++++++++++++++++++++++++++++++-----
  tests/rgrifieldscheck.sh |  3 +++
  5 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 50dc3f56..5309e6d6 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -667,6 +667,8 @@ extern int clean_journal(struct gfs2_inode *ip, struct 
gfs2_log_header *head);
  /* rgrp.c */
  extern int gfs2_compute_bitstructs(const uint32_t bsize, struct rgrp_tree 
*rgd);
  extern struct rgrp_tree *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk);
+extern int lgfs2_rgrp_crc_check(const struct gfs2_rgrp *rg, char *buf);
+extern void lgfs2_rgrp_crc_set(char *buf);
  extern uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_tree *rgd);
  extern void gfs2_rgrp_relse(struct rgrp_tree *rgd);
  extern struct rgrp_tree *rgrp_insert(struct osi_root *rgtree,
diff --git a/gfs2/libgfs2/meta.c b/gfs2/libgfs2/meta.c
index 1b771f30..82c8c6be 100644
--- a/gfs2/libgfs2/meta.c
+++ b/gfs2/libgfs2/meta.c
@@ -211,6 +211,7 @@ F(rg_igeneration)
  FP(rg_data0, .points_to = ANY_GFS2_BLOCK|(1 << LGFS2_MT_FREE))
  F(rg_data, .flags = LGFS2_MFF_FSBLOCKS)
  F(rg_bitbytes, .flags = LGFS2_MFF_BYTES)
+F(rg_crc, .flags = LGFS2_MFF_CHECK)
  #endif
  RF(rg_reserved)
  };
diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c
index fd25a860..dfb99d14 100644
--- a/gfs2/libgfs2/ondisk.c
+++ b/gfs2/libgfs2/ondisk.c
@@ -237,7 +237,8 @@ void gfs2_rgrp_in(struct gfs2_rgrp *rg, struct 
gfs2_buffer_head *bh)
        CPIN_64(rg, str, rg_data0);
        CPIN_32(rg, str, rg_data);
        CPIN_32(rg, str, rg_bitbytes);
-       CPIN_08(rg, str, rg_reserved, 64);
+       CPIN_32(rg, str, rg_crc);
+       CPIN_08(rg, str, rg_reserved, 60);
  #else
        CPIN_08(rg, str, rg_reserved, 80);
  #endif
@@ -261,7 +262,8 @@ void gfs2_rgrp_out(const struct gfs2_rgrp *rg, char *buf)
        CPOUT_64(rg, str, rg_data0);
        CPOUT_32(rg, str, rg_data);
        CPOUT_32(rg, str, rg_bitbytes);
-       CPOUT_08(rg, str, rg_reserved, 64);
+       CPOUT_08(rg, str, rg_reserved, 60);
+       lgfs2_rgrp_crc_set(buf);
  #else
        CPOUT_08(rg, str, rg_reserved, 80);
  #endif
@@ -289,6 +291,7 @@ void gfs2_rgrp_print(const struct gfs2_rgrp *rg)
        pv(rg, rg_data0, "%llu", "0x%llx");
        pv(rg, rg_data, "%u", "0x%x");
        pv(rg, rg_bitbytes, "%u", "0x%x");
+       pv(rg, rg_crc, "%u", "0x%x");
  #endif
  }
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index 17178bd9..03861d14 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -158,6 +158,42 @@ void lgfs2_rgrp_bitbuf_free(lgfs2_rgrp_t rg)
  }
/**
+ * Check a resource group's crc
+ * Returns 0 on success, non-zero if crc is bad
+ */
+int lgfs2_rgrp_crc_check(const struct gfs2_rgrp *rg, char *buf)
+{
+       int ret = 0;
+#ifdef GFS2_HAS_RG_RI_FIELDS
+       uint32_t crc = rg->rg_crc;
+
+       if (crc == 0)
+               return 0;
+
+       ((struct gfs2_rgrp *)buf)->rg_crc = 0;
+       if (crc != gfs2_disk_hash(buf, sizeof(struct gfs2_rgrp)))
+               ret = 1;
+       ((struct gfs2_rgrp *)buf)->rg_crc = cpu_to_be32(crc);
+#endif
+       return ret;
+}
+
+/**
+ * Set the crc of an on-disk resource group
+ */
+void lgfs2_rgrp_crc_set(char *buf)
+{
+#ifdef GFS2_HAS_RG_RI_FIELDS
+       struct gfs2_rgrp *rg = (struct gfs2_rgrp *)buf;
+       uint32_t crc;
+
+       rg->rg_crc = 0;
+       crc = gfs2_disk_hash(buf, sizeof(struct gfs2_rgrp));
+       rg->rg_crc = cpu_to_be32(crc);
+#endif
+}
+
+/**
   * gfs2_rgrp_read - read in the resource group information from disk.
   * @rgd - resource group structure
   * returns: 0 if no error, otherwise the block number that failed
@@ -194,11 +230,18 @@ uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct 
rgrp_tree *rgd)
                        return rgd->ri.ri_addr + err;
                }
        }
-       if (x > 0) {
-               if (sdp->gfs1)
-                       gfs_rgrp_in((struct gfs_rgrp *)&rgd->rg, 
rgd->bits[0].bi_bh);
-               else
-                       gfs2_rgrp_in(&rgd->rg, rgd->bits[0].bi_bh);
+       if (x <= 0) {
+               free(bhs);
+               return 0;
+       }
+       if (sdp->gfs1)
+               gfs_rgrp_in((struct gfs_rgrp *)&rgd->rg, rgd->bits[0].bi_bh);
+       else {
+               gfs2_rgrp_in(&rgd->rg, rgd->bits[0].bi_bh);
+               if (lgfs2_rgrp_crc_check(&rgd->rg, rgd->bits[0].bi_bh->b_data)) 
{
+                       free(bhs);
+                       return rgd->ri.ri_addr;
+               }
        }
        free(bhs);
        return 0;
@@ -623,6 +666,7 @@ lgfs2_rgrp_t lgfs2_rgrps_append(lgfs2_rgrps_t rgs, struct 
gfs2_rindex *entry, ui
        rg->rg.rg_data0 = rg->ri.ri_data0;
        rg->rg.rg_data = rg->ri.ri_data;
        rg->rg.rg_bitbytes = rg->ri.ri_bitbytes;
+       rg->rg.rg_crc = 0;
  #endif
        compute_bitmaps(rg, rgs->sdp->bsize);
        rg->rgrps = rgs;
diff --git a/tests/rgrifieldscheck.sh b/tests/rgrifieldscheck.sh
index c99470a9..85f6408e 100755
--- a/tests/rgrifieldscheck.sh
+++ b/tests/rgrifieldscheck.sh
@@ -1,6 +1,9 @@
  #!/bin/sh
  dev=$1
  i=0
+gfs2_edit -p rg 0 $dev | grep rg_data0 > /dev/null 2>&1
+# New fields not present in /usr/include/linux/gfs2_ondisk.h
+test $? = 0 || exit 0
  gfs2_edit -p rindex $dev | while read field rival unused
  do
        test $field = ri_data0 -o $field = ri_data -o $field = ri_bitbytes || 
continue

Reply via email to