aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2011-04-26 05:23:56 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-05-03 06:48:07 -0400
commit4f1de018215fb56940ce5793e11becd1e8cd6e44 (patch)
tree4f90d7ef5e219615eab7c45e421fa45cb2729b1e
parent6905d9e4dda6112f007e9090bca80507da158e63 (diff)
GFS2: Fix ail list traversal
In the recent patches to update the AIL list code, I managed to forget that the ail list lock got dropped, even though I added a comment specifically to remind myself :( Reported-by: Barry Marson <bmarson@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/log.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index ad1f1887633f..cec26c00b50d 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -89,9 +89,9 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
89 * 89 *
90 */ 90 */
91 91
92static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, 92static int gfs2_ail1_start_one(struct gfs2_sbd *sdp,
93 struct writeback_control *wbc, 93 struct writeback_control *wbc,
94 struct gfs2_ail *ai) 94 struct gfs2_ail *ai)
95__releases(&sdp->sd_ail_lock) 95__releases(&sdp->sd_ail_lock)
96__acquires(&sdp->sd_ail_lock) 96__acquires(&sdp->sd_ail_lock)
97{ 97{
@@ -100,7 +100,6 @@ __acquires(&sdp->sd_ail_lock)
100 struct gfs2_bufdata *bd, *s; 100 struct gfs2_bufdata *bd, *s;
101 struct buffer_head *bh; 101 struct buffer_head *bh;
102 102
103restart:
104 list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, bd_ail_st_list) { 103 list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, bd_ail_st_list) {
105 bh = bd->bd_bh; 104 bh = bd->bd_bh;
106 105
@@ -120,13 +119,17 @@ restart:
120 gl = bd->bd_gl; 119 gl = bd->bd_gl;
121 list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list); 120 list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list);
122 mapping = bh->b_page->mapping; 121 mapping = bh->b_page->mapping;
122 if (!mapping)
123 continue;
123 spin_unlock(&sdp->sd_ail_lock); 124 spin_unlock(&sdp->sd_ail_lock);
124 generic_writepages(mapping, wbc); 125 generic_writepages(mapping, wbc);
125 spin_lock(&sdp->sd_ail_lock); 126 spin_lock(&sdp->sd_ail_lock);
126 if (wbc->nr_to_write <= 0) 127 if (wbc->nr_to_write <= 0)
127 break; 128 break;
128 goto restart; 129 return 1;
129 } 130 }
131
132 return 0;
130} 133}
131 134
132 135
@@ -146,10 +149,12 @@ void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
146 149
147 trace_gfs2_ail_flush(sdp, wbc, 1); 150 trace_gfs2_ail_flush(sdp, wbc, 1);
148 spin_lock(&sdp->sd_ail_lock); 151 spin_lock(&sdp->sd_ail_lock);
152restart:
149 list_for_each_entry_reverse(ai, head, ai_list) { 153 list_for_each_entry_reverse(ai, head, ai_list) {
150 if (wbc->nr_to_write <= 0) 154 if (wbc->nr_to_write <= 0)
151 break; 155 break;
152 gfs2_ail1_start_one(sdp, wbc, ai); /* This may drop ail lock */ 156 if (gfs2_ail1_start_one(sdp, wbc, ai))
157 goto restart;
153 } 158 }
154 spin_unlock(&sdp->sd_ail_lock); 159 spin_unlock(&sdp->sd_ail_lock);
155 trace_gfs2_ail_flush(sdp, wbc, 0); 160 trace_gfs2_ail_flush(sdp, wbc, 0);