[Cluster-devel] [GFS2 PATCH] [v2] GFS2: Introduce new gfs2_log_header_v2

Bob Peterson rpeterso at redhat.com
Fri Dec 8 15:28:47 UTC 2017


Here is a version 2 replacement for this patch, with improvements.
---
This patch adds a new structure called gfs2_log_header_v2 which is
used to store expanded fields into previously unused areas of the
log headers. Some of these are used for debug purposes so we can
backtrack when problems occur. Others are reserved for future
expansion.

This is based on a prototype patch from Steve Whitehouse.

Signed-off-by: Bob Peterson <rpeterso at redhat.com>
---
 fs/gfs2/log.c                    | 26 +++++++++++++++++++++---
 fs/gfs2/lops.c                   | 43 +++++++++++++++++++++++++++++++++++++---
 fs/gfs2/lops.h                   |  1 +
 include/uapi/linux/gfs2_ondisk.h | 18 +++++++++++++++++
 4 files changed, 82 insertions(+), 6 deletions(-)

diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index f72c44231406..508b6edefab7 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -656,15 +656,20 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
 
 static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
 {
+	struct gfs2_log_header_v2 *lh2;
 	struct gfs2_log_header *lh;
 	unsigned int tail;
 	u32 hash;
 	int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC;
 	struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
 	enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state);
-	lh = page_address(page);
-	clear_page(lh);
+	struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+	struct timespec64 tv;
 
+	lh2 = page_address(page);
+	clear_page(lh2);
+
+	lh = &lh2->lhv1;
 	gfs2_assert_withdraw(sdp, (state != SFS_FROZEN));
 
 	tail = current_tail(sdp);
@@ -681,6 +686,19 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
 	hash = gfs2_disk_hash(page_address(page), sizeof(struct gfs2_log_header));
 	lh->lh_hash = cpu_to_be32(hash);
 
+	tv = current_kernel_time64();
+	lh2->lh_nsec = cpu_to_be32(tv.tv_nsec);
+	lh2->lh_sec = cpu_to_be64(tv.tv_sec);
+	lh2->lh_jinode = cpu_to_be64(GFS2_I(sdp->sd_jdesc->jd_inode)->i_no_addr);
+	lh2->lh_statfs_addr = cpu_to_be64(GFS2_I(sdp->sd_sc_inode)->i_no_addr);
+	lh2->lh_quota_addr = cpu_to_be64(GFS2_I(sdp->sd_qc_inode)->i_no_addr);
+
+	spin_lock(&sdp->sd_statfs_spin);
+	lh2->lh_local_total = cpu_to_be64(l_sc->sc_total);
+	lh2->lh_local_free = cpu_to_be64(l_sc->sc_free);
+	lh2->lh_local_dinodes = cpu_to_be64(l_sc->sc_dinodes);
+	spin_unlock(&sdp->sd_statfs_spin);
+
 	if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) {
 		gfs2_ordered_wait(sdp);
 		log_flush_wait(sdp);
@@ -688,7 +706,9 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
 	}
 
 	sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
-	gfs2_log_write_page(sdp, page);
+
+	/* Sets both the header address & overall checksum */
+	gfs2_log_write_hdr(sdp, page);
 	gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags);
 	log_flush_wait(sdp);
 
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index c8ff7b7954f0..d592ee7f502d 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -18,6 +18,7 @@
 #include <linux/fs.h>
 #include <linux/list_sort.h>
 
+#include "dir.h"
 #include "gfs2.h"
 #include "incore.h"
 #include "inode.h"
@@ -306,6 +307,25 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno)
 	return gfs2_log_alloc_bio(sdp, blkno);
 }
 
