All of lore.kernel.org
 help / color / mirror / Atom feed
* [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2
@ 2018-01-18 16:04 Andreas Gruenbacher
  2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 1/3] gfs2: Get rid of gfs2_log_header_in Andreas Gruenbacher
                   ` (4 more replies)
  0 siblings, 5 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2018-01-18 16:04 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Here's a revised version of Bob's gfs2_log_header_v2 patches from
January 4:

The first patch cleanus up get_log_header in a preliminary step.

The second patch incorporates the following chages:

 * Fix a NULL pointer access when recovering a node's own journal
   (sdp->sd_qc_inode is NULL in gfs2_write_log_header in that case).
 
 * Move the call to gfs2_log_bmap out of gfs2_log_write.  With that,
   lh_crc can be computed in gfs2_write_log_header and no separate
   gfs2_set_log_csum function is needed anymore.

 * Change lh_crc to only cover the rest of the block excluding the v1
   log header: there is no point in crc-protecting the v1 header a
   second time.

 * Since lh_crc covers the rest of the block and not only a few header
   fields, it makes sense to use crc32c, which is much faster on
   architectures that implement it in hardware.

The third patch is unchanged from Bob's last version.

Thanks,
Andreas

Andreas Gruenbacher (1):
  gfs2: Get rid of gfs2_log_header_in

Bob Peterson (2):
  GFS2: Introduce new gfs2_log_header_v2
  GFS2: Log the reason for log flushes in every log header

 fs/gfs2/aops.c                   |  3 +-
 fs/gfs2/file.c                   |  4 +-
 fs/gfs2/glops.c                  | 19 ++++++---
 fs/gfs2/incore.h                 |  1 -
 fs/gfs2/log.c                    | 83 +++++++++++++++++++++++++++++-----------
 fs/gfs2/log.h                    | 12 ++----
 fs/gfs2/lops.c                   | 16 ++++----
 fs/gfs2/lops.h                   |  3 ++
 fs/gfs2/ops_fstype.c             |  2 +-
 fs/gfs2/quota.c                  |  3 +-
 fs/gfs2/recovery.c               | 57 ++++++++++++---------------
 fs/gfs2/rgrp.c                   |  3 +-
 fs/gfs2/super.c                  | 13 +++++--
 fs/gfs2/trace_gfs2.h             | 11 ++++--
 fs/gfs2/trans.c                  |  3 +-
 include/uapi/linux/gfs2_ondisk.h | 46 +++++++++++++++++++++-
 16 files changed, 187 insertions(+), 92 deletions(-)

-- 
2.14.3



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 1/3] gfs2: Get rid of gfs2_log_header_in
  2018-01-18 16:04 [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
@ 2018-01-18 16:04 ` Andreas Gruenbacher
  2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2018-01-18 16:04 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Get rid of gfs2_log_header_in by integrating it into get_log_header.
Clean up the crc32 computations and use the same functions for encoding
and decoding to make things less confusing.  Eliminate lh_hash from
gfs2_log_header_host which is completely useless.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/gfs2/incore.h   |  1 -
 fs/gfs2/log.c      |  2 +-
 fs/gfs2/recovery.c | 44 ++++++++++++++++----------------------------
 3 files changed, 17 insertions(+), 30 deletions(-)

diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 6e18e9793ec4..4b7946ff7770 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -44,7 +44,6 @@ struct gfs2_log_header_host {
 	u32 lh_flags;		/* GFS2_LOG_HEAD_... */
 	u32 lh_tail;		/* Block number of log tail */
 	u32 lh_blkno;
-	u32 lh_hash;
 };
 
 /*
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index b9889ae5fd7c..c27cbcebfe88 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -680,7 +680,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
 	lh->lh_flags = cpu_to_be32(flags);
 	lh->lh_tail = cpu_to_be32(tail);
 	lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
-	hash = gfs2_disk_hash(page_address(page), sizeof(struct gfs2_log_header));
+	hash = ~crc32(~0, lh, sizeof(*lh));
 	lh->lh_hash = cpu_to_be32(hash);
 
 	gfs2_log_write_page(sdp, page);
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 5d3431219425..975f32166dfe 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -118,22 +118,6 @@ void gfs2_revoke_clean(struct gfs2_jdesc *jd)
 	}
 }
 
-static int gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
-{
-	const struct gfs2_log_header *str = buf;
-
-	if (str->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
-	    str->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH))
-		return 1;
-
-	lh->lh_sequence = be64_to_cpu(str->lh_sequence);
-	lh->lh_flags = be32_to_cpu(str->lh_flags);
-	lh->lh_tail = be32_to_cpu(str->lh_tail);
-	lh->lh_blkno = be32_to_cpu(str->lh_blkno);
-	lh->lh_hash = be32_to_cpu(str->lh_hash);
-	return 0;
-}
-
 /**
  * get_log_header - read the log header for a given segment
  * @jd: the journal
@@ -151,29 +135,33 @@ static int gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
 static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
 			  struct gfs2_log_header_host *head)
 {
+	struct gfs2_log_header *lh;
 	struct buffer_head *bh;
-	struct gfs2_log_header_host uninitialized_var(lh);
-	const u32 nothing = 0;
 	u32 hash;
 	int error;
 
 	error = gfs2_replay_read_block(jd, blk, &bh);
 	if (error)
 		return error;
+	lh = (void *)bh->b_data;
 
-	hash = crc32_le((u32)~0, bh->b_data, sizeof(struct gfs2_log_header) -
-					     sizeof(u32));
-	hash = crc32_le(hash, (unsigned char const *)&nothing, sizeof(nothing));
-	hash ^= (u32)~0;
-	error = gfs2_log_header_in(&lh, bh->b_data);
-	brelse(bh);
+	hash = crc32(~0, lh, sizeof(*lh) - 4);
+	hash = ~crc32_le_shift(hash, 4);  /* assume lh_hash is zero */
 
-	if (error || lh.lh_blkno != blk || lh.lh_hash != hash)
-		return 1;
+	error = lh->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
+		lh->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH) ||
+		be32_to_cpu(lh->lh_blkno) != blk ||
+		be32_to_cpu(lh->lh_hash) != hash;
 
-	*head = lh;
+	brelse(bh);
 
-	return 0;
+	if (!error) {
+		head->lh_sequence = be64_to_cpu(lh->lh_sequence);
+		head->lh_flags = be32_to_cpu(lh->lh_flags);
+		head->lh_tail = be32_to_cpu(lh->lh_tail);
+		head->lh_blkno = be32_to_cpu(lh->lh_blkno);
+	}
+	return error;
 }
 
 /**
-- 
2.14.3



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-18 16:04 [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
  2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 1/3] gfs2: Get rid of gfs2_log_header_in Andreas Gruenbacher
@ 2018-01-18 16:04 ` Andreas Gruenbacher
  2018-01-19 10:47   ` Andrew Price
  2018-01-19 14:31   ` Andrew Price
  2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 3/3] GFS2: Log the reason for log flushes in every log header Andreas Gruenbacher
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2018-01-18 16:04 UTC (permalink / raw)
  To: cluster-devel.redhat.com

From: Bob Peterson <rpeterso@redhat.com>

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
(i.e., this change is backwards compatible).  Some of these are used for
debug purposes so we can backtrack when problems occur.  Others are
reserved for future expansion.

This patch is based on a prototype from Steve Whitehouse.

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
 fs/gfs2/aops.c                   |  2 +-
 fs/gfs2/file.c                   |  3 +-
 fs/gfs2/glops.c                  | 13 +++----
 fs/gfs2/log.c                    | 75 ++++++++++++++++++++++++++++++----------
 fs/gfs2/log.h                    | 12 ++-----
 fs/gfs2/lops.c                   | 16 +++++----
 fs/gfs2/lops.h                   |  3 ++
 fs/gfs2/ops_fstype.c             |  2 +-
 fs/gfs2/quota.c                  |  3 +-
 fs/gfs2/recovery.c               | 17 +++++----
 fs/gfs2/rgrp.c                   |  2 +-
 fs/gfs2/super.c                  |  9 ++---
 fs/gfs2/trans.c                  |  2 +-
 include/uapi/linux/gfs2_ondisk.h | 25 +++++++++++++-
 14 files changed, 126 insertions(+), 58 deletions(-)

diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 658ca027cab9..7c64925735d3 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -445,7 +445,7 @@ static int gfs2_jdata_writepages(struct address_space *mapping,
 
 	ret = gfs2_write_cache_jdata(mapping, wbc);
 	if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) {
-		gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH);
+		gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
 		ret = gfs2_write_cache_jdata(mapping, wbc);
 	}
 	return ret;
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index bd60dc682676..7a02b4e6e9f3 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -246,7 +246,8 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
 	}
 	if ((flags ^ new_flags) & GFS2_DIF_JDATA) {
 		if (new_flags & GFS2_DIF_JDATA)
-			gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH);
+			gfs2_log_flush(sdp, ip->i_gl,
+				       GFS2_LOG_HEAD_FLUSH_NORMAL);
 		error = filemap_fdatawrite(inode->i_mapping);
 		if (error)
 			goto out;
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index cdd1c5f06f45..2daab13a9e0b 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -107,7 +107,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 	__gfs2_ail_flush(gl, 0, tr.tr_revokes);
 
 	gfs2_trans_end(sdp);
-	gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 }
 
 void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
@@ -128,7 +128,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 		return;
 	__gfs2_ail_flush(gl, fsync, max_revokes);
 	gfs2_trans_end(sdp);
-	gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 }
 
 /**
@@ -157,7 +157,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
 		return;
 	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
-	gfs2_log_flush(sdp, gl, NORMAL_FLUSH);
+	gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
 	error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
 	mapping_set_error(mapping, error);
@@ -252,7 +252,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
 
 	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
-	gfs2_log_flush(gl->gl_name.ln_sbd, gl, NORMAL_FLUSH);
+	gfs2_log_flush(gl->gl_name.ln_sbd, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	filemap_fdatawrite(metamapping);
 	if (isreg) {
 		struct address_space *mapping = ip->i_inode.i_mapping;
@@ -303,7 +303,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 	}
 
 	if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) {
-		gfs2_log_flush(gl->gl_name.ln_sbd, NULL, NORMAL_FLUSH);
+		gfs2_log_flush(gl->gl_name.ln_sbd, NULL,
+			       GFS2_LOG_HEAD_FLUSH_NORMAL);
 		gl->gl_name.ln_sbd->sd_rindex_uptodate = 0;
 	}
 	if (ip && S_ISREG(ip->i_inode.i_mode))
@@ -495,7 +496,7 @@ static void freeze_go_sync(struct gfs2_glock *gl)
 			gfs2_assert_withdraw(sdp, 0);
 		}
 		queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
-		gfs2_log_flush(sdp, NULL, FREEZE_FLUSH);
+		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE);
 	}
 }
 
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index c27cbcebfe88..a2eb13c04591 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -14,6 +14,7 @@
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
+#include <linux/crc32c.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
@@ -653,20 +654,25 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
 /**
  * write_log_header - Write a journal log header buffer at sd_log_flush_head
  * @sdp: The GFS2 superblock
+ * @jd: journal descriptor of the journal to which we are writing
  * @seq: sequence number
  * @tail: tail of the log
- * @flags: log header flags
+ * @flags: log header flags GFS2_LOG_HEAD_*
  * @op_flags: flags to pass to the bio
  *
  * Returns: the initialized log buffer descriptor
  */
 
-void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
-			   u32 flags, int op_flags)
+void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
+			   u64 seq, u32 tail, u32 flags, int op_flags)
 {
 	struct gfs2_log_header *lh;
-	u32 hash;
+	u32 hash, crc;
 	struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
+	struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+	struct timespec64 tv;
+	struct super_block *sb = sdp->sd_vfs;
+	u64 addr;
 
 	lh = page_address(page);
 	clear_page(lh);
@@ -680,10 +686,39 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
 	lh->lh_flags = cpu_to_be32(flags);
 	lh->lh_tail = cpu_to_be32(tail);
 	lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
-	hash = ~crc32(~0, lh, sizeof(*lh));
+	hash = ~crc32(~0, lh, LH_V1_SIZE);
 	lh->lh_hash = cpu_to_be32(hash);
 
-	gfs2_log_write_page(sdp, page);
+	tv = current_kernel_time64();
+	lh->lh_nsec = cpu_to_be32(tv.tv_nsec);
+	lh->lh_sec = cpu_to_be64(tv.tv_sec);
+	addr = gfs2_log_bmap(sdp);
+	lh->lh_addr = cpu_to_be64(addr);
+	lh->lh_jinode = cpu_to_be64(GFS2_I(jd->jd_inode)->i_no_addr);
+
+	/* We may only write local statfs, quota, etc., when writing to our
+	   own journal. The values are left 0 when recovering a journal
+	   different from our own. */
+	if (!(flags & GFS2_LOG_HEAD_RECOVERY)) {
+		lh->lh_statfs_addr =
+			cpu_to_be64(GFS2_I(sdp->sd_sc_inode)->i_no_addr);
+		lh->lh_quota_addr =
+			cpu_to_be64(GFS2_I(sdp->sd_qc_inode)->i_no_addr);
+
+		spin_lock(&sdp->sd_statfs_spin);
+		lh->lh_local_total = cpu_to_be64(l_sc->sc_total);
+		lh->lh_local_free = cpu_to_be64(l_sc->sc_free);
+		lh->lh_local_dinodes = cpu_to_be64(l_sc->sc_dinodes);
+		spin_unlock(&sdp->sd_statfs_spin);
+	}
+
+	BUILD_BUG_ON(offsetof(struct gfs2_log_header, lh_crc) != LH_V1_SIZE);
+
+	crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
+		     sb->s_blocksize - LH_V1_SIZE - 4);
+	lh->lh_crc = cpu_to_be32(crc);
+
+	gfs2_log_write(sdp, page, sb->s_blocksize, 0, addr);
 	gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags);
 	log_flush_wait(sdp);
 }
@@ -691,6 +726,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
 /**
  * log_write_header - Get and initialize a journal header buffer
  * @sdp: The GFS2 superblock
+ * @flags: The log header flags, including log header origin
  *
  * Returns: the initialized log buffer descriptor
  */
@@ -710,8 +746,8 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
 		op_flags = REQ_SYNC | REQ_META | REQ_PRIO;
 	}
 	sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
-	gfs2_write_log_header(sdp, sdp->sd_log_sequence++, tail, flags,
-			      op_flags);
+	gfs2_write_log_header(sdp, sdp->sd_jdesc, sdp->sd_log_sequence++, tail,
+			      flags, op_flags);
 
 	if (sdp->sd_log_tail != tail)
 		log_pull_tail(sdp, tail);
@@ -721,11 +757,11 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
  * gfs2_log_flush - flush incore transaction(s)
  * @sdp: the filesystem
  * @gl: The glock structure to flush.  If NULL, flush the whole incore log
+ * @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_*
  *
  */
 
-void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
-		    enum gfs2_flush_type type)
+void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
 {
 	struct gfs2_trans *tr;
 	enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state);
