aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2011-05-21 14:21:07 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-05-21 14:21:07 -0400
commit26b06a6958df0f12f1a654db8598433eb89cc024 (patch)
tree4f65fc66e5bef81d7ef16f620686a048c49c7196 /fs/gfs2
parent6d3117b41295150d4ac70622055dd8f5529d86b2 (diff)
GFS2: Wait properly when flushing the ail list
The ail flush code has always relied upon log flushing to prevent it from spinning needlessly. This fixes it to wait on the last I/O request submitted (we don't need to wait for all of it) instead of either spinning with io_schedule or sleeping. As a result cpu usage of gfs2_logd is much reduced with certain workloads. Reported-by: Abhijith Das <adas@redhat.com> Tested-by: Abhijith Das <adas@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/log.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index cec26c00b50d..903115f2bb34 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -228,6 +228,27 @@ static int gfs2_ail1_empty(struct gfs2_sbd *sdp)
228 return ret; 228 return ret;
229} 229}
230 230
231static void gfs2_ail1_wait(struct gfs2_sbd *sdp)
232{
233 struct gfs2_ail *ai;
234 struct gfs2_bufdata *bd;
235 struct buffer_head *bh;
236
237 spin_lock(&sdp->sd_ail_lock);
238 list_for_each_entry_reverse(ai, &sdp->sd_ail1_list, ai_list) {
239 list_for_each_entry(bd, &ai->ai_ail1_list, bd_ail_st_list) {
240 bh = bd->bd_bh;
241 if (!buffer_locked(bh))
242 continue;
243 get_bh(bh);
244 spin_unlock(&sdp->sd_ail_lock);
245 wait_on_buffer(bh);
246 brelse(bh);
247 return;
248 }
249 }
250 spin_unlock(&sdp->sd_ail_lock);
251}
231 252
232/** 253/**
233 * gfs2_ail2_empty_one - Check whether or not a trans in the AIL has been synced 254 * gfs2_ail2_empty_one - Check whether or not a trans in the AIL has been synced
@@ -878,9 +899,9 @@ void gfs2_meta_syncfs(struct gfs2_sbd *sdp)
878 gfs2_log_flush(sdp, NULL); 899 gfs2_log_flush(sdp, NULL);
879 for (;;) { 900 for (;;) {
880 gfs2_ail1_start(sdp); 901 gfs2_ail1_start(sdp);
902 gfs2_ail1_wait(sdp);
881 if (gfs2_ail1_empty(sdp)) 903 if (gfs2_ail1_empty(sdp))
882 break; 904 break;
883 msleep(10);
884 } 905 }
885} 906}
886 907
@@ -920,12 +941,14 @@ int gfs2_logd(void *data)
920 941
921 if (gfs2_ail_flush_reqd(sdp)) { 942 if (gfs2_ail_flush_reqd(sdp)) {
922 gfs2_ail1_start(sdp); 943 gfs2_ail1_start(sdp);
923 io_schedule(); 944 gfs2_ail1_wait(sdp);
924 gfs2_ail1_empty(sdp); 945 gfs2_ail1_empty(sdp);
925 gfs2_log_flush(sdp, NULL); 946 gfs2_log_flush(sdp, NULL);
926 } 947 }
927 948
928 wake_up(&sdp->sd_log_waitq); 949 if (!gfs2_ail_flush_reqd(sdp))
950 wake_up(&sdp->sd_log_waitq);
951
929 t = gfs2_tune_get(sdp, gt_logd_secs) * HZ; 952 t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
930 if (freezing(current)) 953 if (freezing(current))
931 refrigerator(); 954 refrigerator();