aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2014-03-06 17:19:15 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2014-03-07 04:14:48 -0500
commita17d758b661d6fa01a0d466d7bdda3c131bb68f9 (patch)
tree974c88f31959ab2f54483542c1b96e1fc257612b /fs/gfs2
parentfc554ed3d89d220b9d0c020e19aa52fb6bf1d673 (diff)
GFS2: Move recovery variables to journal structure in memory
If multiple nodes fail and their recovery work runs simultaneously, they would use the same unprotected variables in the superblock. For example, they would stomp on each other's revoked blocks lists, which resulted in file system metadata corruption. This patch moves the necessary variables so that each journal has its own separate area for tracking its journal replay. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/incore.h18
-rw-r--r--fs/gfs2/lops.c38
-rw-r--r--fs/gfs2/ops_fstype.c4
-rw-r--r--fs/gfs2/recovery.c16
-rw-r--r--fs/gfs2/recovery.h6
5 files changed, 39 insertions, 43 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 456d8fa9da2b..ef26ed98e778 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -503,6 +503,15 @@ struct gfs2_jdesc {
503 unsigned int jd_jid; 503 unsigned int jd_jid;
504 unsigned int jd_blocks; 504 unsigned int jd_blocks;
505 int jd_recover_error; 505 int jd_recover_error;
506 /* Replay stuff */
507
508 unsigned int jd_found_blocks;
509 unsigned int jd_found_revokes;
510 unsigned int jd_replayed_blocks;
511
512 struct list_head jd_revoke_list;
513 unsigned int jd_replay_tail;
514
506}; 515};
507 516
508struct gfs2_statfs_change_host { 517struct gfs2_statfs_change_host {
@@ -782,15 +791,6 @@ struct gfs2_sbd {
782 struct list_head sd_ail1_list; 791 struct list_head sd_ail1_list;
783 struct list_head sd_ail2_list; 792 struct list_head sd_ail2_list;
784 793
785 /* Replay stuff */
786
787 struct list_head sd_revoke_list;
788 unsigned int sd_replay_tail;
789
790 unsigned int sd_found_blocks;
791 unsigned int sd_found_revokes;
792 unsigned int sd_replayed_blocks;
793
794 /* For quiescing the filesystem */ 794 /* For quiescing the filesystem */
795 struct gfs2_holder sd_freeze_gh; 795 struct gfs2_holder sd_freeze_gh;
796 796
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index ae1d6352a1eb..a294d8d8bcd4 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -520,13 +520,11 @@ static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
520static void buf_lo_before_scan(struct gfs2_jdesc *jd, 520static void buf_lo_before_scan(struct gfs2_jdesc *jd,
521 struct gfs2_log_header_host *head, int pass) 521 struct gfs2_log_header_host *head, int pass)
522{ 522{
523 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
524
525 if (pass != 0) 523 if (pass != 0)
526 return; 524 return;
527 525
528 sdp->sd_found_blocks = 0; 526 jd->jd_found_blocks = 0;
529 sdp->sd_replayed_blocks = 0; 527 jd->jd_replayed_blocks = 0;
530} 528}
531 529
532static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, 530static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
@@ -549,9 +547,9 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
549 for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) { 547 for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) {
550 blkno = be64_to_cpu(*ptr++); 548 blkno = be64_to_cpu(*ptr++);
551 549
552 sdp->sd_found_blocks++; 550 jd->jd_found_blocks++;
553 551
554 if (gfs2_revoke_check(sdp, blkno, start)) 552 if (gfs2_revoke_check(jd, blkno, start))
555 continue; 553 continue;
556 554
557 error = gfs2_replay_read_block(jd, start, &bh_log); 555 error = gfs2_replay_read_block(jd, start, &bh_log);
@@ -572,7 +570,7 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
572 if (error) 570 if (error)
573 break; 571 break;
574 572
575 sdp->sd_replayed_blocks++; 573 jd->jd_replayed_blocks++;
576 } 574 }
577 575
578 return error; 576 return error;
@@ -615,7 +613,7 @@ static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
615 gfs2_meta_sync(ip->i_gl); 613 gfs2_meta_sync(ip->i_gl);
616 614
617 fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n", 615 fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n",
618 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks); 616 jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks);
619} 617}
620 618
621static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 619static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
@@ -677,13 +675,11 @@ static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
677static void revoke_lo_before_scan(struct gfs2_jdesc *jd, 675static void revoke_lo_before_scan(struct gfs2_jdesc *jd,
678 struct gfs2_log_header_host *head, int pass) 676 struct gfs2_log_header_host *head, int pass)
679{ 677{
680 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
681
682 if (pass != 0) 678 if (pass != 0)
683 return; 679 return;
684 680
685 sdp->sd_found_revokes = 0; 681 jd->jd_found_revokes = 0;
686 sdp->sd_replay_tail = head->lh_tail; 682 jd->jd_replay_tail = head->lh_tail;
687} 683}
688 684
689static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, 685static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
@@ -715,13 +711,13 @@ static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
715 while (offset + sizeof(u64) <= sdp->sd_sb.sb_bsize) { 711 while (offset + sizeof(u64) <= sdp->sd_sb.sb_bsize) {
716 blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset)); 712 blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset));
717 713
718 error = gfs2_revoke_add(sdp, blkno, start); 714 error = gfs2_revoke_add(jd, blkno, start);
719 if (error < 0) { 715 if (error < 0) {
720 brelse(bh); 716 brelse(bh);
721 return error; 717 return error;
722 } 718 }
723 else if (error) 719 else if (error)
724 sdp->sd_found_revokes++; 720 jd->jd_found_revokes++;
725 721
726 if (!--revokes) 722 if (!--revokes)
727 break; 723 break;
@@ -741,16 +737,16 @@ static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
741 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); 737 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
742 738
743 if (error) { 739 if (error) {
744 gfs2_revoke_clean(sdp); 740 gfs2_revoke_clean(jd);
745 return; 741 return;
746 } 742 }
747 if (pass != 1) 743 if (pass != 1)
748 return; 744 return;
749 745
750 fs_info(sdp, "jid=%u: Found %u revoke tags\n", 746 fs_info(sdp, "jid=%u: Found %u revoke tags\n",
751 jd->jd_jid, sdp->sd_found_revokes); 747 jd->jd_jid, jd->jd_found_revokes);
752 748
753 gfs2_revoke_clean(sdp); 749 gfs2_revoke_clean(jd);
754} 750}
755 751
756/** 752/**
@@ -789,9 +785,9 @@ static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
789 blkno = be64_to_cpu(*ptr++); 785 blkno = be64_to_cpu(*ptr++);
790 esc = be64_to_cpu(*ptr++); 786 esc = be64_to_cpu(*ptr++);
791 787
792 sdp->sd_found_blocks++; 788 jd->jd_found_blocks++;
793 789
794 if (gfs2_revoke_check(sdp, blkno, start)) 790 if (gfs2_revoke_check(jd, blkno, start))
795 continue; 791 continue;
796 792
797 error = gfs2_replay_read_block(jd, start, &bh_log); 793 error = gfs2_replay_read_block(jd, start, &bh_log);
@@ -811,7 +807,7 @@ static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
811 brelse(bh_log); 807 brelse(bh_log);
812 brelse(bh_ip); 808 brelse(bh_ip);
813 809
814 sdp->sd_replayed_blocks++; 810 jd->jd_replayed_blocks++;
815 } 811 }
816 812
817 return error; 813 return error;
@@ -835,7 +831,7 @@ static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
835 gfs2_meta_sync(ip->i_gl); 831 gfs2_meta_sync(ip->i_gl);
836 832
837 fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n", 833 fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n",
838 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks); 834 jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks);
839} 835}
840 836
841static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 837static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index c3ef8443b540..ea9c35cae757 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -128,8 +128,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
128 atomic_set(&sdp->sd_log_in_flight, 0); 128 atomic_set(&sdp->sd_log_in_flight, 0);
129 init_waitqueue_head(&sdp->sd_log_flush_wait); 129 init_waitqueue_head(&sdp->sd_log_flush_wait);
130 130
131 INIT_LIST_HEAD(&sdp->sd_revoke_list);
132
133 return sdp; 131 return sdp;
134} 132}
135 133
@@ -575,6 +573,8 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
575 break; 573 break;
576 574
577 INIT_LIST_HEAD(&jd->extent_list); 575 INIT_LIST_HEAD(&jd->extent_list);
576 INIT_LIST_HEAD(&jd->jd_revoke_list);
577
578 INIT_WORK(&jd->jd_work, gfs2_recover_func); 578 INIT_WORK(&jd->jd_work, gfs2_recover_func);
579 jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1); 579 jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1);
580 if (!jd->jd_inode || IS_ERR(jd->jd_inode)) { 580 if (!jd->jd_inode || IS_ERR(jd->jd_inode)) {
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 963b2d75200c..7ad4094d68c0 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -52,9 +52,9 @@ int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
52 return error; 52 return error;
53} 53}
54 54
55int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where) 55int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where)
56{ 56{
57 struct list_head *head = &sdp->sd_revoke_list; 57 struct list_head *head = &jd->jd_revoke_list;
58 struct gfs2_revoke_replay *rr; 58 struct gfs2_revoke_replay *rr;
59 int found = 0; 59 int found = 0;
60 60
@@ -81,13 +81,13 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)
81 return 1; 81 return 1;
82} 82}
83 83
84int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where) 84int gfs2_revoke_check(struct gfs2_jdesc *jd, u64 blkno, unsigned int where)
85{ 85{
86 struct gfs2_revoke_replay *rr; 86 struct gfs2_revoke_replay *rr;
87 int wrap, a, b, revoke; 87 int wrap, a, b, revoke;
88 int found = 0; 88 int found = 0;
89 89
90 list_for_each_entry(rr, &sdp->sd_revoke_list, rr_list) { 90 list_for_each_entry(rr, &jd->jd_revoke_list, rr_list) {
91 if (rr->rr_blkno == blkno) { 91 if (rr->rr_blkno == blkno) {
92 found = 1; 92 found = 1;
93 break; 93 break;
@@ -97,17 +97,17 @@ int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)
97 if (!found) 97 if (!found)
98 return 0; 98 return 0;
99 99
100 wrap = (rr->rr_where < sdp->sd_replay_tail); 100 wrap = (rr->rr_where < jd->jd_replay_tail);
101 a = (sdp->sd_replay_tail < where); 101 a = (jd->jd_replay_tail < where);
102 b = (where < rr->rr_where); 102 b = (where < rr->rr_where);
103 revoke = (wrap) ? (a || b) : (a && b); 103 revoke = (wrap) ? (a || b) : (a && b);
104 104
105 return revoke; 105 return revoke;
106} 106}
107 107
108void gfs2_revoke_clean(struct gfs2_sbd *sdp) 108void gfs2_revoke_clean(struct gfs2_jdesc *jd)
109{ 109{
110 struct list_head *head = &sdp->sd_revoke_list; 110 struct list_head *head = &jd->jd_revoke_list;
111 struct gfs2_revoke_replay *rr; 111 struct gfs2_revoke_replay *rr;
112 112
113 while (!list_empty(head)) { 113 while (!list_empty(head)) {
diff --git a/fs/gfs2/recovery.h b/fs/gfs2/recovery.h
index 2226136c7647..6142836cce96 100644
--- a/fs/gfs2/recovery.h
+++ b/fs/gfs2/recovery.h
@@ -23,9 +23,9 @@ static inline void gfs2_replay_incr_blk(struct gfs2_sbd *sdp, unsigned int *blk)
23extern int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk, 23extern int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
24 struct buffer_head **bh); 24 struct buffer_head **bh);
25 25
26extern int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where); 26extern int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
27extern int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where); 27extern int gfs2_revoke_check(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
28extern void gfs2_revoke_clean(struct gfs2_sbd *sdp); 28extern void gfs2_revoke_clean(struct gfs2_jdesc *jd);
29 29
30extern int gfs2_find_jhead(struct gfs2_jdesc *jd, 30extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
31 struct gfs2_log_header_host *head); 31 struct gfs2_log_header_host *head);