Bob,

On 4 January 2018 at 17:51, Bob Peterson <[email protected]> wrote:
> Hi,
>
> Here is a revised version 4 of the log_header_v2 patch.
> It incorporates changes suggested by Steve Whitehouse, namely,
> to pass the journal descriptor to write_log_header and also
> to record the destination journal's inode rather than the caller's
> journal inode number.
>
> Regards,
>
> Bob Peterson
> ---
> This patch expands the gfs2_log_header structure to include new
> fields into previously unused areas of the log headers. Some of
> these are used for debug purposes so we can backtrack when
> problems occur. Some more may be used for fsck to more easily
> reconstruct damaged file systems. 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                    | 63 
> ++++++++++++++++++++++++++++------------
>  fs/gfs2/log.h                    | 12 ++------
>  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               |  9 +++---
>  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, 124 insertions(+), 53 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 b9889ae5fd7c..e526cc6ad604 100644
> --- a/fs/gfs2/log.c
> +++ b/fs/gfs2/log.c
> @@ -653,20 +653,24 @@ 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;
>         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);
> @@ -680,10 +684,31 @@ 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 = gfs2_disk_hash(page_address(page), 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);
> +       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 (jd == sdp->sd_jdesc) {
> +               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);
> +       }
> +
> +       gfs2_log_write(sdp, page, sb->s_blocksize, 0, true);
>         gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags);
>         log_flush_wait(sdp);
>  }
> @@ -691,6 +716,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 +736,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 +747,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 +765,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 +790,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 +811,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 +821,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 +983,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 +991,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..1d5fb3671da4 100644
> --- a/fs/gfs2/lops.c
> +++ b/fs/gfs2/lops.c
> @@ -18,6 +18,7 @@
>  #include <linux/fs.h>
>  #include <linux/list_sort.h>
>
> +#include "dir.h"
>  #include "gfs2.h"
>  #include "incore.h"
>  #include "inode.h"
> @@ -306,6 +307,25 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd 
> *sdp, u64 blkno)
>         return gfs2_log_alloc_bio(sdp, blkno);
>  }
>
> +/**
> + * gfs2_set_log_csum - Set a whole-block checksum for a page
> + * @sb: The superblock
> + * @page: The page to write
> + * @blkno: The device block number we want to write to
> + *
> + * Set the location of the block to be written and then checksum the block
> + * before writing it.
> + */
> +static void gfs2_set_log_csum(struct super_block *sb, struct page *page,
> +                             u64 blkno)
> +{
> +       struct gfs2_log_header *lh = page_address(page);
> +       u32 hash;
> +
> +       lh->lh_addr = cpu_to_be64(blkno);
> +       hash = gfs2_disk_hash(page_address(page), sb->s_blocksize);
> +       lh->lh_crc = cpu_to_be32(hash);
> +}
>
>  /**
>   * gfs2_log_write - write to log
> @@ -319,8 +339,8 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, 
> u64 blkno)
>   * 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, bool is_hdr)
>  {
>         u64 blkno = gfs2_log_bmap(sdp);
>         struct bio *bio;
> @@ -334,6 +354,8 @@ static void gfs2_log_write(struct gfs2_sbd *sdp, struct 
> page *page,
>                 ret = bio_add_page(bio, page, size, offset);
>                 WARN_ON(ret == 0);
>         }
> +       if (is_hdr)
> +               gfs2_set_log_csum(sdp->sd_vfs, page, blkno);
>  }
>
>  /**
> @@ -348,7 +370,7 @@ static void gfs2_log_write(struct gfs2_sbd *sdp, struct 
> page *page,
>
>  static void gfs2_log_write_bh(struct gfs2_sbd *sdp, struct buffer_head *bh)
>  {
> -       gfs2_log_write(sdp, bh->b_page, bh->b_size, bh_offset(bh));
> +       gfs2_log_write(sdp, bh->b_page, bh->b_size, bh_offset(bh), false);
>  }
>
>  /**
> @@ -365,7 +387,7 @@ static void gfs2_log_write_bh(struct gfs2_sbd *sdp, 
> struct buffer_head *bh)
>  void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page)
>  {
>         struct super_block *sb = sdp->sd_vfs;
> -       gfs2_log_write(sdp, page, sb->s_blocksize, 0);
> +       gfs2_log_write(sdp, page, sb->s_blocksize, 0, false);
>  }
>
>  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..f31a5ff470f4 100644
> --- a/fs/gfs2/lops.h
> +++ b/fs/gfs2/lops.h
> @@ -26,6 +26,8 @@ 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 void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
> +                          unsigned size, unsigned offset, bool is_hdr);
>  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 a3711f543405..d80c1e433f87 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 5d3431219425..0b3a49906e38 100644
> --- a/fs/gfs2/recovery.c
> +++ b/fs/gfs2/recovery.c
> @@ -161,8 +161,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned 
> int blk,
>         if (error)
>                 return error;
>
> -       hash = crc32_le((u32)~0, bh->b_data, sizeof(struct gfs2_log_header) -
> -                                            sizeof(u32));
> +       hash = crc32_le((u32)~0, bh->b_data, LH_V1_SIZE - sizeof(u32));
>         hash = crc32_le(hash, (unsigned char const *)&nothing, 
> sizeof(nothing));
>         hash ^= (u32)~0;
>         error = gfs2_log_header_in(&lh, bh->b_data);
> @@ -384,9 +383,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 e8aba6fa1472..44879546613f 100644
> --- a/fs/gfs2/rgrp.c
> +++ b/fs/gfs2/rgrp.c
> @@ -2086,7 +2086,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 9cb5c9a97d69..d57d29c32523 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 a85ca8b2c9ba..5ab1bf69c788 100644
> --- a/fs/gfs2/trans.c
> +++ b/fs/gfs2/trans.c
> @@ -118,7 +118,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp)
>         up_read(&sdp->sd_log_flush_lock);
>
>         if (sdp->sd_vfs->s_flags & MS_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))

older user-space packages won't know the offsetofend macro, so they
won't build against these kernel headers anymore. Maybe you want to
open-code that?

>  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 */
>  };
>
>  /*
>

Andreas

Reply via email to