@@ -739,7 +775,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
 	}
 	trace_gfs2_log_flush(sdp, 1);
 
-	if (type == SHUTDOWN_FLUSH)
+	if (flags & GFS2_LOG_HEAD_FLUSH_SHUTDOWN)
 		clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
 
 	sdp->sd_log_flush_head = sdp->sd_log_head;
@@ -764,11 +800,11 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
 
 	if (sdp->sd_log_head != sdp->sd_log_flush_head) {
 		log_flush_wait(sdp);
-		log_write_header(sdp, 0);
+		log_write_header(sdp, flags);
 	} else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
 		atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
 		trace_gfs2_log_blocks(sdp, -1);
-		log_write_header(sdp, 0);
+		log_write_header(sdp, flags);
 	}
 	lops_after_commit(sdp, tr);
 
@@ -785,7 +821,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
 	spin_unlock(&sdp->sd_ail_lock);
 	gfs2_log_unlock(sdp);
 
-	if (type != NORMAL_FLUSH) {
+	if (!(flags & GFS2_LOG_HEAD_FLUSH_NORMAL)) {
 		if (!sdp->sd_log_idle) {
 			for (;;) {
 				gfs2_ail1_start(sdp);
@@ -795,12 +831,13 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
 			}
 			atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
 			trace_gfs2_log_blocks(sdp, -1);
-			log_write_header(sdp, 0);
+			log_write_header(sdp, flags);
 			sdp->sd_log_head = sdp->sd_log_flush_head;
 		}
-		if (type == SHUTDOWN_FLUSH || type == FREEZE_FLUSH)
+		if (flags & (GFS2_LOG_HEAD_FLUSH_SHUTDOWN |
+			     GFS2_LOG_HEAD_FLUSH_FREEZE))
 			gfs2_log_shutdown(sdp);
-		if (type == FREEZE_FLUSH)
+		if (flags & GFS2_LOG_HEAD_FLUSH_FREEZE)
 			atomic_set(&sdp->sd_freeze_state, SFS_FROZEN);
 	}
 
@@ -956,7 +993,7 @@ int gfs2_logd(void *data)
 		did_flush = false;
 		if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
 			gfs2_ail1_empty(sdp);
-			gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 			did_flush = true;
 		}
 
@@ -964,7 +1001,7 @@ int gfs2_logd(void *data)
 			gfs2_ail1_start(sdp);
 			gfs2_ail1_wait(sdp);
 			gfs2_ail1_empty(sdp);
-			gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 			did_flush = true;
 		}
 
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h
index 619de9a1ff4f..93b52ac1ca1f 100644
--- a/fs/gfs2/log.h
+++ b/fs/gfs2/log.h
@@ -65,16 +65,10 @@ extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
 
 extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks);
 extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
-enum gfs2_flush_type {
-	NORMAL_FLUSH = 0,
-	SYNC_FLUSH,
-	SHUTDOWN_FLUSH,
-	FREEZE_FLUSH
-};
-extern void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
-				  u32 flags, int op_flags);
+extern void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
+				  u64 seq, u32 tail, u32 flags, int op_flags);
 extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
-			   enum gfs2_flush_type type);
+			   u32 type);
 extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
 extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
 extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index c8ff7b7954f0..4a60221c678f 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"
@@ -138,7 +139,7 @@ static void gfs2_log_incr_head(struct gfs2_sbd *sdp)
 		sdp->sd_log_flush_head = 0;
 }
 
-static u64 gfs2_log_bmap(struct gfs2_sbd *sdp)
+u64 gfs2_log_bmap(struct gfs2_sbd *sdp)
 {
 	unsigned int lbn = sdp->sd_log_flush_head;
 	struct gfs2_journal_extent *je;
@@ -306,23 +307,22 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno)
 	return gfs2_log_alloc_bio(sdp, blkno);
 }
 
-
 /**
  * gfs2_log_write - write to log
  * @sdp: the filesystem
  * @page: the page to write
  * @size: the size of the data to write
  * @offset: the offset within the page 
+ * @blkno: block number of the log entry
  *
  * Try and add the page segment to the current bio. If that fails,
  * submit the current bio to the device and create a new one, and
  * then add the page segment to that.
  */
 
-static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
-			   unsigned size, unsigned offset)
+void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
+		    unsigned size, unsigned offset, u64 blkno)
 {
-	u64 blkno = gfs2_log_bmap(sdp);
 	struct bio *bio;
 	int ret;
 
@@ -348,7 +348,8 @@ 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),
+		       gfs2_log_bmap(sdp));
 }
 
 /**
@@ -365,7 +366,8 @@ 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,
+		       gfs2_log_bmap(sdp));
 }
 
 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..e4949394f054 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -26,6 +26,9 @@ extern const struct gfs2_log_operations gfs2_revoke_lops;
 extern const struct gfs2_log_operations gfs2_databuf_lops;
 
 extern const struct gfs2_log_operations *gfs2_log_ops[];
+extern u64 gfs2_log_bmap(struct gfs2_sbd *sdp);
+extern void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
+			   unsigned size, unsigned offset, u64 blkno);
 extern void gfs2_log_write_page(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/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index ad55eb86a250..d6e620beb9db 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1382,7 +1382,7 @@ static void gfs2_kill_sb(struct super_block *sb)
 		return;
 	}
 
-	gfs2_log_flush(sdp, NULL, SYNC_FLUSH);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SYNC);
 	dput(sdp->sd_root_dir);
 	dput(sdp->sd_master_dir);
 	sdp->sd_root_dir = NULL;
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index e700fb162664..2092df19e433 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -955,7 +955,8 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
 		gfs2_glock_dq_uninit(&ghs[qx]);
 	inode_unlock(&ip->i_inode);
 	kfree(ghs);
-	gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl, NORMAL_FLUSH);
+	gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl,
+		       GFS2_LOG_HEAD_FLUSH_NORMAL);
 	return error;
 }
 
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 975f32166dfe..b6b258998bcd 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -14,6 +14,7 @@
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
+#include <linux/crc32c.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -137,7 +138,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
 {
 	struct gfs2_log_header *lh;
 	struct buffer_head *bh;
-	u32 hash;
+	u32 hash, crc;
 	int error;
 
 	error = gfs2_replay_read_block(jd, blk, &bh);
@@ -145,13 +146,17 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
 		return error;
 	lh = (void *)bh->b_data;
 
-	hash = crc32(~0, lh, sizeof(*lh) - 4);
+	hash = crc32(~0, lh, LH_V1_SIZE - 4);
 	hash = ~crc32_le_shift(hash, 4);  /* assume lh_hash is zero */
 
+	crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
+		     bh->b_size - LH_V1_SIZE - 4);
+
 	error = lh->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
 		lh->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH) ||
 		be32_to_cpu(lh->lh_blkno) != blk ||
-		be32_to_cpu(lh->lh_hash) != hash;
+		be32_to_cpu(lh->lh_hash) != hash ||
+		(lh->lh_crc != 0 && be32_to_cpu(lh->lh_crc) != crc);
 
 	brelse(bh);
 
@@ -372,9 +377,9 @@ static void clean_journal(struct gfs2_jdesc *jd,
 
 	sdp->sd_log_flush_head = head->lh_blkno;
 	gfs2_replay_incr_blk(jd, &sdp->sd_log_flush_head);
-	gfs2_write_log_header(sdp, head->lh_sequence + 1, 0,
-			      GFS2_LOG_HEAD_UNMOUNT, REQ_PREFLUSH |
-			      REQ_FUA | REQ_META | REQ_SYNC);
+	gfs2_write_log_header(sdp, jd, head->lh_sequence + 1, 0,
+			      GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_RECOVERY,
+			      REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC);
 }
 
 
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 6dea72f49316..00eab6c0525c 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -2093,7 +2093,7 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, struct gfs2_alloc_parms *ap)
 		}
 		/* Flushing the log may release space */
 		if (loops == 2)
-			gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	}
 
 	return -ENOSPC;
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index d81d46e19726..fa3a19eaf0eb 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -757,7 +757,8 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc)
 	bool flush_all = (wbc->sync_mode == WB_SYNC_ALL || gfs2_is_jdata(ip));
 
 	if (flush_all)
-		gfs2_log_flush(GFS2_SB(inode), ip->i_gl, NORMAL_FLUSH);
+		gfs2_log_flush(GFS2_SB(inode), ip->i_gl,
+			       GFS2_LOG_HEAD_FLUSH_NORMAL);
 	if (bdi->wb.dirty_exceeded)
 		gfs2_ail1_flush(sdp, wbc);
 	else
@@ -853,7 +854,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
 	gfs2_quota_sync(sdp->sd_vfs, 0);
 	gfs2_statfs_sync(sdp->sd_vfs, 0);
 
-	gfs2_log_flush(sdp, NULL, SHUTDOWN_FLUSH);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN);
 	wait_event(sdp->sd_reserving_log_wait, atomic_read(&sdp->sd_reserving_log) == 0);
 	gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
 
@@ -946,7 +947,7 @@ static int gfs2_sync_fs(struct super_block *sb, int wait)
 
 	gfs2_quota_sync(sb, -1);
 	if (wait)
-		gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	return sdp->sd_log_error;
 }
 
@@ -1650,7 +1651,7 @@ static void gfs2_evict_inode(struct inode *inode)
 	goto out_unlock;
 
 out_truncate:
-	gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH);
+	gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	metamapping = gfs2_glock2aspace(ip->i_gl);
 	if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) {
 		filemap_fdatawrite(metamapping);
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index b95ebd166cac..7aec6d3434fa 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -117,7 +117,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp)
 	up_read(&sdp->sd_log_flush_lock);
 
 	if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS)
-		gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	if (alloced)
 		sb_end_intwrite(sdp->sd_vfs);
 }
diff --git a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h
index 09f0920f07e9..7eb73c32272f 100644
--- a/include/uapi/linux/gfs2_ondisk.h
+++ b/include/uapi/linux/gfs2_ondisk.h
@@ -403,7 +403,15 @@ struct gfs2_ea_header {
  * Log header structure
  */
 
-#define GFS2_LOG_HEAD_UNMOUNT	0x00000001	/* log is clean */
+#define GFS2_LOG_HEAD_UNMOUNT		0x00000001 /* log is clean */
+#define GFS2_LOG_HEAD_FLUSH_NORMAL	0x00000002 /* normal log flush */
+#define GFS2_LOG_HEAD_FLUSH_SYNC	0x00000004 /* Sync log flush */
+#define GFS2_LOG_HEAD_FLUSH_SHUTDOWN	0x00000008 /* Shutdown log flush */
+#define GFS2_LOG_HEAD_FLUSH_FREEZE	0x00000010 /* Freeze flush */
+#define GFS2_LOG_HEAD_RECOVERY		0x00000020 /* Journal recovery */
+#define GFS2_LOG_HEAD_USERSPACE		0x80000000 /* Written by gfs2-utils */
+
+#define LH_V1_SIZE (offsetofend(struct gfs2_log_header, lh_hash))
 
 struct gfs2_log_header {
 	struct gfs2_meta_header lh_header;
@@ -413,6 +421,21 @@ struct gfs2_log_header {
 	__be32 lh_tail;		/* Block number of log tail */
 	__be32 lh_blkno;
 	__be32 lh_hash;
+
+	/* Version 2 additional fields start here */
+	__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 addr 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_origin;	/* The origin of this log header */
 };
 
 /*
-- 
2.14.3



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 3/3] GFS2: Log the reason for log flushes in every log header
  2018-01-18 16:04 [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
  2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 1/3] gfs2: Get rid of gfs2_log_header_in Andreas Gruenbacher
  2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
@ 2018-01-18 16:04 ` Andreas Gruenbacher
  2018-01-18 16:23 ` [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2 Steven Whitehouse
  2018-01-19 14:40 ` [Cluster-devel] [PATCH v6] " Andreas Gruenbacher
  4 siblings, 0 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2018-01-18 16:04 UTC (permalink / raw)
  To: cluster-devel.redhat.com

From: Bob Peterson <rpeterso@redhat.com>

This patch just adds the capability for GFS2 to track which function
called gfs2_log_flush. This should make it easier to diagnose
problems based on the sequence of events found in the journals.

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
 fs/gfs2/aops.c                   |  3 ++-
 fs/gfs2/file.c                   |  3 ++-
 fs/gfs2/glops.c                  | 18 ++++++++++++------
 fs/gfs2/log.c                    | 14 ++++++++------
 fs/gfs2/ops_fstype.c             |  2 +-
 fs/gfs2/quota.c                  |  2 +-
 fs/gfs2/rgrp.c                   |  3 ++-
 fs/gfs2/super.c                  | 12 ++++++++----
 fs/gfs2/trace_gfs2.h             | 11 +++++++----
 fs/gfs2/trans.c                  |  3 ++-
 include/uapi/linux/gfs2_ondisk.h | 21 +++++++++++++++++++++
 11 files changed, 66 insertions(+), 26 deletions(-)

diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 7c64925735d3..eb06f517004c 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -445,7 +445,8 @@ static int gfs2_jdata_writepages(struct address_space *mapping,
 
 	ret = gfs2_write_cache_jdata(mapping, wbc);
 	if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) {
-		gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
+		gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
+			       GFS2_LFC_JDATA_WPAGES);
 		ret = gfs2_write_cache_jdata(mapping, wbc);
 	}
 	return ret;
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 7a02b4e6e9f3..4f88e201b3f0 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -247,7 +247,8 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
 	if ((flags ^ new_flags) & GFS2_DIF_JDATA) {
 		if (new_flags & GFS2_DIF_JDATA)
 			gfs2_log_flush(sdp, ip->i_gl,
-				       GFS2_LOG_HEAD_FLUSH_NORMAL);
+				       GFS2_LOG_HEAD_FLUSH_NORMAL |
+				       GFS2_LFC_SET_FLAGS);
 		error = filemap_fdatawrite(inode->i_mapping);
 		if (error)
 			goto out;
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 2daab13a9e0b..d8782a7a1e7d 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -107,7 +107,8 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 	__gfs2_ail_flush(gl, 0, tr.tr_revokes);
 
 	gfs2_trans_end(sdp);
-	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
+		       GFS2_LFC_AIL_EMPTY_GL);
 }
 
 void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
@@ -128,7 +129,8 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 		return;
 	__gfs2_ail_flush(gl, fsync, max_revokes);
 	gfs2_trans_end(sdp);
-	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
+		       GFS2_LFC_AIL_FLUSH);
 }
 
 /**
@@ -157,7 +159,8 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
 		return;
 	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
-	gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
+	gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
+		       GFS2_LFC_RGRP_GO_SYNC);
 	filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
 	error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
 	mapping_set_error(mapping, error);
@@ -252,7 +255,8 @@ static void inode_go_sync(struct gfs2_glock *gl)
 
 	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
-	gfs2_log_flush(gl->gl_name.ln_sbd, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
+	gfs2_log_flush(gl->gl_name.ln_sbd, gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
+		       GFS2_LFC_INODE_GO_SYNC);
 	filemap_fdatawrite(metamapping);
 	if (isreg) {
 		struct address_space *mapping = ip->i_inode.i_mapping;
@@ -304,7 +308,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 
 	if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) {
 		gfs2_log_flush(gl->gl_name.ln_sbd, NULL,
-			       GFS2_LOG_HEAD_FLUSH_NORMAL);
+			       GFS2_LOG_HEAD_FLUSH_NORMAL |
+			       GFS2_LFC_INODE_GO_INVAL);
 		gl->gl_name.ln_sbd->sd_rindex_uptodate = 0;
 	}
 	if (ip && S_ISREG(ip->i_inode.i_mode))
@@ -496,7 +501,8 @@ static void freeze_go_sync(struct gfs2_glock *gl)
 			gfs2_assert_withdraw(sdp, 0);
 		}
 		queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
-		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE);
+		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE |
+			       GFS2_LFC_FREEZE_GO_SYNC);
 	}
 }
 
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index a2eb13c04591..cf6b46247df4 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -757,7 +757,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
  * gfs2_log_flush - flush incore transaction(s)
  * @sdp: the filesystem
  * @gl: The glock structure to flush.  If NULL, flush the whole incore log
- * @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_*
+ * @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_* and debug flags
  *
  */
 
@@ -773,7 +773,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
 		up_write(&sdp->sd_log_flush_lock);
 		return;
 	}
-	trace_gfs2_log_flush(sdp, 1);
+	trace_gfs2_log_flush(sdp, 1, flags);
 
 	if (flags & GFS2_LOG_HEAD_FLUSH_SHUTDOWN)
 		clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
@@ -841,7 +841,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
 			atomic_set(&sdp->sd_freeze_state, SFS_FROZEN);
 	}
 
