Hi,

On 22/12/17 13:34, Bob Peterson wrote:
Hi,

Here is version 2 of this patch, which has been heavily revised
based on comments from the initial patch. I'm still planning to
do a third patch which saves a new debug field for log header
origin.

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

This is based on a prototype patch from Steve Whitehouse.

In addition to Steve's original code, we also replace the log
flush types (NORMAL_FLUSH, SYNC_FLUSH, etc.) with new log header
flags (GFS2_LOG_HEAD_*). This way the log flush type be
automatically saved in the log header (as the UNMOUNT flag is now).
A few extra flags are also defined so we can distinguish whether
the log header was written by recovery, user space (gfs2-utils),
or one of the log flush operations.

Signed-off-by: Bob Peterson <[email protected]>
---
  fs/gfs2/aops.c                   |  2 +-
  fs/gfs2/file.c                   |  3 ++-
  fs/gfs2/glops.c                  | 13 ++++++-----
  fs/gfs2/log.c                    | 50 ++++++++++++++++++++++++++++------------
  fs/gfs2/log.h                    |  8 +------
  fs/gfs2/lops.c                   | 30 ++++++++++++++++++++----
  fs/gfs2/lops.h                   |  2 ++
  fs/gfs2/ops_fstype.c             |  2 +-
  fs/gfs2/quota.c                  |  3 ++-
  fs/gfs2/recovery.c               |  4 ++--
  fs/gfs2/rgrp.c                   |  2 +-
  fs/gfs2/super.c                  |  9 ++++----
  fs/gfs2/trans.c                  |  2 +-
  include/uapi/linux/gfs2_ondisk.h | 26 ++++++++++++++++++++-
  14 files changed, 111 insertions(+), 45 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 58705ef8643a..475c601ef4d8 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 27e97d3de1e0..2cc00d28e907 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -652,7 +652,7 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
   * @sdp: The GFS2 superblock
   * @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
@@ -661,13 +661,18 @@ void gfs2_write_revokes(struct gfs2_sbd *sdp)
  void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
                           u32 flags, int op_flags)
  {
+       struct gfs2_log_header_v2 *lh2;
        struct gfs2_log_header *lh;
        u32 hash;
        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;
- lh = page_address(page);
-       clear_page(lh);
+       lh2 = page_address(page);
+       clear_page(lh2);
+ lh = &lh2->lhv1;
        lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
        lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
        lh->lh_header.__pad0 = cpu_to_be64(0);
@@ -680,7 +685,20 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, 
u32 tail,
        hash = gfs2_disk_hash(page_address(page), sizeof(struct 
gfs2_log_header));
        lh->lh_hash = cpu_to_be32(hash);
- gfs2_log_write_page(sdp, page);
+       tv = current_kernel_time64();
+       lh2->lh_nsec = cpu_to_be32(tv.tv_nsec);
+       lh2->lh_sec = cpu_to_be64(tv.tv_sec);
+       lh2->lh_jinode = 
cpu_to_be64(GFS2_I(sdp->sd_jdesc->jd_inode)->i_no_addr);
+       lh2->lh_statfs_addr = cpu_to_be64(GFS2_I(sdp->sd_sc_inode)->i_no_addr);
+       lh2->lh_quota_addr = cpu_to_be64(GFS2_I(sdp->sd_qc_inode)->i_no_addr);
+
+       spin_lock(&sdp->sd_statfs_spin);
+       lh2->lh_local_total = cpu_to_be64(l_sc->sc_total);
+       lh2->lh_local_free = cpu_to_be64(l_sc->sc_free);
+       lh2->lh_local_dinodes = cpu_to_be64(l_sc->sc_dinodes);
+       spin_unlock(&sdp->sd_statfs_spin);
+
Bear in mind, that now this function writes the recovery log headers too, it must avoid writing the local node's statfs info into the log that has just been recovered (for another node). Likewise the other local inode info needs to match that for the node/log that has been recovered. Otherwise though, the patch looks good,

Steve.

Reply via email to