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 *)¬hing,
> 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