-	trace_gfs2_log_flush(sdp, 0);
+	trace_gfs2_log_flush(sdp, 0, flags);
 	up_write(&sdp->sd_log_flush_lock);
 
 	kfree(tr);
@@ -937,7 +937,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
 
 	sdp->sd_log_flush_head = sdp->sd_log_head;
 
-	log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT);
+	log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT | GFS2_LFC_SHUTDOWN);
 
 	gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
 	gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list));
@@ -993,7 +993,8 @@ int gfs2_logd(void *data)
 		did_flush = false;
 		if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
 			gfs2_ail1_empty(sdp);
-			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
+			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
+				       GFS2_LFC_LOGD_JFLUSH_REQD);
 			did_flush = true;
 		}
 
@@ -1001,7 +1002,8 @@ int gfs2_logd(void *data)
 			gfs2_ail1_start(sdp);
 			gfs2_ail1_wait(sdp);
 			gfs2_ail1_empty(sdp);
-			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
+			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
+				       GFS2_LFC_LOGD_AIL_FLUSH_REQD);
 			did_flush = true;
 		}
 
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index d6e620beb9db..e6a0a8a89ea7 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1382,7 +1382,7 @@ static void gfs2_kill_sb(struct super_block *sb)
 		return;
 	}
 
-	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SYNC);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SYNC | GFS2_LFC_KILL_SB);
 	dput(sdp->sd_root_dir);
 	dput(sdp->sd_master_dir);
 	sdp->sd_root_dir = NULL;
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 2092df19e433..7a98abd340ee 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -956,7 +956,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
 	inode_unlock(&ip->i_inode);
 	kfree(ghs);
 	gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl,
-		       GFS2_LOG_HEAD_FLUSH_NORMAL);
+		       GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_DO_SYNC);
 	return error;
 }
 
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 00eab6c0525c..078b002e0a68 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -2093,7 +2093,8 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, struct gfs2_alloc_parms *ap)
 		}
 		/* Flushing the log may release space */
 		if (loops == 2)
-			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
+			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
+				       GFS2_LFC_INPLACE_RESERVE);
 	}
 
 	return -ENOSPC;
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index fa3a19eaf0eb..50a297b920fc 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -758,7 +758,8 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc)
 
 	if (flush_all)
 		gfs2_log_flush(GFS2_SB(inode), ip->i_gl,
-			       GFS2_LOG_HEAD_FLUSH_NORMAL);
+			       GFS2_LOG_HEAD_FLUSH_NORMAL |
+			       GFS2_LFC_WRITE_INODE);
 	if (bdi->wb.dirty_exceeded)
 		gfs2_ail1_flush(sdp, wbc);
 	else
@@ -854,7 +855,8 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
 	gfs2_quota_sync(sdp->sd_vfs, 0);
 	gfs2_statfs_sync(sdp->sd_vfs, 0);
 
-	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN |
+		       GFS2_LFC_MAKE_FS_RO);
 	wait_event(sdp->sd_reserving_log_wait, atomic_read(&sdp->sd_reserving_log) == 0);
 	gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
 
@@ -947,7 +949,8 @@ static int gfs2_sync_fs(struct super_block *sb, int wait)
 
 	gfs2_quota_sync(sb, -1);
 	if (wait)
-		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
+		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
+			       GFS2_LFC_SYNC_FS);
 	return sdp->sd_log_error;
 }
 
@@ -1651,7 +1654,8 @@ static void gfs2_evict_inode(struct inode *inode)
 	goto out_unlock;
 
 out_truncate:
-	gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
+	gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
+		       GFS2_LFC_EVICT_INODE);
 	metamapping = gfs2_glock2aspace(ip->i_gl);
 	if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) {
 		filemap_fdatawrite(metamapping);
diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h
index f67a709589d3..b9318b49ff8f 100644
--- a/fs/gfs2/trace_gfs2.h
+++ b/fs/gfs2/trace_gfs2.h
@@ -353,26 +353,29 @@ TRACE_EVENT(gfs2_pin,
 /* Flushing the log */
 TRACE_EVENT(gfs2_log_flush,
 
-	TP_PROTO(const struct gfs2_sbd *sdp, int start),
+	TP_PROTO(const struct gfs2_sbd *sdp, int start, u32 flags),
 
-	TP_ARGS(sdp, start),
+	TP_ARGS(sdp, start, flags),
 
 	TP_STRUCT__entry(
 		__field(        dev_t,  dev                     )
 		__field(	int,	start			)
 		__field(	u64,	log_seq			)
+		__field(	u32,	flags			)
 	),
 
 	TP_fast_assign(
 		__entry->dev            = sdp->sd_vfs->s_dev;
 		__entry->start		= start;
 		__entry->log_seq	= sdp->sd_log_sequence;
+		__entry->flags		= flags;
 	),
 
-	TP_printk("%u,%u log flush %s %llu",
+	TP_printk("%u,%u log flush %s %llu %llx",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
 		  __entry->start ? "start" : "end",
-		  (unsigned long long)__entry->log_seq)
+		  (unsigned long long)__entry->log_seq,
+		  (unsigned long long)__entry->flags)
 );
 
 /* Reserving/releasing blocks in the log */
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 7aec6d3434fa..c75cacaa349b 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -117,7 +117,8 @@ void gfs2_trans_end(struct gfs2_sbd *sdp)
 	up_read(&sdp->sd_log_flush_lock);
 
 	if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS)
-		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
+		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
+			       GFS2_LFC_TRANS_END);
 	if (alloced)
 		sb_end_intwrite(sdp->sd_vfs);
 }
