aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r--fs/gfs2/log.c165
1 files changed, 85 insertions, 80 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 3ebafa1efad0..03e00417061b 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -18,6 +18,7 @@
18#include <linux/kthread.h> 18#include <linux/kthread.h>
19#include <linux/freezer.h> 19#include <linux/freezer.h>
20#include <linux/bio.h> 20#include <linux/bio.h>
21#include <linux/writeback.h>
21 22
22#include "gfs2.h" 23#include "gfs2.h"
23#include "incore.h" 24#include "incore.h"
@@ -83,50 +84,90 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
83/** 84/**
84 * gfs2_ail1_start_one - Start I/O on a part of the AIL 85 * gfs2_ail1_start_one - Start I/O on a part of the AIL
85 * @sdp: the filesystem 86 * @sdp: the filesystem
86 * @tr: the part of the AIL 87 * @wbc: The writeback control structure
88 * @ai: The ail structure
87 * 89 *
88 */ 90 */
89 91
90static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) 92static void gfs2_ail1_start_one(struct gfs2_sbd *sdp,
93 struct writeback_control *wbc,
94 struct gfs2_ail *ai)
91__releases(&sdp->sd_ail_lock) 95__releases(&sdp->sd_ail_lock)
92__acquires(&sdp->sd_ail_lock) 96__acquires(&sdp->sd_ail_lock)
93{ 97{
94 struct gfs2_glock *gl = NULL; 98 struct gfs2_glock *gl = NULL;
99 struct address_space *mapping;
95 struct gfs2_bufdata *bd, *s; 100 struct gfs2_bufdata *bd, *s;
96 struct buffer_head *bh; 101 struct buffer_head *bh;
97 int retry;
98 102
99 do { 103restart:
100 retry = 0; 104 list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, bd_ail_st_list) {
105 bh = bd->bd_bh;
101 106
102 list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, 107 gfs2_assert(sdp, bd->bd_ail == ai);
103 bd_ail_st_list) {
104 bh = bd->bd_bh;
105 108
106 gfs2_assert(sdp, bd->bd_ail == ai); 109 if (!buffer_busy(bh)) {
110 if (!buffer_uptodate(bh))
111 gfs2_io_error_bh(sdp, bh);
112 list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
113 continue;
114 }
115
116 if (!buffer_dirty(bh))
117 continue;
118 if (gl == bd->bd_gl)
119 continue;
120 gl = bd->bd_gl;
121 list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list);
122 mapping = bh->b_page->mapping;
123 spin_unlock(&sdp->sd_ail_lock);
124 generic_writepages(mapping, wbc);
125 spin_lock(&sdp->sd_ail_lock);
126 if (wbc->nr_to_write <= 0)
127 break;
128 goto restart;
129 }
130}
107 131
108 if (!buffer_busy(bh)) {
109 if (!buffer_uptodate(bh))
110 gfs2_io_error_bh(sdp, bh);
111 list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
112 continue;
113 }
114 132
115 if (!buffer_dirty(bh)) 133/**
116 continue; 134 * gfs2_ail1_flush - start writeback of some ail1 entries
117 if (gl == bd->bd_gl) 135 * @sdp: The super block
118 continue; 136 * @wbc: The writeback control structure
119 gl = bd->bd_gl; 137 *
120 list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list); 138 * Writes back some ail1 entries, according to the limits in the
139 * writeback control structure
140 */
121 141
122 spin_unlock(&sdp->sd_ail_lock); 142void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
123 filemap_fdatawrite(gfs2_glock2aspace(gl)); 143{
124 spin_lock(&sdp->sd_ail_lock); 144 struct list_head *head = &sdp->sd_ail1_list;
145 struct gfs2_ail *ai;
125 146
126 retry = 1; 147 spin_lock(&sdp->sd_ail_lock);
148 list_for_each_entry_reverse(ai, head, ai_list) {
149 if (wbc->nr_to_write <= 0)
127 break; 150 break;
128 } 151 gfs2_ail1_start_one(sdp, wbc, ai); /* This may drop ail lock */
129 } while (retry); 152 }
153 spin_unlock(&sdp->sd_ail_lock);
154}
155
156/**
157 * gfs2_ail1_start - start writeback of all ail1 entries
158 * @sdp: The superblock
159 */
160
161static void gfs2_ail1_start(struct gfs2_sbd *sdp)
162{
163 struct writeback_control wbc = {
164 .sync_mode = WB_SYNC_NONE,
165 .nr_to_write = LONG_MAX,
166 .range_start = 0,
167 .range_end = LLONG_MAX,
168 };
169
170 return gfs2_ail1_flush(sdp, &wbc);
130} 171}
131 172
132/** 173/**
@@ -136,7 +177,7 @@ __acquires(&sdp->sd_ail_lock)
136 * 177 *
137 */ 178 */
138 179
139static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int flags) 180static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
140{ 181{
141 struct gfs2_bufdata *bd, *s; 182 struct gfs2_bufdata *bd, *s;
142 struct buffer_head *bh; 183 struct buffer_head *bh;
@@ -144,71 +185,37 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl
144 list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, 185 list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list,
145 bd_ail_st_list) { 186 bd_ail_st_list) {
146 bh = bd->bd_bh; 187 bh = bd->bd_bh;
147
148 gfs2_assert(sdp, bd->bd_ail == ai); 188 gfs2_assert(sdp, bd->bd_ail == ai);
149 189 if (buffer_busy(bh))
150 if (buffer_busy(bh)) { 190 continue;
151 if (flags & DIO_ALL)
152 continue;
153 else
154 break;
155 }
156
157 if (!buffer_uptodate(bh)) 191 if (!buffer_uptodate(bh))
158 gfs2_io_error_bh(sdp, bh); 192 gfs2_io_error_bh(sdp, bh);
159
160 list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); 193 list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
161 } 194 }
162 195
163 return list_empty(&ai->ai_ail1_list);
164} 196}
165 197
166static void gfs2_ail1_start(struct gfs2_sbd *sdp) 198/**
167{ 199 * gfs2_ail1_empty - Try to empty the ail1 lists
168 struct list_head *head; 200 * @sdp: The superblock
169 u64 sync_gen; 201 *
170 struct gfs2_ail *ai; 202 * Tries to empty the ail1 lists, starting with the oldest first
171 int done = 0; 203 */
172
173 spin_lock(&sdp->sd_ail_lock);
174 head = &sdp->sd_ail1_list;
175 if (list_empty(head)) {
176 spin_unlock(&sdp->sd_ail_lock);
177 return;
178 }
179 sync_gen = sdp->sd_ail_sync_gen++;
180
181 while(!done) {
182 done = 1;
183 list_for_each_entry_reverse(ai, head, ai_list) {
184 if (ai->ai_sync_gen >= sync_gen)
185 continue;
186 ai->ai_sync_gen = sync_gen;
187 gfs2_ail1_start_one(sdp, ai); /* This may drop ail lock */
188 done = 0;
189 break;
190 }
191 }
192
193 spin_unlock(&sdp->sd_ail_lock);
194}
195 204
196static int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags) 205static int gfs2_ail1_empty(struct gfs2_sbd *sdp)
197{ 206{
198 struct gfs2_ail *ai, *s; 207 struct gfs2_ail *ai, *s;
199 int ret; 208 int ret;
200 209
201 spin_lock(&sdp->sd_ail_lock); 210 spin_lock(&sdp->sd_ail_lock);
202
203 list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) { 211 list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) {
204 if (gfs2_ail1_empty_one(sdp, ai, flags)) 212 gfs2_ail1_empty_one(sdp, ai);
213 if (list_empty(&ai->ai_ail1_list))
205 list_move(&ai->ai_list, &sdp->sd_ail2_list); 214 list_move(&ai->ai_list, &sdp->sd_ail2_list);
206 else if (!(flags & DIO_ALL)) 215 else
207 break; 216 break;
208 } 217 }
209
210 ret = list_empty(&sdp->sd_ail1_list); 218 ret = list_empty(&sdp->sd_ail1_list);
211
212 spin_unlock(&sdp->sd_ail_lock); 219 spin_unlock(&sdp->sd_ail_lock);
213 220
214 return ret; 221 return ret;
@@ -569,7 +576,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
569 set_buffer_uptodate(bh); 576 set_buffer_uptodate(bh);
570 clear_buffer_dirty(bh); 577 clear_buffer_dirty(bh);
571 578
572 gfs2_ail1_empty(sdp, 0); 579 gfs2_ail1_empty(sdp);
573 tail = current_tail(sdp); 580 tail = current_tail(sdp);
574 581
575 lh = (struct gfs2_log_header *)bh->b_data; 582 lh = (struct gfs2_log_header *)bh->b_data;
@@ -864,7 +871,7 @@ void gfs2_meta_syncfs(struct gfs2_sbd *sdp)
864 gfs2_log_flush(sdp, NULL); 871 gfs2_log_flush(sdp, NULL);
865 for (;;) { 872 for (;;) {
866 gfs2_ail1_start(sdp); 873 gfs2_ail1_start(sdp);
867 if (gfs2_ail1_empty(sdp, DIO_ALL)) 874 if (gfs2_ail1_empty(sdp))
868 break; 875 break;
869 msleep(10); 876 msleep(10);
870 } 877 }
@@ -900,17 +907,15 @@ int gfs2_logd(void *data)
900 907
901 preflush = atomic_read(&sdp->sd_log_pinned); 908 preflush = atomic_read(&sdp->sd_log_pinned);
902 if (gfs2_jrnl_flush_reqd(sdp) || t == 0) { 909 if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
903 gfs2_ail1_empty(sdp, DIO_ALL); 910 gfs2_ail1_empty(sdp);
904 gfs2_log_flush(sdp, NULL); 911 gfs2_log_flush(sdp, NULL);
905 gfs2_ail1_empty(sdp, DIO_ALL);
906 } 912 }
907 913
908 if (gfs2_ail_flush_reqd(sdp)) { 914 if (gfs2_ail_flush_reqd(sdp)) {
909 gfs2_ail1_start(sdp); 915 gfs2_ail1_start(sdp);
910 io_schedule(); 916 io_schedule();
911 gfs2_ail1_empty(sdp, 0); 917 gfs2_ail1_empty(sdp);
912 gfs2_log_flush(sdp, NULL); 918 gfs2_log_flush(sdp, NULL);
913 gfs2_ail1_empty(sdp, DIO_ALL);
914 } 919 }
915 920
916 wake_up(&sdp->sd_log_waitq); 921 wake_up(&sdp->sd_log_waitq);