[Cluster-devel] [PATCH v5] gfs2: clean_journal improperly set sd_log_flush_head

2019-04-03 Thread Bob Peterson
Hi,

Andreas had some suggestions for v4, so here is v5.

Bob
---
gfs2: clean_journal improperly set sd_log_flush_head

This patch fixes regressions in 588bff95c94efc05f9e1a0b19015c9408ed7c0ef.
Due to that patch, function clean_journal was setting the value of
sd_log_flush_head, but that's only valid if it is replaying the node's
own journal. If it's replaying another node's journal, that's completely
wrong and will lead to multiple problems. This patch tries to clean up
the mess by passing the value of the logical journal block number into
gfs2_write_log_header so the function can treat non-owned journals
generically. For the local journal, the journal extent map is used for
best performance. For other nodes from other journals, new function
gfs2_lblk_to_dblk is called to figure it out using gfs2_iomap_get.

This patch also tries to establish more consistency when passing journal
block parameters by changing several unsigned int types to a consistent
u32.

Fixes: 588bff95c94e ("GFS2: Reduce code redundancy writing log headers")
Signed-off-by: Bob Peterson 
---
 fs/gfs2/bmap.c | 26 ++
 fs/gfs2/bmap.h |  1 +
 fs/gfs2/incore.h   |  2 +-
 fs/gfs2/log.c  | 24 
 fs/gfs2/log.h  |  3 ++-
 fs/gfs2/lops.c |  6 +++---
 fs/gfs2/lops.h |  2 +-
 fs/gfs2/recovery.c | 10 ++
 fs/gfs2/recovery.h |  2 +-
 9 files changed, 57 insertions(+), 19 deletions(-)

diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 02b2646d84b3..e95b33b65d89 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -925,6 +925,32 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, 
loff_t length,
goto out;
 }
 
+/**
+ * gfs2_lblk_to_dblk - convert logical block to disk block
+ * @inode: the inode of the file we're mapping
+ * @lblock: the block relative to the start of the file
+ * @dblock: the returned dblock, if no error
+ *
+ * This function maps a single block from a file logical block (relative to
+ * the start of the file) to a file system absolute block using iomap.
+ *
+ * Returns: the absolute file system block, or an error
+ */
+int gfs2_lblk_to_dblk(struct inode *inode, u32 lblock, u64 *dblock)
+{
+   struct iomap iomap = { };
+   struct metapath mp = { .mp_aheight = 1, };
+   loff_t pos = (loff_t)lblock << inode->i_blkbits;
+   int ret;
+
+   ret = gfs2_iomap_get(inode, pos, i_blocksize(inode), 0, , );
+   release_metapath();
+   if (ret == 0)
+   *dblock = iomap.addr >> inode->i_blkbits;
+
+   return ret;
+}
+
 static int gfs2_write_lock(struct inode *inode)
 {
struct gfs2_inode *ip = GFS2_I(inode);
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h
index 6b18fb323f0a..19a1fd772c61 100644
--- a/fs/gfs2/bmap.h
+++ b/fs/gfs2/bmap.h
@@ -64,5 +64,6 @@ extern int gfs2_write_alloc_required(struct gfs2_inode *ip, 
u64 offset,
 extern int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc 
*jd);
 extern void gfs2_free_journal_extents(struct gfs2_jdesc *jd);
 extern int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length);
+extern int gfs2_lblk_to_dblk(struct inode *inode, u32 lblock, u64 *dblock);
 
 #endif /* __BMAP_DOT_H__ */
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index cdf07b408f54..86840a70ee1a 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -535,7 +535,7 @@ struct gfs2_jdesc {
unsigned long jd_flags;
 #define JDF_RECOVERY 1
unsigned int jd_jid;
-   unsigned int jd_blocks;
+   u32 jd_blocks;
int jd_recover_error;
/* Replay stuff */
 
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index b8830fda51e8..ebbc68dca145 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -666,11 +666,12 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
 }
 
 /**
- * write_log_header - Write a journal log header buffer at sd_log_flush_head
+ * gfs2_write_log_header - Write a journal log header buffer at lblock
  * @sdp: The GFS2 superblock
  * @jd: journal descriptor of the journal to which we are writing
  * @seq: sequence number
  * @tail: tail of the log
+ * @lblock: value for lh_blkno (block number relative to start of journal)
  * @flags: log header flags GFS2_LOG_HEAD_*
  * @op_flags: flags to pass to the bio
  *
@@ -678,7 +679,8 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
  */
 
 void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
