aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2019-03-25 11:34:19 -0400
committerAndreas Gruenbacher <agruenba@redhat.com>2019-05-07 17:39:04 -0400
commit7c70b896951c84d63e6d71b82668f9c8b8bbd440 (patch)
tree87b69c01020de67faf1fe3536413146436cd1636 /fs/gfs2
parent7881ef3f33bb80f459ea6020d1e021fc524a6348 (diff)
gfs2: clean_journal improperly set sd_log_flush_head
This patch fixes regressions in 588bff95c94efc05f9e1a0b19015c9408ed7c0ef. Due to that patch, function clean_journal was setting the value of sd_log_flush_head, but that's only valid if it is replaying the node's own journal. If it's replaying another node's journal, that's completely wrong and will lead to multiple problems. This patch tries to clean up the mess by passing the value of the logical journal block number into gfs2_write_log_header so the function can treat non-owned journals generically. For the local journal, the journal extent map is used for best performance. For other nodes from other journals, new function gfs2_lblk_to_dblk is called to figure it out using gfs2_iomap_get. This patch also tries to establish more consistency when passing journal block parameters by changing several unsigned int types to a consistent u32. Fixes: 588bff95c94e ("GFS2: Reduce code redundancy writing log headers") Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/bmap.c26
-rw-r--r--fs/gfs2/bmap.h1
-rw-r--r--fs/gfs2/incore.h2
-rw-r--r--fs/gfs2/log.c24
-rw-r--r--fs/gfs2/log.h3
-rw-r--r--fs/gfs2/lops.c6
-rw-r--r--fs/gfs2/lops.h2
-rw-r--r--fs/gfs2/recovery.c10
-rw-r--r--fs/gfs2/recovery.h2
9 files changed, 57 insertions, 19 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 2f9290f69610..59334e2edffb 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -925,6 +925,32 @@ do_alloc:
925 goto out; 925 goto out;
926} 926}
927 927
928/**
929 * gfs2_lblk_to_dblk - convert logical block to disk block
930 * @inode: the inode of the file we're mapping
931 * @lblock: the block relative to the start of the file
932 * @dblock: the returned dblock, if no error
933 *
934 * This function maps a single block from a file logical block (relative to
935 * the start of the file) to a file system absolute block using iomap.
936 *
937 * Returns: the absolute file system block, or an error
938 */
939int gfs2_lblk_to_dblk(struct inode *inode, u32 lblock, u64 *dblock)
940{
941 struct iomap iomap = { };
942 struct metapath mp = { .mp_aheight = 1, };
943 loff_t pos = (loff_t)lblock << inode->i_blkbits;
944 int ret;
945
946 ret = gfs2_iomap_get(inode, pos, i_blocksize(inode), 0, &iomap, &mp);
947 release_metapath(&mp);
948 if (ret == 0)
949 *dblock = iomap.addr >> inode->i_blkbits;
950
951 return ret;
952}
953
928static int gfs2_write_lock(struct inode *inode) 954static int gfs2_write_lock(struct inode *inode)
929{ 955{
930 struct gfs2_inode *ip = GFS2_I(inode); 956 struct gfs2_inode *ip = GFS2_I(inode);
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h
index 6b18fb323f0a..19a1fd772c61 100644
--- a/fs/gfs2/bmap.h
+++ b/fs/gfs2/bmap.h
@@ -64,5 +64,6 @@ extern int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
64extern int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd); 64extern int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd);
65extern void gfs2_free_journal_extents(struct gfs2_jdesc *jd); 65extern void gfs2_free_journal_extents(struct gfs2_jdesc *jd);
66extern int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length); 66extern int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length);
67extern int gfs2_lblk_to_dblk(struct inode *inode, u32 lblock, u64 *dblock);
67 68
68#endif /* __BMAP_DOT_H__ */ 69#endif /* __BMAP_DOT_H__ */
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index cdf07b408f54..86840a70ee1a 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -535,7 +535,7 @@ struct gfs2_jdesc {
535 unsigned long jd_flags; 535 unsigned long jd_flags;
536#define JDF_RECOVERY 1 536#define JDF_RECOVERY 1
537 unsigned int jd_jid; 537 unsigned int jd_jid;
538 unsigned int jd_blocks; 538 u32 jd_blocks;
539 int jd_recover_error; 539 int jd_recover_error;
540 /* Replay stuff */ 540 /* Replay stuff */
541 541
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index b8830fda51e8..ebbc68dca145 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -666,11 +666,12 @@ out_of_blocks:
666} 666}
667 667
668/** 668/**
669 * write_log_header - Write a journal log header buffer at sd_log_flush_head 669 * gfs2_write_log_header - Write a journal log header buffer at lblock
670 * @sdp: The GFS2 superblock 670 * @sdp: The GFS2 superblock
671 * @jd: journal descriptor of the journal to which we are writing 671 * @jd: journal descriptor of the journal to which we are writing
672 * @seq: sequence number 672 * @seq: sequence number
673 * @tail: tail of the log 673 * @tail: tail of the log
674 * @lblock: value for lh_blkno (block number relative to start of journal)
674 * @flags: log header flags GFS2_LOG_HEAD_* 675 * @flags: log header flags GFS2_LOG_HEAD_*
675 * @op_flags: flags to pass to the bio 676 * @op_flags: flags to pass to the bio
676 * 677 *
@@ -678,7 +679,8 @@ out_of_blocks:
678 */ 679 */
679 680
680void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd, 681void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
681 u64 seq, u32 tail, u32 flags, int op_flags) 682 u64 seq, u32 tail, u32 lblock, u32 flags,
683 int op_flags)
682{ 684{
683 struct gfs2_log_header *lh; 685 struct gfs2_log_header *lh;
684 u32 hash, crc; 686 u32 hash, crc;
@@ -686,7 +688,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
686 struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; 688 struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
687 struct timespec64 tv; 689 struct timespec64 tv;
688 struct super_block *sb = sdp->sd_vfs; 690 struct super_block *sb = sdp->sd_vfs;
689 u64 addr; 691 u64 dblock;
690 692
691 lh = page_address(page); 693 lh = page_address(page);
692 clear_page(lh); 694 clear_page(lh);
@@ -699,15 +701,21 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
699 lh->lh_sequence = cpu_to_be64(seq); 701 lh->lh_sequence = cpu_to_be64(seq);
700 lh->lh_flags = cpu_to_be32(flags); 702 lh->lh_flags = cpu_to_be32(flags);
701 lh->lh_tail = cpu_to_be32(tail); 703 lh->lh_tail = cpu_to_be32(tail);
702 lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head); 704 lh->lh_blkno = cpu_to_be32(lblock);
703 hash = ~crc32(~0, lh, LH_V1_SIZE); 705 hash = ~crc32(~0, lh, LH_V1_SIZE);
704 lh->lh_hash = cpu_to_be32(hash); 706 lh->lh_hash = cpu_to_be32(hash);
705 707
706 ktime_get_coarse_real_ts64(&tv); 708 ktime_get_coarse_real_ts64(&tv);
707 lh->lh_nsec = cpu_to_be32(tv.tv_nsec); 709 lh->lh_nsec = cpu_to_be32(tv.tv_nsec);
708 lh->lh_sec = cpu_to_be64(tv.tv_sec); 710 lh->lh_sec = cpu_to_be64(tv.tv_sec);
709 addr = gfs2_log_bmap(sdp); 711 if (!list_empty(&jd->extent_list))
710 lh->lh_addr = cpu_to_be64(addr); 712 dblock = gfs2_log_bmap(sdp);
713 else {
714 int ret = gfs2_lblk_to_dblk(jd->jd_inode, lblock, &dblock);
715 if (gfs2_assert_withdraw(sdp, ret == 0))
716 return;
717 }
718 lh->lh_addr = cpu_to_be64(dblock);
711 lh->lh_jinode = cpu_to_be64(GFS2_I(jd->jd_inode)->i_no_addr); 719 lh->lh_jinode = cpu_to_be64(GFS2_I(jd->jd_inode)->i_no_addr);
712 720
713 /* We may only write local statfs, quota, etc., when writing to our 721 /* We may only write local statfs, quota, etc., when writing to our
@@ -732,7 +740,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
732 sb->s_blocksize - LH_V1_SIZE - 4); 740 sb->s_blocksize - LH_V1_SIZE - 4);
733 lh->lh_crc = cpu_to_be32(crc); 741 lh->lh_crc = cpu_to_be32(crc);
734 742
735 gfs2_log_write(sdp, page, sb->s_blocksize, 0, addr); 743 gfs2_log_write(sdp, page, sb->s_blocksize, 0, dblock);
736 gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE, op_flags); 744 gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE, op_flags);
737 log_flush_wait(sdp); 745 log_flush_wait(sdp);
738} 746}
@@ -761,7 +769,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
761 } 769 }
762 sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); 770 sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
763 gfs2_write_log_header(sdp, sdp->sd_jdesc, sdp->sd_log_sequence++, tail, 771 gfs2_write_log_header(sdp, sdp->sd_jdesc, sdp->sd_log_sequence++, tail,
764 flags, op_flags); 772 sdp->sd_log_flush_head, flags, op_flags);
765 773
766 if (sdp->sd_log_tail != tail) 774 if (sdp->sd_log_tail != tail)
767 log_pull_tail(sdp, tail); 775 log_pull_tail(sdp, tail);
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h
index 1bc9bd444b28..86d07d436cdf 100644
--- a/fs/gfs2/log.h
+++ b/fs/gfs2/log.h
@@ -70,7 +70,8 @@ extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
70extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks); 70extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks);
71extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); 71extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
72extern void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd, 72extern void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
73 u64 seq, u32 tail, u32 flags, int op_flags); 73 u64 seq, u32 tail, u32 lblock, u32 flags,
74 int op_flags);
74extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, 75extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
75 u32 type); 76 u32 type);
76extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); 77extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 8722c60b11fe..aef21b6a608f 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -530,7 +530,7 @@ static void buf_lo_before_scan(struct gfs2_jdesc *jd,
530 jd->jd_replayed_blocks = 0; 530 jd->jd_replayed_blocks = 0;
531} 531}
532 532
533static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, 533static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start,
534 struct gfs2_log_descriptor *ld, __be64 *ptr, 534 struct gfs2_log_descriptor *ld, __be64 *ptr,
535 int pass) 535 int pass)
536{ 536{
@@ -685,7 +685,7 @@ static void revoke_lo_before_scan(struct gfs2_jdesc *jd,
685 jd->jd_replay_tail = head->lh_tail; 685 jd->jd_replay_tail = head->lh_tail;
686} 686}
687 687
688static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, 688static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, u32 start,
689 struct gfs2_log_descriptor *ld, __be64 *ptr, 689 struct gfs2_log_descriptor *ld, __be64 *ptr,
690 int pass) 690 int pass)
691{ 691{
@@ -767,7 +767,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr
767 gfs2_before_commit(sdp, limit, nbuf, &tr->tr_databuf, 1); 767 gfs2_before_commit(sdp, limit, nbuf, &tr->tr_databuf, 1);
768} 768}
769 769
770static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, 770static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start,
771 struct gfs2_log_descriptor *ld, 771 struct gfs2_log_descriptor *ld,
772 __be64 *ptr, int pass) 772 __be64 *ptr, int pass)
773{ 773{
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
index 711c4d89c063..4e81742de7a0 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -77,7 +77,7 @@ static inline void lops_before_scan(struct gfs2_jdesc *jd,
77 gfs2_log_ops[x]->lo_before_scan(jd, head, pass); 77 gfs2_log_ops[x]->lo_before_scan(jd, head, pass);
78} 78}
79 79
80static inline int lops_scan_elements(struct gfs2_jdesc *jd, unsigned int start, 80static inline int lops_scan_elements(struct gfs2_jdesc *jd, u32 start,
81 struct gfs2_log_descriptor *ld, 81 struct gfs2_log_descriptor *ld,
82 __be64 *ptr, 82 __be64 *ptr,
83 unsigned int pass) 83 unsigned int pass)
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 2dac43065382..fa575d1676b9 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -316,7 +316,7 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
316 * Returns: errno 316 * Returns: errno
317 */ 317 */
318 318
319static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start, 319static int foreach_descriptor(struct gfs2_jdesc *jd, u32 start,
320 unsigned int end, int pass) 320 unsigned int end, int pass)
321{ 321{
322 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); 322 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
@@ -386,10 +386,12 @@ static void clean_journal(struct gfs2_jdesc *jd,
386 struct gfs2_log_header_host *head) 386 struct gfs2_log_header_host *head)
387{ 387{
388 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); 388 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
389 u32 lblock = head->lh_blkno;
389 390
390 sdp->sd_log_flush_head = head->lh_blkno; 391 gfs2_replay_incr_blk(jd, &lblock);
391 gfs2_replay_incr_blk(jd, &sdp->sd_log_flush_head); 392 if (jd->jd_jid == sdp->sd_lockstruct.ls_jid)
392 gfs2_write_log_header(sdp, jd, head->lh_sequence + 1, 0, 393 sdp->sd_log_flush_head = lblock;
394 gfs2_write_log_header(sdp, jd, head->lh_sequence + 1, 0, lblock,
393 GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_RECOVERY, 395 GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_RECOVERY,
394 REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC); 396 REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC);
395} 397}
diff --git a/fs/gfs2/recovery.h b/fs/gfs2/recovery.h
index 11d81248be85..5932d4b6f43e 100644
--- a/fs/gfs2/recovery.h
+++ b/fs/gfs2/recovery.h
@@ -14,7 +14,7 @@
14 14
15extern struct workqueue_struct *gfs_recovery_wq; 15extern struct workqueue_struct *gfs_recovery_wq;
16 16
17static inline void gfs2_replay_incr_blk(struct gfs2_jdesc *jd, unsigned int *blk) 17static inline void gfs2_replay_incr_blk(struct gfs2_jdesc *jd, u32 *blk)
18{ 18{
19 if (++*blk == jd->jd_blocks) 19 if (++*blk == jd->jd_blocks)
20 *blk = 0; 20 *blk = 0;