summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2018-01-16 18:01:33 -0500
committerBob Peterson <rpeterso@redhat.com>2018-01-23 09:38:53 -0500
commitc1696fb85d33194cf65c7ebfc82a75696299c3a3 (patch)
treee6c2faba8786f73db8270822c4fb263cad57b207
parent0ff5916ad4eb857e03e7586665d1c022ef3277f6 (diff)
GFS2: Introduce new gfs2_log_header_v2
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> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
-rw-r--r--fs/gfs2/Kconfig2
-rw-r--r--fs/gfs2/aops.c2
-rw-r--r--fs/gfs2/file.c3
-rw-r--r--fs/gfs2/glops.c13
-rw-r--r--fs/gfs2/log.c75
-rw-r--r--fs/gfs2/log.h12
-rw-r--r--fs/gfs2/lops.c16
-rw-r--r--fs/gfs2/lops.h3
-rw-r--r--fs/gfs2/ops_fstype.c2
-rw-r--r--fs/gfs2/quota.c3
-rw-r--r--fs/gfs2/recovery.c17
-rw-r--r--fs/gfs2/rgrp.c2
-rw-r--r--fs/gfs2/super.c9
-rw-r--r--fs/gfs2/trans.c2
-rw-r--r--include/uapi/linux/gfs2_ondisk.h26
15 files changed, 128 insertions, 59 deletions
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index 43c827a7cce5..c0225d4b5435 100644
--- a/fs/gfs2/Kconfig
+++ b/fs/gfs2/Kconfig
@@ -3,6 +3,8 @@ config GFS2_FS
3 depends on (64BIT || LBDAF) 3 depends on (64BIT || LBDAF)
4 select FS_POSIX_ACL 4 select FS_POSIX_ACL
5 select CRC32 5 select CRC32
6 select CRYPTO
7 select CRYPTO_CRC32C
6 select QUOTACTL 8 select QUOTACTL
7 select FS_IOMAP 9 select FS_IOMAP
8 help 10 help
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index ac4a1e89da1e..462c3fd55929 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -448,7 +448,7 @@ static int gfs2_jdata_writepages(struct address_space *mapping,
448 448
449 ret = gfs2_write_cache_jdata(mapping, wbc); 449 ret = gfs2_write_cache_jdata(mapping, wbc);
450 if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) { 450 if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) {
451 gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH); 451 gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
452 ret = gfs2_write_cache_jdata(mapping, wbc); 452 ret = gfs2_write_cache_jdata(mapping, wbc);
453 } 453 }
454 return ret; 454 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)
246 } 246 }
247 if ((flags ^ new_flags) & GFS2_DIF_JDATA) { 247 if ((flags ^ new_flags) & GFS2_DIF_JDATA) {
248 if (new_flags & GFS2_DIF_JDATA) 248 if (new_flags & GFS2_DIF_JDATA)
249 gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH); 249 gfs2_log_flush(sdp, ip->i_gl,
250 GFS2_LOG_HEAD_FLUSH_NORMAL);
250 error = filemap_fdatawrite(inode->i_mapping); 251 error = filemap_fdatawrite(inode->i_mapping);
251 if (error) 252 if (error)
252 goto out; 253 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)
107 __gfs2_ail_flush(gl, 0, tr.tr_revokes); 107 __gfs2_ail_flush(gl, 0, tr.tr_revokes);
108 108
109 gfs2_trans_end(sdp); 109 gfs2_trans_end(sdp);
110 gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); 110 gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
111} 111}
112 112
113void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) 113void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
@@ -128,7 +128,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
128 return; 128 return;
129 __gfs2_ail_flush(gl, fsync, max_revokes); 129 __gfs2_ail_flush(gl, fsync, max_revokes);
130 gfs2_trans_end(sdp); 130 gfs2_trans_end(sdp);
131 gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); 131 gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
132} 132}
133 133
134/** 134/**
@@ -157,7 +157,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
157 return; 157 return;
158 GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE); 158 GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
159 159
160 gfs2_log_flush(sdp, gl, NORMAL_FLUSH); 160 gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
161 filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end); 161 filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
162 error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end); 162 error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
163 mapping_set_error(mapping, error); 163 mapping_set_error(mapping, error);
@@ -252,7 +252,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
252 252
253 GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE); 253 GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
254 254
255 gfs2_log_flush(gl->gl_name.ln_sbd, gl, NORMAL_FLUSH); 255 gfs2_log_flush(gl->gl_name.ln_sbd, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
256 filemap_fdatawrite(metamapping); 256 filemap_fdatawrite(metamapping);
257 if (isreg) { 257 if (isreg) {
258 struct address_space *mapping = ip->i_inode.i_mapping; 258 struct address_space *mapping = ip->i_inode.i_mapping;
@@ -303,7 +303,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
303 } 303 }
304 304
305 if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) { 305 if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) {
306 gfs2_log_flush(gl->gl_name.ln_sbd, NULL, NORMAL_FLUSH); 306 gfs2_log_flush(gl->gl_name.ln_sbd, NULL,
307 GFS2_LOG_HEAD_FLUSH_NORMAL);
307 gl->gl_name.ln_sbd->sd_rindex_uptodate = 0; 308 gl->gl_name.ln_sbd->sd_rindex_uptodate = 0;
308 } 309 }
309 if (ip && S_ISREG(ip->i_inode.i_mode)) 310 if (ip && S_ISREG(ip->i_inode.i_mode))
@@ -495,7 +496,7 @@ static void freeze_go_sync(struct gfs2_glock *gl)
495 gfs2_assert_withdraw(sdp, 0); 496 gfs2_assert_withdraw(sdp, 0);
496 } 497 }
497 queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work); 498 queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
498 gfs2_log_flush(sdp, NULL, FREEZE_FLUSH); 499 gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE);
499 } 500 }
500} 501}
501 502
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 @@
14#include <linux/buffer_head.h> 14#include <linux/buffer_head.h>
15#include <linux/gfs2_ondisk.h> 15#include <linux/gfs2_ondisk.h>
16#include <linux/crc32.h> 16#include <linux/crc32.h>
17#include <linux/crc32c.h>
17#include <linux/delay.h> 18#include <linux/delay.h>
18#include <linux/kthread.h> 19#include <linux/kthread.h>
19#include <linux/freezer.h> 20#include <linux/freezer.h>
@@ -653,20 +654,25 @@ out_of_blocks:
653/** 654/**
654 * write_log_header - Write a journal log header buffer at sd_log_flush_head 655 * write_log_header - Write a journal log header buffer at sd_log_flush_head
655 * @sdp: The GFS2 superblock 656 * @sdp: The GFS2 superblock
657 * @jd: journal descriptor of the journal to which we are writing
656 * @seq: sequence number 658 * @seq: sequence number
657 * @tail: tail of the log 659 * @tail: tail of the log
658 * @flags: log header flags 660 * @flags: log header flags GFS2_LOG_HEAD_*
659 * @op_flags: flags to pass to the bio 661 * @op_flags: flags to pass to the bio
660 * 662 *
661 * Returns: the initialized log buffer descriptor 663 * Returns: the initialized log buffer descriptor
662 */ 664 */
663 665
664void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail, 666void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
665 u32 flags, int op_flags) 667 u64 seq, u32 tail, u32 flags, int op_flags)
666{ 668{
667 struct gfs2_log_header *lh; 669 struct gfs2_log_header *lh;
668 u32 hash; 670 u32 hash, crc;
669 struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO); 671 struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
672 struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
673 struct timespec64 tv;
674 struct super_block *sb = sdp->sd_vfs;
675 u64 addr;
670 676
671 lh = page_address(page); 677 lh = page_address(page);
672 clear_page(lh); 678 clear_page(lh);
@@ -680,10 +686,39 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
680 lh->lh_flags = cpu_to_be32(flags); 686 lh->lh_flags = cpu_to_be32(flags);
681 lh->lh_tail = cpu_to_be32(tail); 687 lh->lh_tail = cpu_to_be32(tail);
682 lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head); 688 lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
683 hash = ~crc32(~0, lh, sizeof(*lh)); 689 hash = ~crc32(~0, lh, LH_V1_SIZE);
684 lh->lh_hash = cpu_to_be32(hash); 690 lh->lh_hash = cpu_to_be32(hash);
685 691
686 gfs2_log_write_page(sdp, page); 692 tv = current_kernel_time64();
693 lh->lh_nsec = cpu_to_be32(tv.tv_nsec);
694 lh->lh_sec = cpu_to_be64(tv.tv_sec);
695 addr = gfs2_log_bmap(sdp);
696 lh->lh_addr = cpu_to_be64(addr);
697 lh->lh_jinode = cpu_to_be64(GFS2_I(jd->jd_inode)->i_no_addr);
698
699 /* We may only write local statfs, quota, etc., when writing to our
700 own journal. The values are left 0 when recovering a journal
701 different from our own. */
702 if (!(flags & GFS2_LOG_HEAD_RECOVERY)) {
703 lh->lh_statfs_addr =
704 cpu_to_be64(GFS2_I(sdp->sd_sc_inode)->i_no_addr);
705 lh->lh_quota_addr =
706 cpu_to_be64(GFS2_I(sdp->sd_qc_inode)->i_no_addr);
707
708 spin_lock(&sdp->sd_statfs_spin);
709 lh->lh_local_total = cpu_to_be64(l_sc->sc_total);
710 lh->lh_local_free = cpu_to_be64(l_sc->sc_free);
711 lh->lh_local_dinodes = cpu_to_be64(l_sc->sc_dinodes);
712 spin_unlock(&sdp->sd_statfs_spin);
713 }
714
715 BUILD_BUG_ON(offsetof(struct gfs2_log_header, lh_crc) != LH_V1_SIZE);
716
717 crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
718 sb->s_blocksize - LH_V1_SIZE - 4);
719 lh->lh_crc = cpu_to_be32(crc);
720
721 gfs2_log_write(sdp, page, sb->s_blocksize, 0, addr);
687 gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags); 722 gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags);
688 log_flush_wait(sdp); 723 log_flush_wait(sdp);
689} 724}
@@ -691,6 +726,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
691/** 726/**
692 * log_write_header - Get and initialize a journal header buffer 727 * log_write_header - Get and initialize a journal header buffer
693 * @sdp: The GFS2 superblock 728 * @sdp: The GFS2 superblock
729 * @flags: The log header flags, including log header origin
694 * 730 *
695 * Returns: the initialized log buffer descriptor 731 * Returns: the initialized log buffer descriptor
696 */ 732 */
@@ -710,8 +746,8 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
710 op_flags = REQ_SYNC | REQ_META | REQ_PRIO; 746 op_flags = REQ_SYNC | REQ_META | REQ_PRIO;
711 } 747 }
712 sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); 748 sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
713 gfs2_write_log_header(sdp, sdp->sd_log_sequence++, tail, flags, 749 gfs2_write_log_header(sdp, sdp->sd_jdesc, sdp->sd_log_sequence++, tail,
714 op_flags); 750 flags, op_flags);
715 751
716 if (sdp->sd_log_tail != tail) 752 if (sdp->sd_log_tail != tail)
717 log_pull_tail(sdp, tail); 753 log_pull_tail(sdp, tail);
@@ -721,11 +757,11 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
721 * gfs2_log_flush - flush incore transaction(s) 757 * gfs2_log_flush - flush incore transaction(s)
722 * @sdp: the filesystem 758 * @sdp: the filesystem
723 * @gl: The glock structure to flush. If NULL, flush the whole incore log 759 * @gl: The glock structure to flush. If NULL, flush the whole incore log
760 * @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_*
724 * 761 *
725 */ 762 */
726 763
727void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, 764void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
728 enum gfs2_flush_type type)
729{ 765{
730 struct gfs2_trans *tr; 766 struct gfs2_trans *tr;
731 enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); 767 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,
739 } 775 }
740 trace_gfs2_log_flush(sdp, 1); 776 trace_gfs2_log_flush(sdp, 1);
741 777
742 if (type == SHUTDOWN_FLUSH) 778 if (flags & GFS2_LOG_HEAD_FLUSH_SHUTDOWN)
743 clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); 779 clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
744 780
745 sdp->sd_log_flush_head = sdp->sd_log_head; 781 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,
764 800
765 if (sdp->sd_log_head != sdp->sd_log_flush_head) { 801 if (sdp->sd_log_head != sdp->sd_log_flush_head) {
766 log_flush_wait(sdp); 802 log_flush_wait(sdp);
767 log_write_header(sdp, 0); 803 log_write_header(sdp, flags);
768 } else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ 804 } else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
769 atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */ 805 atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
770 trace_gfs2_log_blocks(sdp, -1); 806 trace_gfs2_log_blocks(sdp, -1);
771 log_write_header(sdp, 0); 807 log_write_header(sdp, flags);
772 } 808 }
773 lops_after_commit(sdp, tr); 809 lops_after_commit(sdp, tr);
774 810
@@ -785,7 +821,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
785 spin_unlock(&sdp->sd_ail_lock); 821 spin_unlock(&sdp->sd_ail_lock);
786 gfs2_log_unlock(sdp); 822 gfs2_log_unlock(sdp);
787 823
788 if (type != NORMAL_FLUSH) { 824 if (!(flags & GFS2_LOG_HEAD_FLUSH_NORMAL)) {
789 if (!sdp->sd_log_idle) { 825 if (!sdp->sd_log_idle) {
790 for (;;) { 826 for (;;) {
791 gfs2_ail1_start(sdp); 827 gfs2_ail1_start(sdp);
@@ -795,12 +831,13 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
795 } 831 }
796 atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */ 832 atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
797 trace_gfs2_log_blocks(sdp, -1); 833 trace_gfs2_log_blocks(sdp, -1);
798 log_write_header(sdp, 0); 834 log_write_header(sdp, flags);
799 sdp->sd_log_head = sdp->sd_log_flush_head; 835 sdp->sd_log_head = sdp->sd_log_flush_head;
800 } 836 }
801 if (type == SHUTDOWN_FLUSH || type == FREEZE_FLUSH) 837 if (flags & (GFS2_LOG_HEAD_FLUSH_SHUTDOWN |
838 GFS2_LOG_HEAD_FLUSH_FREEZE))
802 gfs2_log_shutdown(sdp); 839 gfs2_log_shutdown(sdp);
803 if (type == FREEZE_FLUSH) 840 if (flags & GFS2_LOG_HEAD_FLUSH_FREEZE)
804 atomic_set(&sdp->sd_freeze_state, SFS_FROZEN); 841 atomic_set(&sdp->sd_freeze_state, SFS_FROZEN);
805 } 842 }
806 843
@@ -956,7 +993,7 @@ int gfs2_logd(void *data)
956 did_flush = false; 993 did_flush = false;
957 if (gfs2_jrnl_flush_reqd(sdp) || t == 0) { 994 if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
958 gfs2_ail1_empty(sdp); 995 gfs2_ail1_empty(sdp);
959 gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); 996 gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
960 did_flush = true; 997 did_flush = true;
961 } 998 }
962 999
@@ -964,7 +1001,7 @@ int gfs2_logd(void *data)
964 gfs2_ail1_start(sdp); 1001 gfs2_ail1_start(sdp);
965 gfs2_ail1_wait(sdp); 1002 gfs2_ail1_wait(sdp);
966 gfs2_ail1_empty(sdp); 1003 gfs2_ail1_empty(sdp);
967 gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); 1004 gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
968 did_flush = true; 1005 did_flush = true;
969 } 1006 }
970 1007
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,
65 65
66extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks); 66extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks);
67extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); 67extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
68enum gfs2_flush_type { 68extern void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
69 NORMAL_FLUSH = 0, 69 u64 seq, u32 tail, u32 flags, int op_flags);
70 SYNC_FLUSH,
71 SHUTDOWN_FLUSH,
72 FREEZE_FLUSH
73};
74extern void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
75 u32 flags, int op_flags);
76extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, 70extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
77 enum gfs2_flush_type type); 71 u32 type);
78extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); 72extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
79extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd); 73extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
80extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc); 74extern 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 @@
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/list_sort.h> 19#include <linux/list_sort.h>
20 20
21#include "dir.h"
21#include "gfs2.h" 22#include "gfs2.h"
22#include "incore.h" 23#include "incore.h"
23#include "inode.h" 24#include "inode.h"
@@ -138,7 +139,7 @@ static void gfs2_log_incr_head(struct gfs2_sbd *sdp)
138 sdp->sd_log_flush_head = 0; 139 sdp->sd_log_flush_head = 0;
139} 140}
140 141
141static u64 gfs2_log_bmap(struct gfs2_sbd *sdp) 142u64 gfs2_log_bmap(struct gfs2_sbd *sdp)
142{ 143{
143 unsigned int lbn = sdp->sd_log_flush_head; 144 unsigned int lbn = sdp->sd_log_flush_head;
144 struct gfs2_journal_extent *je; 145 struct gfs2_journal_extent *je;
@@ -306,23 +307,22 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno)
306 return gfs2_log_alloc_bio(sdp, blkno); 307 return gfs2_log_alloc_bio(sdp, blkno);
307} 308}
308 309
309
310/** 310/**
311 * gfs2_log_write - write to log 311 * gfs2_log_write - write to log
312 * @sdp: the filesystem 312 * @sdp: the filesystem
313 * @page: the page to write 313 * @page: the page to write
314 * @size: the size of the data to write 314 * @size: the size of the data to write
315 * @offset: the offset within the page 315 * @offset: the offset within the page
316 * @blkno: block number of the log entry
316 * 317 *
317 * Try and add the page segment to the current bio. If that fails, 318 * Try and add the page segment to the current bio. If that fails,
318 * submit the current bio to the device and create a new one, and 319 * submit the current bio to the device and create a new one, and
319 * then add the page segment to that. 320 * then add the page segment to that.
320 */ 321 */
321 322
322static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page, 323void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
323 unsigned size, unsigned offset) 324 unsigned size, unsigned offset, u64 blkno)
324{ 325{
325 u64 blkno = gfs2_log_bmap(sdp);
326 struct bio *bio; 326 struct bio *bio;
327 int ret; 327 int ret;
328 328
@@ -348,7 +348,8 @@ static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
348 348
349static void gfs2_log_write_bh(struct gfs2_sbd *sdp, struct buffer_head *bh) 349static void gfs2_log_write_bh(struct gfs2_sbd *sdp, struct buffer_head *bh)
350{ 350{
351 gfs2_log_write(sdp, bh->b_page, bh->b_size, bh_offset(bh)); 351 gfs2_log_write(sdp, bh->b_page, bh->b_size, bh_offset(bh),
352 gfs2_log_bmap(sdp));
352} 353}
353 354
354/** 355/**
@@ -365,7 +366,8 @@ static void gfs2_log_write_bh(struct gfs2_sbd *sdp, struct buffer_head *bh)
365void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page) 366void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page)
366{ 367{
367 struct super_block *sb = sdp->sd_vfs; 368 struct super_block *sb = sdp->sd_vfs;
368 gfs2_log_write(sdp, page, sb->s_blocksize, 0); 369 gfs2_log_write(sdp, page, sb->s_blocksize, 0,
370 gfs2_log_bmap(sdp));
369} 371}
370 372
371static struct page *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type, 373static 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;
26extern const struct gfs2_log_operations gfs2_databuf_lops; 26extern const struct gfs2_log_operations gfs2_databuf_lops;
27 27
28extern const struct gfs2_log_operations *gfs2_log_ops[]; 28extern const struct gfs2_log_operations *gfs2_log_ops[];
29extern u64 gfs2_log_bmap(struct gfs2_sbd *sdp);
30extern void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
31 unsigned size, unsigned offset, u64 blkno);
29extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page); 32extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page);
30extern void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int op, int op_flags); 33extern void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int op, int op_flags);
31extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh); 34extern 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)
1382 return; 1382 return;
1383 } 1383 }
1384 1384
1385 gfs2_log_flush(sdp, NULL, SYNC_FLUSH); 1385 gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SYNC);
1386 dput(sdp->sd_root_dir); 1386 dput(sdp->sd_root_dir);
1387 dput(sdp->sd_master_dir); 1387 dput(sdp->sd_master_dir);
1388 sdp->sd_root_dir = NULL; 1388 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 @@ out:
955 gfs2_glock_dq_uninit(&ghs[qx]); 955 gfs2_glock_dq_uninit(&ghs[qx]);
956 inode_unlock(&ip->i_inode); 956 inode_unlock(&ip->i_inode);
957 kfree(ghs); 957 kfree(ghs);
958 gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl, NORMAL_FLUSH); 958 gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl,
959 GFS2_LOG_HEAD_FLUSH_NORMAL);
959 return error; 960 return error;
960} 961}
961 962
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 @@
14#include <linux/buffer_head.h> 14#include <linux/buffer_head.h>
15#include <linux/gfs2_ondisk.h> 15#include <linux/gfs2_ondisk.h>
16#include <linux/crc32.h> 16#include <linux/crc32.h>
17#include <linux/crc32c.h>
17 18
18#include "gfs2.h" 19#include "gfs2.h"
19#include "incore.h" 20#include "incore.h"
@@ -137,7 +138,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
137{ 138{
138 struct gfs2_log_header *lh; 139 struct gfs2_log_header *lh;
139 struct buffer_head *bh; 140 struct buffer_head *bh;
140 u32 hash; 141 u32 hash, crc;
141 int error; 142 int error;
142 143
143 error = gfs2_replay_read_block(jd, blk, &bh); 144 error = gfs2_replay_read_block(jd, blk, &bh);
@@ -145,13 +146,17 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
145 return error; 146 return error;
146 lh = (void *)bh->b_data; 147 lh = (void *)bh->b_data;
147 148
148 hash = crc32(~0, lh, sizeof(*lh) - 4); 149 hash = crc32(~0, lh, LH_V1_SIZE - 4);
149 hash = ~crc32_le_shift(hash, 4); /* assume lh_hash is zero */ 150 hash = ~crc32_le_shift(hash, 4); /* assume lh_hash is zero */
150 151
152 crc = crc32c(~0, (void *)lh + LH_V1_SIZE + 4,
153 bh->b_size - LH_V1_SIZE - 4);
154
151 error = lh->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) || 155 error = lh->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
152 lh->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH) || 156 lh->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH) ||
153 be32_to_cpu(lh->lh_blkno) != blk || 157 be32_to_cpu(lh->lh_blkno) != blk ||
154 be32_to_cpu(lh->lh_hash) != hash; 158 be32_to_cpu(lh->lh_hash) != hash ||
159 (lh->lh_crc != 0 && be32_to_cpu(lh->lh_crc) != crc);
155 160
156 brelse(bh); 161 brelse(bh);
157 162
@@ -372,9 +377,9 @@ static void clean_journal(struct gfs2_jdesc *jd,
372 377
373 sdp->sd_log_flush_head = head->lh_blkno; 378 sdp->sd_log_flush_head = head->lh_blkno;
374 gfs2_replay_incr_blk(jd, &sdp->sd_log_flush_head); 379 gfs2_replay_incr_blk(jd, &sdp->sd_log_flush_head);
375 gfs2_write_log_header(sdp, head->lh_sequence + 1, 0, 380 gfs2_write_log_header(sdp, jd, head->lh_sequence + 1, 0,
376 GFS2_LOG_HEAD_UNMOUNT, REQ_PREFLUSH | 381 GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_RECOVERY,
377 REQ_FUA | REQ_META | REQ_SYNC); 382 REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC);
378} 383}
379 384
380 385
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 @@ next_rgrp:
2093 } 2093 }
2094 /* Flushing the log may release space */ 2094 /* Flushing the log may release space */
2095 if (loops == 2) 2095 if (loops == 2)
2096 gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); 2096 gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
2097 } 2097 }
2098 2098
2099 return -ENOSPC; 2099 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)
757 bool flush_all = (wbc->sync_mode == WB_SYNC_ALL || gfs2_is_jdata(ip)); 757 bool flush_all = (wbc->sync_mode == WB_SYNC_ALL || gfs2_is_jdata(ip));
758 758
759 if (flush_all) 759 if (flush_all)
760 gfs2_log_flush(GFS2_SB(inode), ip->i_gl, NORMAL_FLUSH); 760 gfs2_log_flush(GFS2_SB(inode), ip->i_gl,
761 GFS2_LOG_HEAD_FLUSH_NORMAL);
761 if (bdi->wb.dirty_exceeded) 762 if (bdi->wb.dirty_exceeded)
762 gfs2_ail1_flush(sdp, wbc); 763 gfs2_ail1_flush(sdp, wbc);
763 else 764 else
@@ -853,7 +854,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
853 gfs2_quota_sync(sdp->sd_vfs, 0); 854 gfs2_quota_sync(sdp->sd_vfs, 0);
854 gfs2_statfs_sync(sdp->sd_vfs, 0); 855 gfs2_statfs_sync(sdp->sd_vfs, 0);
855 856
856 gfs2_log_flush(sdp, NULL, SHUTDOWN_FLUSH); 857 gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN);
857 wait_event(sdp->sd_reserving_log_wait, atomic_read(&sdp->sd_reserving_log) == 0); 858 wait_event(sdp->sd_reserving_log_wait, atomic_read(&sdp->sd_reserving_log) == 0);
858 gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks); 859 gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
859 860
@@ -946,7 +947,7 @@ static int gfs2_sync_fs(struct super_block *sb, int wait)
946 947
947 gfs2_quota_sync(sb, -1); 948 gfs2_quota_sync(sb, -1);
948 if (wait) 949 if (wait)
949 gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); 950 gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
950 return sdp->sd_log_error; 951 return sdp->sd_log_error;
951} 952}
952 953
@@ -1650,7 +1651,7 @@ alloc_failed:
1650 goto out_unlock; 1651 goto out_unlock;
1651 1652
1652out_truncate: 1653out_truncate:
1653 gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH); 1654 gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
1654 metamapping = gfs2_glock2aspace(ip->i_gl); 1655 metamapping = gfs2_glock2aspace(ip->i_gl);
1655 if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) { 1656 if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) {
1656 filemap_fdatawrite(metamapping); 1657 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)
117 up_read(&sdp->sd_log_flush_lock); 117 up_read(&sdp->sd_log_flush_lock);
118 118
119 if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS) 119 if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS)
120 gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); 120 gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
121 if (alloced) 121 if (alloced)
122 sb_end_intwrite(sdp->sd_vfs); 122 sb_end_intwrite(sdp->sd_vfs);
123} 123}
diff --git a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h
index 09f0920f07e9..9a81d520f54a 100644
--- a/include/uapi/linux/gfs2_ondisk.h
+++ b/include/uapi/linux/gfs2_ondisk.h
@@ -403,7 +403,15 @@ struct gfs2_ea_header {
403 * Log header structure 403 * Log header structure
404 */ 404 */
405 405
406#define GFS2_LOG_HEAD_UNMOUNT 0x00000001 /* log is clean */ 406#define GFS2_LOG_HEAD_UNMOUNT 0x00000001 /* log is clean */
407#define GFS2_LOG_HEAD_FLUSH_NORMAL 0x00000002 /* normal log flush */
408#define GFS2_LOG_HEAD_FLUSH_SYNC 0x00000004 /* Sync log flush */
409#define GFS2_LOG_HEAD_FLUSH_SHUTDOWN 0x00000008 /* Shutdown log flush */
410#define GFS2_LOG_HEAD_FLUSH_FREEZE 0x00000010 /* Freeze flush */
411#define GFS2_LOG_HEAD_RECOVERY 0x00000020 /* Journal recovery */
412#define GFS2_LOG_HEAD_USERSPACE 0x80000000 /* Written by gfs2-utils */
413
414#define LH_V1_SIZE (offsetofend(struct gfs2_log_header, lh_hash))
407 415
408struct gfs2_log_header { 416struct gfs2_log_header {
409 struct gfs2_meta_header lh_header; 417 struct gfs2_meta_header lh_header;
@@ -412,7 +420,21 @@ struct gfs2_log_header {
412 __be32 lh_flags; /* GFS2_LOG_HEAD_... */ 420 __be32 lh_flags; /* GFS2_LOG_HEAD_... */
413 __be32 lh_tail; /* Block number of log tail */ 421 __be32 lh_tail; /* Block number of log tail */
414 __be32 lh_blkno; 422 __be32 lh_blkno;
415 __be32 lh_hash; 423 __be32 lh_hash; /* crc up to here with this field 0 */
424
425 /* Version 2 additional fields start here */
426 __be32 lh_crc; /* crc32c from lh_nsec to end of block */
427 __be32 lh_nsec; /* Nanoseconds of timestamp */
428 __be64 lh_sec; /* Seconds of timestamp */
429 __be64 lh_addr; /* Block addr of this log header (absolute) */
430 __be64 lh_jinode; /* Journal inode number */
431 __be64 lh_statfs_addr; /* Local statfs inode number */
432 __be64 lh_quota_addr; /* Local quota change inode number */
433
434 /* Statfs local changes (i.e. diff from global statfs) */
435 __be64 lh_local_total;
436 __be64 lh_local_free;
437 __be64 lh_local_dinodes;
416}; 438};
417 439
418/* 440/*