diff --git a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h
index 7eb73c32272f..04585f8e44bb 100644
--- a/include/uapi/linux/gfs2_ondisk.h
+++ b/include/uapi/linux/gfs2_ondisk.h
@@ -411,6 +411,27 @@ struct gfs2_ea_header {
 #define GFS2_LOG_HEAD_RECOVERY		0x00000020 /* Journal recovery */
 #define GFS2_LOG_HEAD_USERSPACE		0x80000000 /* Written by gfs2-utils */
 
+/* Log flush callers */
+#define GFS2_LFC_SHUTDOWN		0x00000100
+#define GFS2_LFC_JDATA_WPAGES		0x00000200
+#define GFS2_LFC_SET_FLAGS		0x00000400
+#define GFS2_LFC_AIL_EMPTY_GL		0x00000800
+#define GFS2_LFC_AIL_FLUSH		0x00001000
+#define GFS2_LFC_RGRP_GO_SYNC		0x00002000
+#define GFS2_LFC_INODE_GO_SYNC		0x00004000
+#define GFS2_LFC_INODE_GO_INVAL		0x00008000
+#define GFS2_LFC_FREEZE_GO_SYNC		0x00010000
+#define GFS2_LFC_KILL_SB		0x00020000
+#define GFS2_LFC_DO_SYNC		0x00040000
+#define GFS2_LFC_INPLACE_RESERVE	0x00080000
+#define GFS2_LFC_WRITE_INODE		0x00100000
+#define GFS2_LFC_MAKE_FS_RO		0x00200000
+#define GFS2_LFC_SYNC_FS		0x00400000
+#define GFS2_LFC_EVICT_INODE		0x00800000
+#define GFS2_LFC_TRANS_END		0x01000000
+#define GFS2_LFC_LOGD_JFLUSH_REQD	0x02000000
+#define GFS2_LFC_LOGD_AIL_FLUSH_REQD	0x04000000
+
 #define LH_V1_SIZE (offsetofend(struct gfs2_log_header, lh_hash))
 
 struct gfs2_log_header {
-- 
2.14.3



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-18 16:04 [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
                   ` (2 preceding siblings ...)
  2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 3/3] GFS2: Log the reason for log flushes in every log header Andreas Gruenbacher
@ 2018-01-18 16:23 ` Steven Whitehouse
  2018-01-19 14:40 ` [Cluster-devel] [PATCH v6] " Andreas Gruenbacher
  4 siblings, 0 replies; 16+ messages in thread
From: Steven Whitehouse @ 2018-01-18 16:23 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,


On 18/01/18 16:04, Andreas Gruenbacher wrote:
> Here's a revised version of Bob's gfs2_log_header_v2 patches from
> January 4:
>
> The first patch cleanus up get_log_header in a preliminary step.
>
> The second patch incorporates the following chages:
>
>   * Fix a NULL pointer access when recovering a node's own journal
>     (sdp->sd_qc_inode is NULL in gfs2_write_log_header in that case).
>   
>   * Move the call to gfs2_log_bmap out of gfs2_log_write.  With that,
>     lh_crc can be computed in gfs2_write_log_header and no separate
>     gfs2_set_log_csum function is needed anymore.
>
>   * Change lh_crc to only cover the rest of the block excluding the v1
>     log header: there is no point in crc-protecting the v1 header a
>     second time.
>
>   * Since lh_crc covers the rest of the block and not only a few header
>     fields, it makes sense to use crc32c, which is much faster on
>     architectures that implement it in hardware.
>
> The third patch is unchanged from Bob's last version.
Yes, that should make it a bit faster in that case, which seems like it 
is worth doing. Is there any measurable effect I wonder?

Steve.

> Thanks,
> Andreas
>
> Andreas Gruenbacher (1):
>    gfs2: Get rid of gfs2_log_header_in
>
> Bob Peterson (2):
>    GFS2: Introduce new gfs2_log_header_v2
>    GFS2: Log the reason for log flushes in every log header
>
>   fs/gfs2/aops.c                   |  3 +-
>   fs/gfs2/file.c                   |  4 +-
>   fs/gfs2/glops.c                  | 19 ++++++---
>   fs/gfs2/incore.h                 |  1 -
>   fs/gfs2/log.c                    | 83 +++++++++++++++++++++++++++++-----------
>   fs/gfs2/log.h                    | 12 ++----
>   fs/gfs2/lops.c                   | 16 ++++----
>   fs/gfs2/lops.h                   |  3 ++
>   fs/gfs2/ops_fstype.c             |  2 +-
>   fs/gfs2/quota.c                  |  3 +-
>   fs/gfs2/recovery.c               | 57 ++++++++++++---------------
>   fs/gfs2/rgrp.c                   |  3 +-
>   fs/gfs2/super.c                  | 13 +++++--
>   fs/gfs2/trace_gfs2.h             | 11 ++++--
>   fs/gfs2/trans.c                  |  3 +-
>   include/uapi/linux/gfs2_ondisk.h | 46 +++++++++++++++++++++-
>   16 files changed, 187 insertions(+), 92 deletions(-)
>



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
@ 2018-01-19 10:47   ` Andrew Price
  2018-01-19 10:53     ` Steven Whitehouse
  2018-01-19 14:31   ` Andrew Price
  1 sibling, 1 reply; 16+ messages in thread
From: Andrew Price @ 2018-01-19 10:47 UTC (permalink / raw)
  To: cluster-devel.redhat.com



On 18/01/18 16:04, Andreas Gruenbacher wrote:
<snip>
> diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
> index c27cbcebfe88..a2eb13c04591 100644
> --- a/fs/gfs2/log.c
> +++ b/fs/gfs2/log.c
> @@ -14,6 +14,7 @@
>   #include <linux/buffer_head.h>
>   #include <linux/gfs2_ondisk.h>
>   #include <linux/crc32.h>
> +#include <linux/crc32c.h>
>   #include <linux/delay.h>
>   #include <linux/kthread.h>
>   #include <linux/freezer.h>
> @@ -653,20 +654,25 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
>   /**
>    * write_log_header - Write a journal log header buffer at sd_log_flush_head
>    * @sdp: The GFS2 superblock
> + * @jd: journal descriptor of the journal to which we are writing
>    * @seq: sequence number
>    * @tail: tail of the log
> - * @flags: log header flags
> + * @flags: log header flags GFS2_LOG_HEAD_*
>    * @op_flags: flags to pass to the bio
>    *
>    * Returns: the initialized log buffer descriptor
>    */
>   
> -void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
> -			   u32 flags, int op_flags)
> +void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
> +			   u64 seq, u32 tail, u32 flags, int op_flags)
>   {
>   	struct gfs2_log_header *lh;
> -	u32 hash;
> +	u32 hash, crc;
>   	struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
> +	struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
> +	struct timespec64 tv;
> +	struct super_block *sb = sdp->sd_vfs;
> +	u64 addr;
>   
>   	lh = page_address(page);
>   	clear_page(lh);
> @@ -680,10 +686,39 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
>   	lh->lh_flags = cpu_to_be32(flags);
>   	lh->lh_tail = cpu_to_be32(tail);
>   	lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
> -	hash = ~crc32(~0, lh, sizeof(*lh));
> +	hash = ~crc32(~0, lh, LH_V1_SIZE);
>   	lh->lh_hash = cpu_to_be32(hash);
>   
> -	gfs2_log_write_page(sdp, page);
> +	tv = current_kernel_time64();
> +	lh->lh_nsec = cpu_to_be32(tv.tv_nsec);
> +	lh->lh_sec = cpu_to_be64(tv.tv_sec);
> +	addr = gfs2_log_bmap(sdp);
> +	lh->lh_addr = cpu_to_be64(addr);
> +	lh->lh_jinode = cpu_to_be64(GFS2_I(jd->jd_inode)->i_no_addr);
> +
> +	/* We may only write local statfs, quota, etc., when writing to our
> +	   own journal. The values are left 0 when recovering a journal
> +	   different from our own. */
> +	if (!(flags & GFS2_LOG_HEAD_RECOVERY)) {
> +		lh->lh_statfs_addr =
> +			cpu_to_be64(GFS2_I(sdp->sd_sc_inode)->i_no_addr);
> +		lh->lh_quota_addr =
> +			cpu_to_be64(GFS2_I(sdp->sd_qc_inode)->i_no_addr);
> +
> +		spin_lock(&sdp->sd_statfs_spin);
> +		lh->lh_local_total = cpu_to_be64(l_sc->sc_total);
> +		lh->lh_local_free = cpu_to_be64(l_sc->sc_free);
> +		lh->lh_local_dinodes = cpu_to_be64(l_sc->sc_dinodes);
> +		spin_unlock(&sdp->sd_statfs_spin);
> +	}
> +
> +	BUILD_BUG_ON(offsetof(struct gfs2_log_header, lh_crc) != LH_V1_SIZE);
> +
> +	crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
> +		     sb->s_blocksize - LH_V1_SIZE - 4);
> +	lh->lh_crc = cpu_to_be32(crc);

This seems to be at odds with the field comment:

 > +	__be32 lh_crc;		/* crc32 of whole block with this field 0 */

Is it really just CRCing the block from lh_crc + 4 onwards?

Andy



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-19 10:47   ` Andrew Price
@ 2018-01-19 10:53     ` Steven Whitehouse
  2018-01-19 12:19       ` Andrew Price
  0 siblings, 1 reply; 16+ messages in thread
From: Steven Whitehouse @ 2018-01-19 10:53 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,


On 19/01/18 10:47, Andrew Price wrote:
>
>
> On 18/01/18 16:04, Andreas Gruenbacher wrote:
> <snip>
>> diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
>> index c27cbcebfe88..a2eb13c04591 100644
>> --- a/fs/gfs2/log.c
>> +++ b/fs/gfs2/log.c
>> @@ -14,6 +14,7 @@
>> ? #include <linux/buffer_head.h>
>> ? #include <linux/gfs2_ondisk.h>
>> ? #include <linux/crc32.h>
>> +#include <linux/crc32c.h>
>> ? #include <linux/delay.h>
>> ? #include <linux/kthread.h>
>> ? #include <linux/freezer.h>
>> @@ -653,20 +654,25 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
>> ? /**
>> ?? * write_log_header - Write a journal log header buffer at 
>> sd_log_flush_head
>> ?? * @sdp: The GFS2 superblock
>> + * @jd: journal descriptor of the journal to which we are writing
>> ?? * @seq: sequence number
>> ?? * @tail: tail of the log
>> - * @flags: log header flags
>> + * @flags: log header flags GFS2_LOG_HEAD_*
>> ?? * @op_flags: flags to pass to the bio
>> ?? *
>> ?? * Returns: the initialized log buffer descriptor
>> ?? */
>> ? -void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
>> -?????????????? u32 flags, int op_flags)
>> +void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
>> +?????????????? u64 seq, u32 tail, u32 flags, int op_flags)
>> ? {
>> ????? struct gfs2_log_header *lh;
>> -??? u32 hash;
>> +??? u32 hash, crc;
>> ????? struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
>> +??? struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
>> +??? struct timespec64 tv;
>> +??? struct super_block *sb = sdp->sd_vfs;
>> +??? u64 addr;
>> ? ????? lh = page_address(page);
>> ????? clear_page(lh);
>> @@ -680,10 +686,39 @@ void gfs2_write_log_header(struct gfs2_sbd 
>> *sdp, u64 seq, u32 tail,
>> ????? lh->lh_flags = cpu_to_be32(flags);
>> ????? lh->lh_tail = cpu_to_be32(tail);
>> ????? lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
>> -??? hash = ~crc32(~0, lh, sizeof(*lh));
>> +??? hash = ~crc32(~0, lh, LH_V1_SIZE);
>> ????? lh->lh_hash = cpu_to_be32(hash);
>> ? -??? gfs2_log_write_page(sdp, page);
>> +??? tv = current_kernel_time64();
>> +??? lh->lh_nsec = cpu_to_be32(tv.tv_nsec);
>> +??? lh->lh_sec = cpu_to_be64(tv.tv_sec);
>> +??? addr = gfs2_log_bmap(sdp);
>> +??? lh->lh_addr = cpu_to_be64(addr);
>> +??? lh->lh_jinode = cpu_to_be64(GFS2_I(jd->jd_inode)->i_no_addr);
>> +
>> +??? /* We may only write local statfs, quota, etc., when writing to our
>> +?????? own journal. The values are left 0 when recovering a journal
>> +?????? different from our own. */
>> +??? if (!(flags & GFS2_LOG_HEAD_RECOVERY)) {
>> +??????? lh->lh_statfs_addr =
>> + cpu_to_be64(GFS2_I(sdp->sd_sc_inode)->i_no_addr);
>> +??????? lh->lh_quota_addr =
>> + cpu_to_be64(GFS2_I(sdp->sd_qc_inode)->i_no_addr);
>> +
>> +??????? spin_lock(&sdp->sd_statfs_spin);
>> +??????? lh->lh_local_total = cpu_to_be64(l_sc->sc_total);
>> +??????? lh->lh_local_free = cpu_to_be64(l_sc->sc_free);
>> +??????? lh->lh_local_dinodes = cpu_to_be64(l_sc->sc_dinodes);
>> +??????? spin_unlock(&sdp->sd_statfs_spin);
>> +??? }
>> +
>> +??? BUILD_BUG_ON(offsetof(struct gfs2_log_header, lh_crc) != 
>> LH_V1_SIZE);
>> +
>> +??? crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
>> +???????????? sb->s_blocksize - LH_V1_SIZE - 4);
>> +??? lh->lh_crc = cpu_to_be32(crc);
>
> This seems to be at odds with the field comment:
>
> > +??? __be32 lh_crc;??????? /* crc32 of whole block with this field 0 */
>
> Is it really just CRCing the block from lh_crc + 4 onwards?
>
> Andy
>
Yes, the comment needs updating to match the code, if we are going to do 
that. I'm not too concerned either way, but it might be a good plan to 
make an inline function to calculate the checksum there, just to make 
the clearer how it is done, and because we are going to need the same 
code in multiple places eventually,

Steve.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-19 10:53     ` Steven Whitehouse
@ 2018-01-19 12:19       ` Andrew Price
  2018-01-19 14:35         ` Andreas Gruenbacher
  0 siblings, 1 reply; 16+ messages in thread
From: Andrew Price @ 2018-01-19 12:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On 19/01/18 10:53, Steven Whitehouse wrote:
> On 19/01/18 10:47, Andrew Price wrote:
>> On 18/01/18 16:04, Andreas Gruenbacher wrote:
>> <snip>
>>> diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
>>> index c27cbcebfe88..a2eb13c04591 100644
>>> --- a/fs/gfs2/log.c
>>> +++ b/fs/gfs2/log.c
>>> @@ -14,6 +14,7 @@
>>> ? #include <linux/buffer_head.h>
>>> ? #include <linux/gfs2_ondisk.h>
>>> ? #include <linux/crc32.h>
>>> +#include <linux/crc32c.h>
>>> ? #include <linux/delay.h>
>>> ? #include <linux/kthread.h>
>>> ? #include <linux/freezer.h>
>>> @@ -653,20 +654,25 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
>>> ? /**
>>> ?? * write_log_header - Write a journal log header buffer at 
>>> sd_log_flush_head
>>> ?? * @sdp: The GFS2 superblock
>>> + * @jd: journal descriptor of the journal to which we are writing
>>> ?? * @seq: sequence number
>>> ?? * @tail: tail of the log
>>> - * @flags: log header flags
>>> + * @flags: log header flags GFS2_LOG_HEAD_*
>>> ?? * @op_flags: flags to pass to the bio
>>> ?? *
>>> ?? * Returns: the initialized log buffer descriptor
>>> ?? */
>>> ? -void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
>>> -?????????????? u32 flags, int op_flags)
>>> +void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
>>> +?????????????? u64 seq, u32 tail, u32 flags, int op_flags)
>>> ? {
>>> ????? struct gfs2_log_header *lh;
>>> -??? u32 hash;
>>> +??? u32 hash, crc;
>>> ????? struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
>>> +??? struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
>>> +??? struct timespec64 tv;
>>> +??? struct super_block *sb = sdp->sd_vfs;
>>> +??? u64 addr;
>>> ? ????? lh = page_address(page);
>>> ????? clear_page(lh);
>>> @@ -680,10 +686,39 @@ void gfs2_write_log_header(struct gfs2_sbd 
>>> *sdp, u64 seq, u32 tail,
>>> ????? lh->lh_flags = cpu_to_be32(flags);
>>> ????? lh->lh_tail = cpu_to_be32(tail);
>>> ????? lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
>>> -??? hash = ~crc32(~0, lh, sizeof(*lh));
>>> +??? hash = ~crc32(~0, lh, LH_V1_SIZE);
>>> ????? lh->lh_hash = cpu_to_be32(hash);
>>> ? -??? gfs2_log_write_page(sdp, page);
>>> +??? tv = current_kernel_time64();
>>> +??? lh->lh_nsec = cpu_to_be32(tv.tv_nsec);
>>> +??? lh->lh_sec = cpu_to_be64(tv.tv_sec);
>>> +??? addr = gfs2_log_bmap(sdp);
>>> +??? lh->lh_addr = cpu_to_be64(addr);
>>> +??? lh->lh_jinode = cpu_to_be64(GFS2_I(jd->jd_inode)->i_no_addr);
>>> +
>>> +??? /* We may only write local statfs, quota, etc., when writing to our
>>> +?????? own journal. The values are left 0 when recovering a journal
>>> +?????? different from our own. */
>>> +??? if (!(flags & GFS2_LOG_HEAD_RECOVERY)) {
>>> +??????? lh->lh_statfs_addr =
>>> + cpu_to_be64(GFS2_I(sdp->sd_sc_inode)->i_no_addr);
>>> +??????? lh->lh_quota_addr =
>>> + cpu_to_be64(GFS2_I(sdp->sd_qc_inode)->i_no_addr);
>>> +
>>> +??????? spin_lock(&sdp->sd_statfs_spin);
>>> +??????? lh->lh_local_total = cpu_to_be64(l_sc->sc_total);
>>> +??????? lh->lh_local_free = cpu_to_be64(l_sc->sc_free);
>>> +??????? lh->lh_local_dinodes = cpu_to_be64(l_sc->sc_dinodes);
>>> +??????? spin_unlock(&sdp->sd_statfs_spin);
>>> +??? }
>>> +
>>> +??? BUILD_BUG_ON(offsetof(struct gfs2_log_header, lh_crc) != 
>>> LH_V1_SIZE);
>>> +
>>> +??? crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
>>> +???????????? sb->s_blocksize - LH_V1_SIZE - 4);
>>> +??? lh->lh_crc = cpu_to_be32(crc);
>>
>> This seems to be at odds with the field comment:
>>
>> > +??? __be32 lh_crc;??????? /* crc32 of whole block with this field 0 */
>>
>> Is it really just CRCing the block from lh_crc + 4 onwards?
>>
>> Andy
>>
> Yes, the comment needs updating to match the code, if we are going to do 
> that. I'm not too concerned either way, but it might be a good plan to 
> make an inline function to calculate the checksum there, just to make 
> the clearer how it is done, and because we are going to need the same 
> code in multiple places eventually,

Thanks for clarifying. I have another query: in the gfs2_jadd case the 
new journal is written via an fd so the lh_addr is unknown when writing 
the log headers it initialises the journal with. Is it ok to leave that 
zero?

Andy



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
  2018-01-19 10:47   ` Andrew Price
@ 2018-01-19 14:31   ` Andrew Price
  2018-01-19 14:39     ` Steven Whitehouse
  2018-01-19 20:06     ` Andrew Price
  1 sibling, 2 replies; 16+ messages in thread
From: Andrew Price @ 2018-01-19 14:31 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On 18/01/18 16:04, Andreas Gruenbacher wrote:> diff --git 
a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h
> index 09f0920f07e9..7eb73c32272f 100644
> --- a/include/uapi/linux/gfs2_ondisk.h
> +++ b/include/uapi/linux/gfs2_ondisk.h
> @@ -403,7 +403,15 @@ struct gfs2_ea_header {
>    * Log header structure
>    */
>   
> -#define GFS2_LOG_HEAD_UNMOUNT	0x00000001	/* log is clean */
> +#define GFS2_LOG_HEAD_UNMOUNT		0x00000001 /* log is clean */
> +#define GFS2_LOG_HEAD_FLUSH_NORMAL	0x00000002 /* normal log flush */
> +#define GFS2_LOG_HEAD_FLUSH_SYNC	0x00000004 /* Sync log flush */
> +#define GFS2_LOG_HEAD_FLUSH_SHUTDOWN	0x00000008 /* Shutdown log flush */
> +#define GFS2_LOG_HEAD_FLUSH_FREEZE	0x00000010 /* Freeze flush */
> +#define GFS2_LOG_HEAD_RECOVERY		0x00000020 /* Journal recovery */
> +#define GFS2_LOG_HEAD_USERSPACE		0x80000000 /* Written by gfs2-utils */
> +
> +#define LH_V1_SIZE (offsetofend(struct gfs2_log_header, lh_hash))
>   
>   struct gfs2_log_header {
>   	struct gfs2_meta_header lh_header;
> @@ -413,6 +421,21 @@ struct gfs2_log_header {
>   	__be32 lh_tail;		/* Block number of log tail */
>   	__be32 lh_blkno;
>   	__be32 lh_hash;
> +
> +	/* Version 2 additional fields start here */
> +	__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 addr 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_origin;	/* The origin of this log header */
>   };

4 bytes of padding gets added at the end of the struct. Could it be made 
explicit with a __pad field? It currently breaks the metadata 
description test with "gfs2_log_header: size mismatch between struct 128 
and fields 124".

I've pushed a gfs2-utils patch with basic support for the new log header 
format to the andyp-lhv2 branch. I need to test it some more but it 
should be useful for testing these patches already. I'll finalise it 
once the v2 patches are in for-next.

Andy



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-19 12:19       ` Andrew Price
@ 2018-01-19 14:35         ` Andreas Gruenbacher
  0 siblings, 0 replies; 16+ messages in thread
From: Andreas Gruenbacher @ 2018-01-19 14:35 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On 19 January 2018 at 13:19, Andrew Price <anprice@redhat.com> wrote:
> On 19/01/18 10:53, Steven Whitehouse wrote:
>>
>> On 19/01/18 10:47, Andrew Price wrote:
>>>
>>> On 18/01/18 16:04, Andreas Gruenbacher wrote:
>>> <snip>
>>>>
>>>> diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
>>>> index c27cbcebfe88..a2eb13c04591 100644
>>>> --- a/fs/gfs2/log.c
>>>> +++ b/fs/gfs2/log.c
>>>> @@ -14,6 +14,7 @@
>>>>   #include <linux/buffer_head.h>
>>>>   #include <linux/gfs2_ondisk.h>
>>>>   #include <linux/crc32.h>
>>>> +#include <linux/crc32c.h>
>>>>   #include <linux/delay.h>
>>>>   #include <linux/kthread.h>
>>>>   #include <linux/freezer.h>
>>>> @@ -653,20 +654,25 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
>>>>   /**
>>>>    * write_log_header - Write a journal log header buffer at
>>>> sd_log_flush_head
>>>>    * @sdp: The GFS2 superblock
>>>> + * @jd: journal descriptor of the journal to which we are writing
>>>>    * @seq: sequence number
>>>>    * @tail: tail of the log
>>>> - * @flags: log header flags
>>>> + * @flags: log header flags GFS2_LOG_HEAD_*
>>>>    * @op_flags: flags to pass to the bio
>>>>    *
>>>>    * Returns: the initialized log buffer descriptor
>>>>    */
>>>>   -void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
>>>> -               u32 flags, int op_flags)
>>>> +void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
>>>> +               u64 seq, u32 tail, u32 flags, int op_flags)
>>>>   {
>>>>       struct gfs2_log_header *lh;
>>>> -    u32 hash;
>>>> +    u32 hash, crc;
>>>>       struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
>>>> +    struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
>>>> +    struct timespec64 tv;
>>>> +    struct super_block *sb = sdp->sd_vfs;
>>>> +    u64 addr;
>>>>         lh = page_address(page);
>>>>       clear_page(lh);
>>>> @@ -680,10 +686,39 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp,
>>>> u64 seq, u32 tail,
>>>>       lh->lh_flags = cpu_to_be32(flags);
>>>>       lh->lh_tail = cpu_to_be32(tail);
>>>>       lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
>>>> -    hash = ~crc32(~0, lh, sizeof(*lh));
>>>> +    hash = ~crc32(~0, lh, LH_V1_SIZE);
>>>>       lh->lh_hash = cpu_to_be32(hash);
>>>>   -    gfs2_log_write_page(sdp, page);
>>>> +    tv = current_kernel_time64();
>>>> +    lh->lh_nsec = cpu_to_be32(tv.tv_nsec);
>>>> +    lh->lh_sec = cpu_to_be64(tv.tv_sec);
>>>> +    addr = gfs2_log_bmap(sdp);
>>>> +    lh->lh_addr = cpu_to_be64(addr);
>>>> +    lh->lh_jinode = cpu_to_be64(GFS2_I(jd->jd_inode)->i_no_addr);
>>>> +
>>>> +    /* We may only write local statfs, quota, etc., when writing to our
>>>> +       own journal. The values are left 0 when recovering a journal
>>>> +       different from our own. */
>>>> +    if (!(flags & GFS2_LOG_HEAD_RECOVERY)) {
>>>> +        lh->lh_statfs_addr =
>>>> + cpu_to_be64(GFS2_I(sdp->sd_sc_inode)->i_no_addr);
>>>> +        lh->lh_quota_addr =
>>>> + cpu_to_be64(GFS2_I(sdp->sd_qc_inode)->i_no_addr);
>>>> +
>>>> +        spin_lock(&sdp->sd_statfs_spin);
>>>> +        lh->lh_local_total = cpu_to_be64(l_sc->sc_total);
>>>> +        lh->lh_local_free = cpu_to_be64(l_sc->sc_free);
>>>> +        lh->lh_local_dinodes = cpu_to_be64(l_sc->sc_dinodes);
>>>> +        spin_unlock(&sdp->sd_statfs_spin);
>>>> +    }
>>>> +
>>>> +    BUILD_BUG_ON(offsetof(struct gfs2_log_header, lh_crc) !=
>>>> LH_V1_SIZE);
>>>> +
>>>> +    crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
>>>> +             sb->s_blocksize - LH_V1_SIZE - 4);
>>>> +    lh->lh_crc = cpu_to_be32(crc);
>>>
>>>
>>> This seems to be at odds with the field comment:
>>>
>>> > +    __be32 lh_crc;        /* crc32 of whole block with this field 0 */
>>>
>>> Is it really just CRCing the block from lh_crc + 4 onwards?
>>>
>>> Andy
>>>
>> Yes, the comment needs updating to match the code, if we are going to do
>> that. I'm not too concerned either way, but it might be a good plan to make
>> an inline function to calculate the checksum there, just to make the clearer
>> how it is done, and because we are going to need the same code in multiple
>> places eventually,

I'll do that and add the necessary padding at the end as well.

> Thanks for clarifying. I have another query: in the gfs2_jadd case the new
> journal is written via an fd so the lh_addr is unknown when writing the log
> headers it initialises the journal with. Is it ok to leave that zero?

Right now, no. You can easily find out the physical blocks with the
FS_IOC_FIEMAP ioctl though, will that work?

Thanks,
Andreas



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-19 14:31   ` Andrew Price
@ 2018-01-19 14:39     ` Steven Whitehouse
  2018-01-19 15:06       ` Andrew Price
  2018-01-19 20:06     ` Andrew Price
  1 sibling, 1 reply; 16+ messages in thread
From: Steven Whitehouse @ 2018-01-19 14:39 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,


On 19/01/18 14:31, Andrew Price wrote:
> On 18/01/18 16:04, Andreas Gruenbacher wrote:> diff --git 
> a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h
>> index 09f0920f07e9..7eb73c32272f 100644
>> --- a/include/uapi/linux/gfs2_ondisk.h
>> +++ b/include/uapi/linux/gfs2_ondisk.h
>> @@ -403,7 +403,15 @@ struct gfs2_ea_header {
>> ?? * Log header structure
>> ?? */
>> ? -#define GFS2_LOG_HEAD_UNMOUNT??? 0x00000001??? /* log is clean */
>> +#define GFS2_LOG_HEAD_UNMOUNT??????? 0x00000001 /* log is clean */
>> +#define GFS2_LOG_HEAD_FLUSH_NORMAL??? 0x00000002 /* normal log flush */
>> +#define GFS2_LOG_HEAD_FLUSH_SYNC??? 0x00000004 /* Sync log flush */
>> +#define GFS2_LOG_HEAD_FLUSH_SHUTDOWN??? 0x00000008 /* Shutdown log 
>> flush */
>> +#define GFS2_LOG_HEAD_FLUSH_FREEZE??? 0x00000010 /* Freeze flush */
>> +#define GFS2_LOG_HEAD_RECOVERY??????? 0x00000020 /* Journal recovery */
>> +#define GFS2_LOG_HEAD_USERSPACE??????? 0x80000000 /* Written by 
>> gfs2-utils */
>> +
>> +#define LH_V1_SIZE (offsetofend(struct gfs2_log_header, lh_hash))
>> ? ? struct gfs2_log_header {
>> ????? struct gfs2_meta_header lh_header;
>> @@ -413,6 +421,21 @@ struct gfs2_log_header {
>> ????? __be32 lh_tail;??????? /* Block number of log tail */
>> ????? __be32 lh_blkno;
>> ????? __be32 lh_hash;
>> +
>> +??? /* Version 2 additional fields start here */
>> +??? __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 addr 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_origin;??? /* The origin of this log header */
>> ? };
>
> 4 bytes of padding gets added at the end of the struct. Could it be 
> made explicit with a __pad field? It currently breaks the metadata 
> description test with "gfs2_log_header: size mismatch between struct 
> 128 and fields 124".
>
> I've pushed a gfs2-utils patch with basic support for the new log 
> header format to the andyp-lhv2 branch. I need to test it some more 
> but it should be useful for testing these patches already. I'll 
> finalise it once the v2 patches are in for-next.
>
> Andy
>
It could, however nothing follows the structure, so it isn't generally 
needed, and I suspect that the test was expecting all the structures to 
be of fixed size (which all the others are). Still, it might be the 
easiest way to fix that test unless we can find another solution?

Steve.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v6] GFS2: Introduce new gfs2_log_header_v2
  2018-01-18 16:04 [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
                   ` (3 preceding siblings ...)
  2018-01-18 16:23 ` [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2 Steven Whitehouse
@ 2018-01-19 14:40 ` Andreas Gruenbacher
  2018-01-19 15:14   ` Andrew Price
  4 siblings, 1 reply; 16+ messages in thread
From: Andreas Gruenbacher @ 2018-01-19 14:40 UTC (permalink / raw)
  To: cluster-devel.redhat.com

From: Bob Peterson <rpeterso@redhat.com>

Changes from v5:

 * Fix struct gfs2_log_header comments.
 * Add missing padding at the end of struct gfs2_log_header.

Thanks,
Andreas

--

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
(i.e., this change is backwards compatible).  Some of these are used for
debug purposes so we can backtrack when problems occur.  Others are
reserved for future expansion.

This patch is based on a prototype from Steve Whitehouse.

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
 fs/gfs2/aops.c                   |  2 +-
 fs/gfs2/file.c                   |  3 +-
 fs/gfs2/glops.c                  | 13 +++----
 fs/gfs2/log.c                    | 75 ++++++++++++++++++++++++++++++----------
 fs/gfs2/log.h                    | 12 ++-----
 fs/gfs2/lops.c                   | 16 +++++----
 fs/gfs2/lops.h                   |  3 ++
 fs/gfs2/ops_fstype.c             |  2 +-
 fs/gfs2/quota.c                  |  3 +-
 fs/gfs2/recovery.c               | 17 +++++----
 fs/gfs2/rgrp.c                   |  2 +-
 fs/gfs2/super.c                  |  9 ++---
 fs/gfs2/trans.c                  |  2 +-
 include/uapi/linux/gfs2_ondisk.h | 28 +++++++++++++--
 14 files changed, 128 insertions(+), 59 deletions(-)

diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 658ca027cab9..7c64925735d3 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -445,7 +445,7 @@ static int gfs2_jdata_writepages(struct address_space *mapping,
 
 	ret = gfs2_write_cache_jdata(mapping, wbc);
 	if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) {
-		gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH);
+		gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
 		ret = gfs2_write_cache_jdata(mapping, wbc);
 	}
 	return ret;
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index bd60dc682676..7a02b4e6e9f3 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -246,7 +246,8 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
 	}
 	if ((flags ^ new_flags) & GFS2_DIF_JDATA) {
 		if (new_flags & GFS2_DIF_JDATA)
-			gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH);
+			gfs2_log_flush(sdp, ip->i_gl,
+				       GFS2_LOG_HEAD_FLUSH_NORMAL);
 		error = filemap_fdatawrite(inode->i_mapping);
 		if (error)
 			goto out;
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index cdd1c5f06f45..2daab13a9e0b 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -107,7 +107,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 	__gfs2_ail_flush(gl, 0, tr.tr_revokes);
 
 	gfs2_trans_end(sdp);
-	gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 }
 
 void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
@@ -128,7 +128,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 		return;
 	__gfs2_ail_flush(gl, fsync, max_revokes);
 	gfs2_trans_end(sdp);
-	gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 }
 
 /**
@@ -157,7 +157,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
 		return;
 	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
-	gfs2_log_flush(sdp, gl, NORMAL_FLUSH);
+	gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
 	error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
 	mapping_set_error(mapping, error);
@@ -252,7 +252,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
 
 	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
-	gfs2_log_flush(gl->gl_name.ln_sbd, gl, NORMAL_FLUSH);
+	gfs2_log_flush(gl->gl_name.ln_sbd, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	filemap_fdatawrite(metamapping);
 	if (isreg) {
 		struct address_space *mapping = ip->i_inode.i_mapping;
@@ -303,7 +303,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 	}
 
 	if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) {
-		gfs2_log_flush(gl->gl_name.ln_sbd, NULL, NORMAL_FLUSH);
+		gfs2_log_flush(gl->gl_name.ln_sbd, NULL,
+			       GFS2_LOG_HEAD_FLUSH_NORMAL);
 		gl->gl_name.ln_sbd->sd_rindex_uptodate = 0;
 	}
 	if (ip && S_ISREG(ip->i_inode.i_mode))
@@ -495,7 +496,7 @@ static void freeze_go_sync(struct gfs2_glock *gl)
 			gfs2_assert_withdraw(sdp, 0);
 		}
 		queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
-		gfs2_log_flush(sdp, NULL, FREEZE_FLUSH);
+		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE);
 	}
 }
 
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index c27cbcebfe88..a2eb13c04591 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -14,6 +14,7 @@
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
+#include <linux/crc32c.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
@@ -653,20 +654,25 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
 /**
  * write_log_header - Write a journal log header buffer at sd_log_flush_head
  * @sdp: The GFS2 superblock
+ * @jd: journal descriptor of the journal to which we are writing
  * @seq: sequence number
  * @tail: tail of the log
- * @flags: log header flags
+ * @flags: log header flags GFS2_LOG_HEAD_*
  * @op_flags: flags to pass to the bio
  *
  * Returns: the initialized log buffer descriptor
  */
 