-  u64 seq, u32 tail, u32 flags, int op_flags)
+  u64 seq, u32 tail, u32 lblock, u32 flags,
+  int op_flags)
 {
struct gfs2_log_header *lh;
u32 hash, crc;
@@ -686,7 +688,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct 
gfs2_jdesc *jd,
struct gfs2_statfs_change_host *l_sc = >sd_statfs_local;
struct timespec64 tv;
struct super_block *sb = sdp->sd_vfs;
-   u64 addr;
+   u64 dblock;
 
lh = page_address(page);
clear_page(lh);
@@ -699,15 +701,21 @@ void 

[Cluster-devel] [PATCH v4] gfs2: clean_journal improperly set sd_log_flush_head

2019-04-03 Thread Bob Peterson
Hi,

On 28 March, I posted a v3 patch for this problem, but that had problems too,
which Andreas found using xfstests/034 test.

This v4 version fixes those problems and, as Steve Whitehouse suggested,
uses the faster iomap interface to map blocks from other journals, rather
than the now obsolete gfs2_extent_map().

Regards,

Bob Peterson
---
This patch fixes regressions in 588bff95c94efc05f9e1a0b19015c9408ed7c0ef.
Due to that patch, function clean_journal was setting the value of
sd_log_flush_head, but that's only valid if it is replaying the node's
own journal. If it's replaying another node's journal, that's completely
wrong and will lead to multiple problems. This patch tries to clean up
the mess by passing the value of the logical journal block number into
gfs2_write_log_header so the function can treat non-owned journals
generically. For the local journal, the journal extent map is used for
best performance. For other nodes from other journals, new function
gfs2_lblk_to_dblk is called to figure it out using gfs2_iomap_get.

This patch also tries to establish more consistency when passing journal
block parameters by changing several unsigned int types to a consistent
u32.

Fixes: 588bff95c94e ("GFS2: Reduce code redundancy writing log headers")
Signed-off-by: Bob Peterson 
---
 fs/gfs2/bmap.c | 27 +++
 fs/gfs2/bmap.h |  1 +
 fs/gfs2/incore.h   |  2 +-
 fs/gfs2/log.c  | 24 
 fs/gfs2/log.h  |  3 ++-
 fs/gfs2/lops.c |  6 +++---
 fs/gfs2/lops.h |  2 +-
 fs/gfs2/recovery.c | 10 ++
 fs/gfs2/recovery.h |  2 +-
 9 files changed, 58 insertions(+), 19 deletions(-)

diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 02b2646d84b3..d914a745787e 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -925,6 +925,33 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, 
loff_t length,
goto out;
 }
 
+/**
+ * gfs2_lblk_to_dblk - convert logical block to disk block
+ * @inode: the inode of the file we're mapping
+ * @lblock: the block relative to the start of the file
+ *
+ * This function maps a single block from a file logical block (relative to
+ * the start of the file) to a file system absolute block using iomap.
+ *
+ * Returns: the absolute file system block, or an error
+ */
+u64 gfs2_lblk_to_dblk(struct inode *inode, u32 lblock)
+{
+   struct iomap iomap = { };
+   struct metapath mp = { .mp_aheight = 1, };
+   struct gfs2_sbd *sdp = GFS2_SB(inode);
+   loff_t pos = (loff_t)lblock << inode->i_blkbits;
+   int ret;
+
+   ret = gfs2_iomap_get(inode, pos, sdp->sd_sb.sb_bsize, 0, , );
+   release_metapath();
+
+   if (gfs2_assert_withdraw(sdp, ret == 0))
+   return (u64)ret;
+
+   return iomap.addr >> inode->i_blkbits;
+}
+
 static int gfs2_write_lock(struct inode *inode)
 {
struct gfs2_inode *ip = GFS2_I(inode);
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h
index 6b18fb323f0a..57e9e57dda86 100644
--- a/fs/gfs2/bmap.h
+++ b/fs/gfs2/bmap.h
@@ -64,5 +64,6 @@ extern int gfs2_write_alloc_required(struct gfs2_inode *ip, 
u64 offset,
 extern int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc 
*jd);
 extern void gfs2_free_journal_extents(struct gfs2_jdesc *jd);
 extern int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length);
+extern u64 gfs2_lblk_to_dblk(struct inode *inode, u32 lblock);
 
 #endif /* __BMAP_DOT_H__ */
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index cdf07b408f54..86840a70ee1a 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -535,7 +535,7 @@ struct gfs2_jdesc {
unsigned long jd_flags;
 #define JDF_RECOVERY 1
unsigned int jd_jid;
-   unsigned int jd_blocks;
+   u32 jd_blocks;
int jd_recover_error;
/* Replay stuff */
 
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index b8830fda51e8..a80a6257cba6 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -666,11 +666,12 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
 }
 
 /**
- * write_log_header - Write a journal log header buffer at sd_log_flush_head
+ * gfs2_write_log_header - Write a journal log header buffer at lblock
  * @sdp: The GFS2 superblock
  * @jd: journal descriptor of the journal to which we are writing
  * @seq: sequence number
  * @tail: tail of the log
+ * @lblock: value for lh_blkno (block number relative to start of journal)
  * @flags: log header flags GFS2_LOG_HEAD_*
  * @op_flags: flags to pass to the bio
  *
@@ -678,7 +679,8 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
  */
 
 void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
-  u64 seq, u32 tail, u32 flags, int op_flags)
+  u64 seq, u32 tail, u32 lblock, u32 flags,
+  int op_flags)
 {
struct gfs2_log_header *lh;
u32 hash, crc;
@@ -686,7 +688,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct 
gfs2_jdesc *jd,
struct