+/**
+ * gfs2_set_log_csum - Set a whole-block checksum for a page
+ * @sb: The superblock
+ * @page: The page to write
+ * @blkno: The device block number we want to write to
+ * 
+ * Set the location of the block to be written and then checksum the block
+ * before writing it.
+ */
+static void gfs2_set_log_csum(struct super_block *sb, struct page *page,
+			      u64 blkno)
+{
+	struct gfs2_log_header_v2 *lh = page_address(page);
+	u32 hash;
+
+	lh->lh_addr = cpu_to_be64(blkno);
+	hash = gfs2_disk_hash(page_address(page), sb->s_blocksize);
+	lh->lh_crc = cpu_to_be32(hash);
+}
 
 /**
  * gfs2_log_write - write to log
@@ -320,7 +340,7 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno)
  */
 
 static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
-			   unsigned size, unsigned offset)
+			   unsigned size, unsigned offset, bool is_hdr)
 {
 	u64 blkno = gfs2_log_bmap(sdp);
 	struct bio *bio;
@@ -334,6 +354,8 @@ static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
 		ret = bio_add_page(bio, page, size, offset);
 		WARN_ON(ret == 0);
 	}
+	if (is_hdr)
+		gfs2_set_log_csum(sdp->sd_vfs, page, blkno);
 }
 
 /**
@@ -348,7 +370,7 @@ static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
 
 static void gfs2_log_write_bh(struct gfs2_sbd *sdp, struct buffer_head *bh)
 {
-	gfs2_log_write(sdp, bh->b_page, bh->b_size, bh_offset(bh));
+	gfs2_log_write(sdp, bh->b_page, bh->b_size, bh_offset(bh), false);
 }
 
 /**
@@ -365,7 +387,22 @@ static void gfs2_log_write_bh(struct gfs2_sbd *sdp, struct buffer_head *bh)
 void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page)
 {
 	struct super_block *sb = sdp->sd_vfs;
-	gfs2_log_write(sdp, page, sb->s_blocksize, 0);
+	gfs2_log_write(sdp, page, sb->s_blocksize, 0, false);
+}
+
+/**
+ * gfs2_log_write_hdr - for writing log headers
+ * @sdp: The superblock
+ * @page: The struct page to be written (containing a log header)
+ *
+ * Same as gfs2_log_write_page except that we set the location of
+ * the block to be written and then checksum the block before
+ * writing it
+ */
+void gfs2_log_write_hdr(struct gfs2_sbd *sdp, struct page *page)
+{
+	struct super_block *sb = sdp->sd_vfs;
+	gfs2_log_write(sdp, page, sb->s_blocksize, 0, true);
 }
 
 static struct page *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type,
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
index e529f536c117..77f3203b477a 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -27,6 +27,7 @@ extern const struct gfs2_log_operations gfs2_databuf_lops;
 
 extern const struct gfs2_log_operations *gfs2_log_ops[];
 extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page);
+extern void gfs2_log_write_hdr(struct gfs2_sbd *sdp, struct page *page);
 extern void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int op, int op_flags);
 extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
 
diff --git a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h
index 5156bad77b47..96d9676ac354 100644
--- a/include/uapi/linux/gfs2_ondisk.h
+++ b/include/uapi/linux/gfs2_ondisk.h
@@ -406,6 +406,24 @@ struct gfs2_log_header {
 	__be32 lh_hash;
 };
 
+struct gfs2_log_header_v2 {
+	struct gfs2_log_header lhv1;
+
+	__be32 lh_crc;		/* crc32 of whole block with this field 0 */
+	__be32 lh_nsec;		/* Nano second time stamp */
+	__be64 lh_sec;		/* Second based time stamp */
+	__be64 lh_addr;		/* Block number of this log header (absolute) */
+	__be64 lh_jinode;	/* Journal inode number */
+	__be64 lh_statfs_addr;	/* Local statfs inode number */
+	__be64 lh_quota_addr;	/* Local quota change inode number */
+
+	/* Statfs local changes (i.e. diff from global statfs) */
+	__be64 lh_local_total;
+	__be64 lh_local_free;
+	__be64 lh_local_dinodes;
+	__be32 lh_log_flushers;	/* what processes competed for log_flush */
+};
+
 /*
  * Log type descriptor
  */




More information about the Cluster-devel mailing list