-void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
-			   u32 flags, int op_flags)
+void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
+			   u64 seq, u32 tail, u32 flags, int op_flags)
 {
 	struct gfs2_log_header *lh;
-	u32 hash;
+	u32 hash, crc;
 	struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
+	struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+	struct timespec64 tv;
+	struct super_block *sb = sdp->sd_vfs;
+	u64 addr;
 
 	lh = page_address(page);
 	clear_page(lh);
@@ -680,10 +686,39 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
 	lh->lh_flags = cpu_to_be32(flags);
 	lh->lh_tail = cpu_to_be32(tail);
 	lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
-	hash = ~crc32(~0, lh, sizeof(*lh));
+	hash = ~crc32(~0, lh, LH_V1_SIZE);
 	lh->lh_hash = cpu_to_be32(hash);
 
-	gfs2_log_write_page(sdp, page);
+	tv = current_kernel_time64();
+	lh->lh_nsec = cpu_to_be32(tv.tv_nsec);
+	lh->lh_sec = cpu_to_be64(tv.tv_sec);
+	addr = gfs2_log_bmap(sdp);
+	lh->lh_addr = cpu_to_be64(addr);
+	lh->lh_jinode = cpu_to_be64(GFS2_I(jd->jd_inode)->i_no_addr);
+
+	/* We may only write local statfs, quota, etc., when writing to our
+	   own journal. The values are left 0 when recovering a journal
+	   different from our own. */
+	if (!(flags & GFS2_LOG_HEAD_RECOVERY)) {
+		lh->lh_statfs_addr =
+			cpu_to_be64(GFS2_I(sdp->sd_sc_inode)->i_no_addr);
+		lh->lh_quota_addr =
+			cpu_to_be64(GFS2_I(sdp->sd_qc_inode)->i_no_addr);
+
+		spin_lock(&sdp->sd_statfs_spin);
+		lh->lh_local_total = cpu_to_be64(l_sc->sc_total);
+		lh->lh_local_free = cpu_to_be64(l_sc->sc_free);
+		lh->lh_local_dinodes = cpu_to_be64(l_sc->sc_dinodes);
+		spin_unlock(&sdp->sd_statfs_spin);
+	}
+
+	BUILD_BUG_ON(offsetof(struct gfs2_log_header, lh_crc) != LH_V1_SIZE);
+
+	crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
+		     sb->s_blocksize - LH_V1_SIZE - 4);
+	lh->lh_crc = cpu_to_be32(crc);
+
+	gfs2_log_write(sdp, page, sb->s_blocksize, 0, addr);
 	gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags);
 	log_flush_wait(sdp);
 }
