diff options
-rw-r--r-- | fs/gfs2/Kconfig | 2 | ||||
-rw-r--r-- | fs/gfs2/aops.c | 2 | ||||
-rw-r--r-- | fs/gfs2/file.c | 3 | ||||
-rw-r--r-- | fs/gfs2/glops.c | 13 | ||||
-rw-r--r-- | fs/gfs2/log.c | 75 | ||||
-rw-r--r-- | fs/gfs2/log.h | 12 | ||||
-rw-r--r-- | fs/gfs2/lops.c | 16 | ||||
-rw-r--r-- | fs/gfs2/lops.h | 3 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 2 | ||||
-rw-r--r-- | fs/gfs2/quota.c | 3 | ||||
-rw-r--r-- | fs/gfs2/recovery.c | 17 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 2 | ||||
-rw-r--r-- | fs/gfs2/super.c | 9 | ||||
-rw-r--r-- | fs/gfs2/trans.c | 2 | ||||
-rw-r--r-- | include/uapi/linux/gfs2_ondisk.h | 26 |
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 | ||
113 | void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) | 113 | void 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 | ||
664 | void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail, | 666 | void 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 | ||
727 | void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, | 764 | void 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 | ||
66 | extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks); | 66 | extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks); |
67 | extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); | 67 | extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); |
68 | enum gfs2_flush_type { | 68 | extern 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 | }; | ||
74 | extern void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail, | ||
75 | u32 flags, int op_flags); | ||
76 | extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, | 70 | extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, |
77 | enum gfs2_flush_type type); | 71 | u32 type); |
78 | extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); | 72 | extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); |
79 | extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd); | 73 | extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd); |
80 | extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc); | 74 | 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..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 | ||
141 | static u64 gfs2_log_bmap(struct gfs2_sbd *sdp) | 142 | u64 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 | ||
322 | static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page, | 323 | void 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 | ||
349 | static void gfs2_log_write_bh(struct gfs2_sbd *sdp, struct buffer_head *bh) | 349 | static 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) | |||
365 | void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page) | 366 | void 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 | ||
371 | static struct page *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type, | 373 | 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..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; | |||
26 | extern const struct gfs2_log_operations gfs2_databuf_lops; | 26 | extern const struct gfs2_log_operations gfs2_databuf_lops; |
27 | 27 | ||
28 | extern const struct gfs2_log_operations *gfs2_log_ops[]; | 28 | extern const struct gfs2_log_operations *gfs2_log_ops[]; |
29 | extern u64 gfs2_log_bmap(struct gfs2_sbd *sdp); | ||
30 | extern void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page, | ||
31 | unsigned size, unsigned offset, u64 blkno); | ||
29 | extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page); | 32 | extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page); |
30 | extern void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int op, int op_flags); | 33 | extern void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int op, int op_flags); |
31 | extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh); | 34 | 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 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 | ||
1652 | out_truncate: | 1653 | out_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 | ||
408 | struct gfs2_log_header { | 416 | struct 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 | /* |