@@ -691,6 +726,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
 /**
  * log_write_header - Get and initialize a journal header buffer
  * @sdp: The GFS2 superblock
+ * @flags: The log header flags, including log header origin
  *
  * Returns: the initialized log buffer descriptor
  */
@@ -710,8 +746,8 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
 		op_flags = REQ_SYNC | REQ_META | REQ_PRIO;
 	}
 	sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
-	gfs2_write_log_header(sdp, sdp->sd_log_sequence++, tail, flags,
-			      op_flags);
+	gfs2_write_log_header(sdp, sdp->sd_jdesc, sdp->sd_log_sequence++, tail,
+			      flags, op_flags);
 
 	if (sdp->sd_log_tail != tail)
 		log_pull_tail(sdp, tail);
@@ -721,11 +757,11 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
  * gfs2_log_flush - flush incore transaction(s)
  * @sdp: the filesystem
  * @gl: The glock structure to flush.  If NULL, flush the whole incore log
+ * @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_*
  *
  */
 
-void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
-		    enum gfs2_flush_type type)
+void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
 {
 	struct gfs2_trans *tr;
 	enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state);
@@ -739,7 +775,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
 	}
 	trace_gfs2_log_flush(sdp, 1);
 
-	if (type == SHUTDOWN_FLUSH)
+	if (flags & GFS2_LOG_HEAD_FLUSH_SHUTDOWN)
 		clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
 
 	sdp->sd_log_flush_head = sdp->sd_log_head;
@@ -764,11 +800,11 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
 
 	if (sdp->sd_log_head != sdp->sd_log_flush_head) {
 		log_flush_wait(sdp);
-		log_write_header(sdp, 0);
+		log_write_header(sdp, flags);
 	} else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
 		atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
 		trace_gfs2_log_blocks(sdp, -1);
-		log_write_header(sdp, 0);
+		log_write_header(sdp, flags);
 	}
 	lops_after_commit(sdp, tr);
 
@@ -785,7 +821,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
 	spin_unlock(&sdp->sd_ail_lock);
 	gfs2_log_unlock(sdp);
 
-	if (type != NORMAL_FLUSH) {
+	if (!(flags & GFS2_LOG_HEAD_FLUSH_NORMAL)) {
 		if (!sdp->sd_log_idle) {
 			for (;;) {
 				gfs2_ail1_start(sdp);
@@ -795,12 +831,13 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
 			}
 			atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
 			trace_gfs2_log_blocks(sdp, -1);
-			log_write_header(sdp, 0);
+			log_write_header(sdp, flags);
 			sdp->sd_log_head = sdp->sd_log_flush_head;
 		}
-		if (type == SHUTDOWN_FLUSH || type == FREEZE_FLUSH)
+		if (flags & (GFS2_LOG_HEAD_FLUSH_SHUTDOWN |
+			     GFS2_LOG_HEAD_FLUSH_FREEZE))
 			gfs2_log_shutdown(sdp);
-		if (type == FREEZE_FLUSH)
+		if (flags & GFS2_LOG_HEAD_FLUSH_FREEZE)
 			atomic_set(&sdp->sd_freeze_state, SFS_FROZEN);
 	}
 
@@ -956,7 +993,7 @@ int gfs2_logd(void *data)
 		did_flush = false;
 		if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
 			gfs2_ail1_empty(sdp);
-			gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 			did_flush = true;
 		}
 
@@ -964,7 +1001,7 @@ int gfs2_logd(void *data)
 			gfs2_ail1_start(sdp);
 			gfs2_ail1_wait(sdp);
 			gfs2_ail1_empty(sdp);
-			gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 			did_flush = true;
 		}
 
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h
index 619de9a1ff4f..93b52ac1ca1f 100644
--- a/fs/gfs2/log.h
+++ b/fs/gfs2/log.h
@@ -65,16 +65,10 @@ extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
 
 extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks);
 extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
-enum gfs2_flush_type {
-	NORMAL_FLUSH = 0,
-	SYNC_FLUSH,
-	SHUTDOWN_FLUSH,
-	FREEZE_FLUSH
-};
-extern void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
-				  u32 flags, int op_flags);
+extern void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
+				  u64 seq, u32 tail, u32 flags, int op_flags);
 extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
-			   enum gfs2_flush_type type);
+			   u32 type);
 extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
 extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
 extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index c8ff7b7954f0..4a60221c678f 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"
@@ -138,7 +139,7 @@ static void gfs2_log_incr_head(struct gfs2_sbd *sdp)
 		sdp->sd_log_flush_head = 0;
 }
 
-static u64 gfs2_log_bmap(struct gfs2_sbd *sdp)
+u64 gfs2_log_bmap(struct gfs2_sbd *sdp)
 {
 	unsigned int lbn = sdp->sd_log_flush_head;
 	struct gfs2_journal_extent *je;
@@ -306,23 +307,22 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno)
 	return gfs2_log_alloc_bio(sdp, blkno);
 }
 
-
 /**
  * gfs2_log_write - write to log
  * @sdp: the filesystem
  * @page: the page to write
  * @size: the size of the data to write
  * @offset: the offset within the page 
+ * @blkno: block number of the log entry
  *
  * Try and add the page segment to the current bio. If that fails,
  * submit the current bio to the device and create a new one, and
  * then add the page segment to that.
  */
 
-static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
-			   unsigned size, unsigned offset)
+void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
+		    unsigned size, unsigned offset, u64 blkno)
 {
-	u64 blkno = gfs2_log_bmap(sdp);
 	struct bio *bio;
 	int ret;
 
@@ -348,7 +348,8 @@ 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),
+		       gfs2_log_bmap(sdp));
 }
 
 /**
@@ -365,7 +366,8 @@ 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,
+		       gfs2_log_bmap(sdp));
 }
 
 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..e4949394f054 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -26,6 +26,9 @@ extern const struct gfs2_log_operations gfs2_revoke_lops;
 extern const struct gfs2_log_operations gfs2_databuf_lops;
 
 extern const struct gfs2_log_operations *gfs2_log_ops[];
+extern u64 gfs2_log_bmap(struct gfs2_sbd *sdp);
+extern void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
+			   unsigned size, unsigned offset, u64 blkno);
 extern void gfs2_log_write_page(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/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index ad55eb86a250..d6e620beb9db 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1382,7 +1382,7 @@ static void gfs2_kill_sb(struct super_block *sb)
 		return;
 	}
 
-	gfs2_log_flush(sdp, NULL, SYNC_FLUSH);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SYNC);
 	dput(sdp->sd_root_dir);
 	dput(sdp->sd_master_dir);
 	sdp->sd_root_dir = NULL;
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index e700fb162664..2092df19e433 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -955,7 +955,8 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
 		gfs2_glock_dq_uninit(&ghs[qx]);
 	inode_unlock(&ip->i_inode);
 	kfree(ghs);
-	gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl, NORMAL_FLUSH);
+	gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl,
+		       GFS2_LOG_HEAD_FLUSH_NORMAL);
 	return error;
 }
 
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 975f32166dfe..b6b258998bcd 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -14,6 +14,7 @@
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
+#include <linux/crc32c.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -137,7 +138,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
 {
 	struct gfs2_log_header *lh;
 	struct buffer_head *bh;
-	u32 hash;
+	u32 hash, crc;
 	int error;
 
 	error = gfs2_replay_read_block(jd, blk, &bh);
@@ -145,13 +146,17 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
 		return error;
 	lh = (void *)bh->b_data;
 
-	hash = crc32(~0, lh, sizeof(*lh) - 4);
+	hash = crc32(~0, lh, LH_V1_SIZE - 4);
 	hash = ~crc32_le_shift(hash, 4);  /* assume lh_hash is zero */
 
+	crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
+		     bh->b_size - LH_V1_SIZE - 4);
+
 	error = lh->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
 		lh->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH) ||
 		be32_to_cpu(lh->lh_blkno) != blk ||
-		be32_to_cpu(lh->lh_hash) != hash;
+		be32_to_cpu(lh->lh_hash) != hash ||
+		(lh->lh_crc != 0 && be32_to_cpu(lh->lh_crc) != crc);
 
 	brelse(bh);
 
@@ -372,9 +377,9 @@ static void clean_journal(struct gfs2_jdesc *jd,
 
 	sdp->sd_log_flush_head = head->lh_blkno;
 	gfs2_replay_incr_blk(jd, &sdp->sd_log_flush_head);
-	gfs2_write_log_header(sdp, head->lh_sequence + 1, 0,
-			      GFS2_LOG_HEAD_UNMOUNT, REQ_PREFLUSH |
-			      REQ_FUA | REQ_META | REQ_SYNC);
+	gfs2_write_log_header(sdp, jd, head->lh_sequence + 1, 0,
+			      GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_RECOVERY,
+			      REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC);
 }
 
 
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 6dea72f49316..00eab6c0525c 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -2093,7 +2093,7 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, struct gfs2_alloc_parms *ap)
 		}
 		/* Flushing the log may release space */
 		if (loops == 2)
-			gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	}
 
 	return -ENOSPC;
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index d81d46e19726..fa3a19eaf0eb 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -757,7 +757,8 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc)
 	bool flush_all = (wbc->sync_mode == WB_SYNC_ALL || gfs2_is_jdata(ip));
 
 	if (flush_all)
-		gfs2_log_flush(GFS2_SB(inode), ip->i_gl, NORMAL_FLUSH);
+		gfs2_log_flush(GFS2_SB(inode), ip->i_gl,
+			       GFS2_LOG_HEAD_FLUSH_NORMAL);
 	if (bdi->wb.dirty_exceeded)
 		gfs2_ail1_flush(sdp, wbc);
 	else
@@ -853,7 +854,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
 	gfs2_quota_sync(sdp->sd_vfs, 0);
 	gfs2_statfs_sync(sdp->sd_vfs, 0);
 
-	gfs2_log_flush(sdp, NULL, SHUTDOWN_FLUSH);
+	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN);
 	wait_event(sdp->sd_reserving_log_wait, atomic_read(&sdp->sd_reserving_log) == 0);
 	gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
 
@@ -946,7 +947,7 @@ static int gfs2_sync_fs(struct super_block *sb, int wait)
 
 	gfs2_quota_sync(sb, -1);
 	if (wait)
-		gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	return sdp->sd_log_error;
 }
 
@@ -1650,7 +1651,7 @@ static void gfs2_evict_inode(struct inode *inode)
 	goto out_unlock;
 
 out_truncate:
-	gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH);
+	gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	metamapping = gfs2_glock2aspace(ip->i_gl);
 	if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) {
 		filemap_fdatawrite(metamapping);
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index b95ebd166cac..7aec6d3434fa 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -117,7 +117,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp)
 	up_read(&sdp->sd_log_flush_lock);
 
 	if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS)
-		gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
+		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
 	if (alloced)
 		sb_end_intwrite(sdp->sd_vfs);
 }
diff --git a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h
index 09f0920f07e9..eff5c158805d 100644
--- a/include/uapi/linux/gfs2_ondisk.h
+++ b/include/uapi/linux/gfs2_ondisk.h
@@ -403,7 +403,15 @@ struct gfs2_ea_header {
  * Log header structure
  */
 
-#define GFS2_LOG_HEAD_UNMOUNT	0x00000001	/* log is clean */
+#define GFS2_LOG_HEAD_UNMOUNT		0x00000001 /* log is clean */
+#define GFS2_LOG_HEAD_FLUSH_NORMAL	0x00000002 /* normal log flush */
+#define GFS2_LOG_HEAD_FLUSH_SYNC	0x00000004 /* Sync log flush */
+#define GFS2_LOG_HEAD_FLUSH_SHUTDOWN	0x00000008 /* Shutdown log flush */
+#define GFS2_LOG_HEAD_FLUSH_FREEZE	0x00000010 /* Freeze flush */
+#define GFS2_LOG_HEAD_RECOVERY		0x00000020 /* Journal recovery */
+#define GFS2_LOG_HEAD_USERSPACE		0x80000000 /* Written by gfs2-utils */
+
+#define LH_V1_SIZE (offsetofend(struct gfs2_log_header, lh_hash))
 
 struct gfs2_log_header {
 	struct gfs2_meta_header lh_header;
@@ -412,7 +420,23 @@ struct gfs2_log_header {
 	__be32 lh_flags;	/* GFS2_LOG_HEAD_... */
 	__be32 lh_tail;		/* Block number of log tail */
 	__be32 lh_blkno;
-	__be32 lh_hash;
+	__be32 lh_hash;		/* crc up to here with this field 0 */
+
+	/* Version 2 additional fields start here */
+	__be32 lh_crc;		/* crc32c from lh_nsec to end of block */
+	__be32 lh_nsec;		/* Nanoseconds of timestamp */
+	__be64 lh_sec;		/* Seconds of timestamp */
+	__be64 lh_addr;		/* Block addr 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_origin;	/* The origin of this log header */
+	__be32 __pad;
 };
 
 /*
-- 
2.14.3



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-19 14:39     ` Steven Whitehouse
@ 2018-01-19 15:06       ` Andrew Price
  0 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2018-01-19 15:06 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On 19/01/18 14:39, Steven Whitehouse wrote:
> On 19/01/18 14:31, Andrew Price wrote:
>> On 18/01/18 16:04, Andreas Gruenbacher wrote:> diff --git 
>> a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h
>>> index 09f0920f07e9..7eb73c32272f 100644
>>> --- a/include/uapi/linux/gfs2_ondisk.h
>>> +++ b/include/uapi/linux/gfs2_ondisk.h
>>> @@ -403,7 +403,15 @@ struct gfs2_ea_header {
>>> ?? * Log header structure
>>> ?? */
>>> ? -#define GFS2_LOG_HEAD_UNMOUNT??? 0x00000001??? /* log is clean */
>>> +#define GFS2_LOG_HEAD_UNMOUNT??????? 0x00000001 /* log is clean */
>>> +#define GFS2_LOG_HEAD_FLUSH_NORMAL??? 0x00000002 /* normal log flush */
>>> +#define GFS2_LOG_HEAD_FLUSH_SYNC??? 0x00000004 /* Sync log flush */
>>> +#define GFS2_LOG_HEAD_FLUSH_SHUTDOWN??? 0x00000008 /* Shutdown log 
>>> flush */
>>> +#define GFS2_LOG_HEAD_FLUSH_FREEZE??? 0x00000010 /* Freeze flush */
>>> +#define GFS2_LOG_HEAD_RECOVERY??????? 0x00000020 /* Journal recovery */
>>> +#define GFS2_LOG_HEAD_USERSPACE??????? 0x80000000 /* Written by 
>>> gfs2-utils */
>>> +
>>> +#define LH_V1_SIZE (offsetofend(struct gfs2_log_header, lh_hash))
>>> ? ? struct gfs2_log_header {
>>> ????? struct gfs2_meta_header lh_header;
>>> @@ -413,6 +421,21 @@ struct gfs2_log_header {
>>> ????? __be32 lh_tail;??????? /* Block number of log tail */
>>> ????? __be32 lh_blkno;
>>> ????? __be32 lh_hash;
>>> +
>>> +??? /* Version 2 additional fields start here */
>>> +??? __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 addr 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_origin;??? /* The origin of this log header */
>>> ? };
>>
>> 4 bytes of padding gets added at the end of the struct. Could it be 
>> made explicit with a __pad field? It currently breaks the metadata 
>> description test with "gfs2_log_header: size mismatch between struct 
>> 128 and fields 124".
>>
>> I've pushed a gfs2-utils patch with basic support for the new log 
>> header format to the andyp-lhv2 branch. I need to test it some more 
>> but it should be useful for testing these patches already. I'll 
>> finalise it once the v2 patches are in for-next.
>>
>> Andy
>>
> It could, however nothing follows the structure, so it isn't generally 
> needed, and I suspect that the test was expecting all the structures to 
> be of fixed size (which all the others are). 

Yes, the test is checking for holes in the structure while also checking 
that the metadata description is complete.

> Still, it might be the 
> easiest way to fix that test unless we can find another solution?

Well we could update the metadata description so that we can declare 
intentional holes that it shouldn't try to dereference. Something like 
the patch below should do it. But if adding the __pad field doesn't 
cause any issues, I don't see why we shouldn't do it that way.

Andy

diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 85ac74cb..a09a4b37 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -130,6 +130,7 @@ struct lgfs2_metafield {
  #define LGFS2_MFF_NSECS    0x04000     /* Units are nsecs */
  #define LGFS2_MFF_MAJOR    0x08000     /* Major device number */
  #define LGFS2_MFF_MINOR    0x10000     /* Minor device number */
+#define LGFS2_MFF_HOLE     0x20000     /* Minor device number */

         /* If it is a pointer, then this field must be set */
         const unsigned points_to;
diff --git a/gfs2/libgfs2/meta.c b/gfs2/libgfs2/meta.c
index e7a2226a..163d9d38 100644
--- a/gfs2/libgfs2/meta.c
+++ b/gfs2/libgfs2/meta.c
@@ -118,7 +118,10 @@ const unsigned int lgfs2_ld1_type_size = 
ARRAY_SIZE(lgfs2_ld1_types);

  #define INR(f,...) RF(f.no_formal_ino) \
                    RFP(f.no_addr, __VA_ARGS__)
-
+#define HOLE(sz, prevf) \
+              { .name = "(hole)", \
+                .offset = offsetof(struct STRUCT, prevf) + 
sizeof(((struct STRUCT *)(0))->prevf), \
+                .length = sz, .flags = LGFS2_MFF_HOLE },
  #define ANY_COMMON_BLOCK (1 << LGFS2_MT_DIR_LEAF) | \
                          (1 << LGFS2_MT_JRNL_DATA) | \
                          (1 << LGFS2_MT_EA_ATTR) | \
@@ -375,6 +378,7 @@ F(lh_local_total, .flags = LGFS2_MFF_FSBLOCKS)
  F(lh_local_free, .flags = LGFS2_MFF_FSBLOCKS)
  F(lh_local_dinodes, .flags = LGFS2_MFF_FSBLOCKS)
  F(lh_log_origin)
+HOLE(4, lh_log_origin)
  #endif
  };



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v6] GFS2: Introduce new gfs2_log_header_v2
  2018-01-19 14:40 ` [Cluster-devel] [PATCH v6] " Andreas Gruenbacher
@ 2018-01-19 15:14   ` Andrew Price
  0 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2018-01-19 15:14 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On 19/01/18 14:40, Andreas Gruenbacher wrote:
> From: Bob Peterson <rpeterso@redhat.com>
> 
> Changes from v5:
> 
>   * Fix struct gfs2_log_header comments.
>   * Add missing padding at the end of struct gfs2_log_header.
> 
> Thanks,
> Andreas

Looks good, thanks!

Andy

> --
> 
> 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
> (i.e., this change is backwards compatible).  Some of these are used for
> debug purposes so we can backtrack when problems occur.  Others are
> reserved for future expansion.
> 
> This patch is based on a prototype from Steve Whitehouse.
> 
> Signed-off-by: Bob Peterson <rpeterso@redhat.com>
> ---
>   fs/gfs2/aops.c                   |  2 +-
>   fs/gfs2/file.c                   |  3 +-
>   fs/gfs2/glops.c                  | 13 +++----
>   fs/gfs2/log.c                    | 75 ++++++++++++++++++++++++++++++----------
>   fs/gfs2/log.h                    | 12 ++-----
>   fs/gfs2/lops.c                   | 16 +++++----
>   fs/gfs2/lops.h                   |  3 ++
>   fs/gfs2/ops_fstype.c             |  2 +-
>   fs/gfs2/quota.c                  |  3 +-
>   fs/gfs2/recovery.c               | 17 +++++----
>   fs/gfs2/rgrp.c                   |  2 +-
>   fs/gfs2/super.c                  |  9 ++---
>   fs/gfs2/trans.c                  |  2 +-
>   include/uapi/linux/gfs2_ondisk.h | 28 +++++++++++++--
>   14 files changed, 128 insertions(+), 59 deletions(-)
> 
> diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
> index 658ca027cab9..7c64925735d3 100644
> --- a/fs/gfs2/aops.c
> +++ b/fs/gfs2/aops.c
> @@ -445,7 +445,7 @@ static int gfs2_jdata_writepages(struct address_space *mapping,
>   
>   	ret = gfs2_write_cache_jdata(mapping, wbc);
>   	if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) {
> -		gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH);
> +		gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   		ret = gfs2_write_cache_jdata(mapping, wbc);
>   	}
>   	return ret;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index bd60dc682676..7a02b4e6e9f3 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -246,7 +246,8 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>   	}
>   	if ((flags ^ new_flags) & GFS2_DIF_JDATA) {
>   		if (new_flags & GFS2_DIF_JDATA)
> -			gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH);
> +			gfs2_log_flush(sdp, ip->i_gl,
> +				       GFS2_LOG_HEAD_FLUSH_NORMAL);
>   		error = filemap_fdatawrite(inode->i_mapping);
>   		if (error)
>   			goto out;
> diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
> index cdd1c5f06f45..2daab13a9e0b 100644
> --- a/fs/gfs2/glops.c
> +++ b/fs/gfs2/glops.c
> @@ -107,7 +107,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
>   	__gfs2_ail_flush(gl, 0, tr.tr_revokes);
>   
>   	gfs2_trans_end(sdp);
> -	gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
> +	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   }
>   
>   void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
> @@ -128,7 +128,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
>   		return;
>   	__gfs2_ail_flush(gl, fsync, max_revokes);
>   	gfs2_trans_end(sdp);
> -	gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
> +	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   }
>   
>   /**
> @@ -157,7 +157,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
>   		return;
>   	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
>   
> -	gfs2_log_flush(sdp, gl, NORMAL_FLUSH);
> +	gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   	filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
>   	error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
>   	mapping_set_error(mapping, error);
> @@ -252,7 +252,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
>   
>   	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
>   
> -	gfs2_log_flush(gl->gl_name.ln_sbd, gl, NORMAL_FLUSH);
> +	gfs2_log_flush(gl->gl_name.ln_sbd, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   	filemap_fdatawrite(metamapping);
>   	if (isreg) {
>   		struct address_space *mapping = ip->i_inode.i_mapping;
> @@ -303,7 +303,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
>   	}
>   
>   	if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) {
> -		gfs2_log_flush(gl->gl_name.ln_sbd, NULL, NORMAL_FLUSH);
> +		gfs2_log_flush(gl->gl_name.ln_sbd, NULL,
> +			       GFS2_LOG_HEAD_FLUSH_NORMAL);
>   		gl->gl_name.ln_sbd->sd_rindex_uptodate = 0;
>   	}
>   	if (ip && S_ISREG(ip->i_inode.i_mode))
> @@ -495,7 +496,7 @@ static void freeze_go_sync(struct gfs2_glock *gl)
>   			gfs2_assert_withdraw(sdp, 0);
>   		}
>   		queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
> -		gfs2_log_flush(sdp, NULL, FREEZE_FLUSH);
> +		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE);
>   	}
>   }
>   
> diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
> index c27cbcebfe88..a2eb13c04591 100644
> --- a/fs/gfs2/log.c
> +++ b/fs/gfs2/log.c
> @@ -14,6 +14,7 @@
>   #include <linux/buffer_head.h>
>   #include <linux/gfs2_ondisk.h>
>   #include <linux/crc32.h>
> +#include <linux/crc32c.h>
>   #include <linux/delay.h>
>   #include <linux/kthread.h>
>   #include <linux/freezer.h>
> @@ -653,20 +654,25 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
>   /**
>    * write_log_header - Write a journal log header buffer at sd_log_flush_head
>    * @sdp: The GFS2 superblock
> + * @jd: journal descriptor of the journal to which we are writing
>    * @seq: sequence number
>    * @tail: tail of the log
> - * @flags: log header flags
> + * @flags: log header flags GFS2_LOG_HEAD_*
>    * @op_flags: flags to pass to the bio
>    *
>    * Returns: the initialized log buffer descriptor
>    */
>   
> -void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
> -			   u32 flags, int op_flags)
> +void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
> +			   u64 seq, u32 tail, u32 flags, int op_flags)
>   {
>   	struct gfs2_log_header *lh;
> -	u32 hash;
> +	u32 hash, crc;
>   	struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
> +	struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
> +	struct timespec64 tv;
> +	struct super_block *sb = sdp->sd_vfs;
> +	u64 addr;
>   
>   	lh = page_address(page);
>   	clear_page(lh);
> @@ -680,10 +686,39 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
>   	lh->lh_flags = cpu_to_be32(flags);
>   	lh->lh_tail = cpu_to_be32(tail);
>   	lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
> -	hash = ~crc32(~0, lh, sizeof(*lh));
> +	hash = ~crc32(~0, lh, LH_V1_SIZE);
>   	lh->lh_hash = cpu_to_be32(hash);
>   
> -	gfs2_log_write_page(sdp, page);
> +	tv = current_kernel_time64();
> +	lh->lh_nsec = cpu_to_be32(tv.tv_nsec);
> +	lh->lh_sec = cpu_to_be64(tv.tv_sec);
> +	addr = gfs2_log_bmap(sdp);
> +	lh->lh_addr = cpu_to_be64(addr);
> +	lh->lh_jinode = cpu_to_be64(GFS2_I(jd->jd_inode)->i_no_addr);
> +
> +	/* We may only write local statfs, quota, etc., when writing to our
> +	   own journal. The values are left 0 when recovering a journal
> +	   different from our own. */
> +	if (!(flags & GFS2_LOG_HEAD_RECOVERY)) {
> +		lh->lh_statfs_addr =
> +			cpu_to_be64(GFS2_I(sdp->sd_sc_inode)->i_no_addr);
> +		lh->lh_quota_addr =
> +			cpu_to_be64(GFS2_I(sdp->sd_qc_inode)->i_no_addr);
> +
> +		spin_lock(&sdp->sd_statfs_spin);
> +		lh->lh_local_total = cpu_to_be64(l_sc->sc_total);
> +		lh->lh_local_free = cpu_to_be64(l_sc->sc_free);
> +		lh->lh_local_dinodes = cpu_to_be64(l_sc->sc_dinodes);
> +		spin_unlock(&sdp->sd_statfs_spin);
> +	}
> +
> +	BUILD_BUG_ON(offsetof(struct gfs2_log_header, lh_crc) != LH_V1_SIZE);
> +
> +	crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
> +		     sb->s_blocksize - LH_V1_SIZE - 4);
> +	lh->lh_crc = cpu_to_be32(crc);
> +
> +	gfs2_log_write(sdp, page, sb->s_blocksize, 0, addr);
>   	gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags);
>   	log_flush_wait(sdp);
>   }
> @@ -691,6 +726,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
>   /**
>    * log_write_header - Get and initialize a journal header buffer
>    * @sdp: The GFS2 superblock
> + * @flags: The log header flags, including log header origin
>    *
>    * Returns: the initialized log buffer descriptor
>    */
> @@ -710,8 +746,8 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
>   		op_flags = REQ_SYNC | REQ_META | REQ_PRIO;
>   	}
>   	sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
> -	gfs2_write_log_header(sdp, sdp->sd_log_sequence++, tail, flags,
> -			      op_flags);
> +	gfs2_write_log_header(sdp, sdp->sd_jdesc, sdp->sd_log_sequence++, tail,
> +			      flags, op_flags);
>   
>   	if (sdp->sd_log_tail != tail)
>   		log_pull_tail(sdp, tail);
> @@ -721,11 +757,11 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
>    * gfs2_log_flush - flush incore transaction(s)
>    * @sdp: the filesystem
>    * @gl: The glock structure to flush.  If NULL, flush the whole incore log
> + * @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_*
>    *
>    */
>   
> -void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
> -		    enum gfs2_flush_type type)
> +void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
>   {
>   	struct gfs2_trans *tr;
>   	enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state);
> @@ -739,7 +775,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
>   	}
>   	trace_gfs2_log_flush(sdp, 1);
>   
> -	if (type == SHUTDOWN_FLUSH)
> +	if (flags & GFS2_LOG_HEAD_FLUSH_SHUTDOWN)
>   		clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
>   
>   	sdp->sd_log_flush_head = sdp->sd_log_head;
> @@ -764,11 +800,11 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
>   
>   	if (sdp->sd_log_head != sdp->sd_log_flush_head) {
>   		log_flush_wait(sdp);
> -		log_write_header(sdp, 0);
> +		log_write_header(sdp, flags);
>   	} else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
>   		atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
>   		trace_gfs2_log_blocks(sdp, -1);
> -		log_write_header(sdp, 0);
> +		log_write_header(sdp, flags);
>   	}
>   	lops_after_commit(sdp, tr);
>   
> @@ -785,7 +821,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
>   	spin_unlock(&sdp->sd_ail_lock);
>   	gfs2_log_unlock(sdp);
>   
> -	if (type != NORMAL_FLUSH) {
> +	if (!(flags & GFS2_LOG_HEAD_FLUSH_NORMAL)) {
>   		if (!sdp->sd_log_idle) {
>   			for (;;) {
>   				gfs2_ail1_start(sdp);
> @@ -795,12 +831,13 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
>   			}
>   			atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
>   			trace_gfs2_log_blocks(sdp, -1);
> -			log_write_header(sdp, 0);
> +			log_write_header(sdp, flags);
>   			sdp->sd_log_head = sdp->sd_log_flush_head;
>   		}
> -		if (type == SHUTDOWN_FLUSH || type == FREEZE_FLUSH)
> +		if (flags & (GFS2_LOG_HEAD_FLUSH_SHUTDOWN |
> +			     GFS2_LOG_HEAD_FLUSH_FREEZE))
>   			gfs2_log_shutdown(sdp);
> -		if (type == FREEZE_FLUSH)
> +		if (flags & GFS2_LOG_HEAD_FLUSH_FREEZE)
>   			atomic_set(&sdp->sd_freeze_state, SFS_FROZEN);
>   	}
>   
> @@ -956,7 +993,7 @@ int gfs2_logd(void *data)
>   		did_flush = false;
>   		if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
>   			gfs2_ail1_empty(sdp);
> -			gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
> +			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   			did_flush = true;
>   		}
>   
> @@ -964,7 +1001,7 @@ int gfs2_logd(void *data)
>   			gfs2_ail1_start(sdp);
>   			gfs2_ail1_wait(sdp);
>   			gfs2_ail1_empty(sdp);
> -			gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
> +			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   			did_flush = true;
>   		}
>   
> diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h
> index 619de9a1ff4f..93b52ac1ca1f 100644
> --- a/fs/gfs2/log.h
> +++ b/fs/gfs2/log.h
> @@ -65,16 +65,10 @@ extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
>   
>   extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks);
>   extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
> -enum gfs2_flush_type {
> -	NORMAL_FLUSH = 0,
> -	SYNC_FLUSH,
> -	SHUTDOWN_FLUSH,
> -	FREEZE_FLUSH
> -};
> -extern void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
> -				  u32 flags, int op_flags);
> +extern void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
> +				  u64 seq, u32 tail, u32 flags, int op_flags);
>   extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
> -			   enum gfs2_flush_type type);
> +			   u32 type);
>   extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
>   extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
>   extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc);
> diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
> index c8ff7b7954f0..4a60221c678f 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"
> @@ -138,7 +139,7 @@ static void gfs2_log_incr_head(struct gfs2_sbd *sdp)
>   		sdp->sd_log_flush_head = 0;
>   }
>   
> -static u64 gfs2_log_bmap(struct gfs2_sbd *sdp)
> +u64 gfs2_log_bmap(struct gfs2_sbd *sdp)
>   {
>   	unsigned int lbn = sdp->sd_log_flush_head;
>   	struct gfs2_journal_extent *je;
> @@ -306,23 +307,22 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno)
>   	return gfs2_log_alloc_bio(sdp, blkno);
>   }
>   
> -
>   /**
>    * gfs2_log_write - write to log
>    * @sdp: the filesystem
>    * @page: the page to write
>    * @size: the size of the data to write
>    * @offset: the offset within the page
> + * @blkno: block number of the log entry
>    *
>    * Try and add the page segment to the current bio. If that fails,
>    * submit the current bio to the device and create a new one, and
>    * then add the page segment to that.
>    */
>   
> -static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
> -			   unsigned size, unsigned offset)
> +void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
> +		    unsigned size, unsigned offset, u64 blkno)
>   {
> -	u64 blkno = gfs2_log_bmap(sdp);
>   	struct bio *bio;
>   	int ret;
>   
> @@ -348,7 +348,8 @@ 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),
> +		       gfs2_log_bmap(sdp));
>   }
>   
>   /**
> @@ -365,7 +366,8 @@ 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,
> +		       gfs2_log_bmap(sdp));
>   }
>   
>   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..e4949394f054 100644
> --- a/fs/gfs2/lops.h
> +++ b/fs/gfs2/lops.h
> @@ -26,6 +26,9 @@ extern const struct gfs2_log_operations gfs2_revoke_lops;
>   extern const struct gfs2_log_operations gfs2_databuf_lops;
>   
>   extern const struct gfs2_log_operations *gfs2_log_ops[];
> +extern u64 gfs2_log_bmap(struct gfs2_sbd *sdp);
> +extern void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
> +			   unsigned size, unsigned offset, u64 blkno);
>   extern void gfs2_log_write_page(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/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
> index ad55eb86a250..d6e620beb9db 100644
> --- a/fs/gfs2/ops_fstype.c
> +++ b/fs/gfs2/ops_fstype.c
> @@ -1382,7 +1382,7 @@ static void gfs2_kill_sb(struct super_block *sb)
>   		return;
>   	}
>   
> -	gfs2_log_flush(sdp, NULL, SYNC_FLUSH);
> +	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SYNC);
>   	dput(sdp->sd_root_dir);
>   	dput(sdp->sd_master_dir);
>   	sdp->sd_root_dir = NULL;
> diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
> index e700fb162664..2092df19e433 100644
> --- a/fs/gfs2/quota.c
> +++ b/fs/gfs2/quota.c
> @@ -955,7 +955,8 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
>   		gfs2_glock_dq_uninit(&ghs[qx]);
>   	inode_unlock(&ip->i_inode);
>   	kfree(ghs);
> -	gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl, NORMAL_FLUSH);
> +	gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl,
> +		       GFS2_LOG_HEAD_FLUSH_NORMAL);
>   	return error;
>   }
>   
> diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
> index 975f32166dfe..b6b258998bcd 100644
> --- a/fs/gfs2/recovery.c
> +++ b/fs/gfs2/recovery.c
> @@ -14,6 +14,7 @@
>   #include <linux/buffer_head.h>
>   #include <linux/gfs2_ondisk.h>
>   #include <linux/crc32.h>
> +#include <linux/crc32c.h>
>   
>   #include "gfs2.h"
>   #include "incore.h"
> @@ -137,7 +138,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
>   {
>   	struct gfs2_log_header *lh;
>   	struct buffer_head *bh;
> -	u32 hash;
> +	u32 hash, crc;
>   	int error;
>   
>   	error = gfs2_replay_read_block(jd, blk, &bh);
> @@ -145,13 +146,17 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
>   		return error;
>   	lh = (void *)bh->b_data;
>   
> -	hash = crc32(~0, lh, sizeof(*lh) - 4);
> +	hash = crc32(~0, lh, LH_V1_SIZE - 4);
>   	hash = ~crc32_le_shift(hash, 4);  /* assume lh_hash is zero */
>   
> +	crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
> +		     bh->b_size - LH_V1_SIZE - 4);
> +
>   	error = lh->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
>   		lh->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH) ||
>   		be32_to_cpu(lh->lh_blkno) != blk ||
> -		be32_to_cpu(lh->lh_hash) != hash;
> +		be32_to_cpu(lh->lh_hash) != hash ||
> +		(lh->lh_crc != 0 && be32_to_cpu(lh->lh_crc) != crc);
>   
>   	brelse(bh);
>   
> @@ -372,9 +377,9 @@ static void clean_journal(struct gfs2_jdesc *jd,
>   
>   	sdp->sd_log_flush_head = head->lh_blkno;
>   	gfs2_replay_incr_blk(jd, &sdp->sd_log_flush_head);
> -	gfs2_write_log_header(sdp, head->lh_sequence + 1, 0,
> -			      GFS2_LOG_HEAD_UNMOUNT, REQ_PREFLUSH |
> -			      REQ_FUA | REQ_META | REQ_SYNC);
> +	gfs2_write_log_header(sdp, jd, head->lh_sequence + 1, 0,
> +			      GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_RECOVERY,
> +			      REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC);
>   }
>   
>   
> diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
> index 6dea72f49316..00eab6c0525c 100644
> --- a/fs/gfs2/rgrp.c
> +++ b/fs/gfs2/rgrp.c
> @@ -2093,7 +2093,7 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, struct gfs2_alloc_parms *ap)
>   		}
>   		/* Flushing the log may release space */
>   		if (loops == 2)
> -			gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
> +			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   	}
>   
>   	return -ENOSPC;
> diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
> index d81d46e19726..fa3a19eaf0eb 100644
> --- a/fs/gfs2/super.c
> +++ b/fs/gfs2/super.c
> @@ -757,7 +757,8 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc)
>   	bool flush_all = (wbc->sync_mode == WB_SYNC_ALL || gfs2_is_jdata(ip));
>   
>   	if (flush_all)
> -		gfs2_log_flush(GFS2_SB(inode), ip->i_gl, NORMAL_FLUSH);
> +		gfs2_log_flush(GFS2_SB(inode), ip->i_gl,
> +			       GFS2_LOG_HEAD_FLUSH_NORMAL);
>   	if (bdi->wb.dirty_exceeded)
>   		gfs2_ail1_flush(sdp, wbc);
>   	else
> @@ -853,7 +854,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
>   	gfs2_quota_sync(sdp->sd_vfs, 0);
>   	gfs2_statfs_sync(sdp->sd_vfs, 0);
>   
> -	gfs2_log_flush(sdp, NULL, SHUTDOWN_FLUSH);
> +	gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN);
>   	wait_event(sdp->sd_reserving_log_wait, atomic_read(&sdp->sd_reserving_log) == 0);
>   	gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
>   
> @@ -946,7 +947,7 @@ static int gfs2_sync_fs(struct super_block *sb, int wait)
>   
>   	gfs2_quota_sync(sb, -1);
>   	if (wait)
> -		gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
> +		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   	return sdp->sd_log_error;
>   }
>   
> @@ -1650,7 +1651,7 @@ static void gfs2_evict_inode(struct inode *inode)
>   	goto out_unlock;
>   
>   out_truncate:
> -	gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH);
> +	gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   	metamapping = gfs2_glock2aspace(ip->i_gl);
>   	if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) {
>   		filemap_fdatawrite(metamapping);
> diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
> index b95ebd166cac..7aec6d3434fa 100644
> --- a/fs/gfs2/trans.c
> +++ b/fs/gfs2/trans.c
> @@ -117,7 +117,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp)
>   	up_read(&sdp->sd_log_flush_lock);
>   
>   	if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS)
> -		gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
> +		gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
>   	if (alloced)
>   		sb_end_intwrite(sdp->sd_vfs);
>   }
> diff --git a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h
> index 09f0920f07e9..eff5c158805d 100644
> --- a/include/uapi/linux/gfs2_ondisk.h
> +++ b/include/uapi/linux/gfs2_ondisk.h
> @@ -403,7 +403,15 @@ struct gfs2_ea_header {
>    * Log header structure
>    */
>   
> -#define GFS2_LOG_HEAD_UNMOUNT	0x00000001	/* log is clean */
> +#define GFS2_LOG_HEAD_UNMOUNT		0x00000001 /* log is clean */
> +#define GFS2_LOG_HEAD_FLUSH_NORMAL	0x00000002 /* normal log flush */
> +#define GFS2_LOG_HEAD_FLUSH_SYNC	0x00000004 /* Sync log flush */
> +#define GFS2_LOG_HEAD_FLUSH_SHUTDOWN	0x00000008 /* Shutdown log flush */
> +#define GFS2_LOG_HEAD_FLUSH_FREEZE	0x00000010 /* Freeze flush */
> +#define GFS2_LOG_HEAD_RECOVERY		0x00000020 /* Journal recovery */
> +#define GFS2_LOG_HEAD_USERSPACE		0x80000000 /* Written by gfs2-utils */
> +
> +#define LH_V1_SIZE (offsetofend(struct gfs2_log_header, lh_hash))
>   
>   struct gfs2_log_header {
>   	struct gfs2_meta_header lh_header;
> @@ -412,7 +420,23 @@ struct gfs2_log_header {
>   	__be32 lh_flags;	/* GFS2_LOG_HEAD_... */
>   	__be32 lh_tail;		/* Block number of log tail */
>   	__be32 lh_blkno;
> -	__be32 lh_hash;
> +	__be32 lh_hash;		/* crc up to here with this field 0 */
> +
> +	/* Version 2 additional fields start here */
> +	__be32 lh_crc;		/* crc32c from lh_nsec to end of block */
> +	__be32 lh_nsec;		/* Nanoseconds of timestamp */
> +	__be64 lh_sec;		/* Seconds of timestamp */
> +	__be64 lh_addr;		/* Block addr 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_origin;	/* The origin of this log header */
> +	__be32 __pad;
>   };
>   
>   /*
> 



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-19 14:31   ` Andrew Price
  2018-01-19 14:39     ` Steven Whitehouse
@ 2018-01-19 20:06     ` Andrew Price
  2018-01-19 22:23       ` Andrew Price
  1 sibling, 1 reply; 16+ messages in thread
From: Andrew Price @ 2018-01-19 20:06 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On 19/01/18 14:31, Andrew Price wrote:> I've pushed a gfs2-utils patch 
with basic support for the new log header
> format to the andyp-lhv2 branch. I need to test it some more but it 
> should be useful for testing these patches already. I'll finalise it 
> once the v2 patches are in for-next.

So the gfs2-utils patch is completely broken in that it isn't using 
crc32c for lh_crc. I'm looking into finding a userspace crc32c 
implementation now.

On a related note: unless I'm mistaken, we'll need to add 'select 
CRYPTO_CRC32C' in gfs2's Kconfig now.

Andy



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2
  2018-01-19 20:06     ` Andrew Price
@ 2018-01-19 22:23       ` Andrew Price
  0 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2018-01-19 22:23 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On 19/01/18 20:06, Andrew Price wrote:
> On 19/01/18 14:31, Andrew Price wrote:> I've pushed a gfs2-utils patch 
> with basic support for the new log header
>> format to the andyp-lhv2 branch. I need to test it some more but it 
>> should be useful for testing these patches already. I'll finalise it 
>> once the v2 patches are in for-next.
> 
> So the gfs2-utils patch is completely broken in that it isn't using 
> crc32c for lh_crc. I'm looking into finding a userspace crc32c 
> implementation now.

I have pushed a new version of the patch to the andyp-lhv2 branch of 
gfs2-utils. It includes a crc32c implementation that originated in the 
kernel and was brought to user-space in btrfs-progs. It uses hardware 
support if it can.

The patch also uses fiemap in gfs2_jadd to set lh_addr, as Andreas 
suggested.

Cheers,
Andy



^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2018-01-19 22:23 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-18 16:04 [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 1/3] gfs2: Get rid of gfs2_log_header_in Andreas Gruenbacher
2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 2/3] GFS2: Introduce new gfs2_log_header_v2 Andreas Gruenbacher
2018-01-19 10:47   ` Andrew Price
2018-01-19 10:53     ` Steven Whitehouse
2018-01-19 12:19       ` Andrew Price
2018-01-19 14:35         ` Andreas Gruenbacher
2018-01-19 14:31   ` Andrew Price
2018-01-19 14:39     ` Steven Whitehouse
2018-01-19 15:06       ` Andrew Price
2018-01-19 20:06     ` Andrew Price
2018-01-19 22:23       ` Andrew Price
2018-01-18 16:04 ` [Cluster-devel] [PATCH v5 3/3] GFS2: Log the reason for log flushes in every log header Andreas Gruenbacher
2018-01-18 16:23 ` [Cluster-devel] [PATCH v5 0/3] GFS2: Introduce new gfs2_log_header_v2 Steven Whitehouse
2018-01-19 14:40 ` [Cluster-devel] [PATCH v6] " Andreas Gruenbacher
2018-01-19 15:14   ` Andrew Price

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.