diff options
Diffstat (limited to 'fs/gfs2/glops.c')
-rw-r--r-- | fs/gfs2/glops.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 5f2e5224c51c..e2e0a90396e7 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -47,7 +47,8 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh) | |||
47 | * None of the buffers should be dirty, locked, or pinned. | 47 | * None of the buffers should be dirty, locked, or pinned. |
48 | */ | 48 | */ |
49 | 49 | ||
50 | static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) | 50 | static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync, |
51 | unsigned int nr_revokes) | ||
51 | { | 52 | { |
52 | struct gfs2_sbd *sdp = gl->gl_sbd; | 53 | struct gfs2_sbd *sdp = gl->gl_sbd; |
53 | struct list_head *head = &gl->gl_ail_list; | 54 | struct list_head *head = &gl->gl_ail_list; |
@@ -57,7 +58,9 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) | |||
57 | 58 | ||
58 | gfs2_log_lock(sdp); | 59 | gfs2_log_lock(sdp); |
59 | spin_lock(&sdp->sd_ail_lock); | 60 | spin_lock(&sdp->sd_ail_lock); |
60 | list_for_each_entry_safe(bd, tmp, head, bd_ail_gl_list) { | 61 | list_for_each_entry_safe_reverse(bd, tmp, head, bd_ail_gl_list) { |
62 | if (nr_revokes == 0) | ||
63 | break; | ||
61 | bh = bd->bd_bh; | 64 | bh = bd->bd_bh; |
62 | if (bh->b_state & b_state) { | 65 | if (bh->b_state & b_state) { |
63 | if (fsync) | 66 | if (fsync) |
@@ -65,6 +68,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) | |||
65 | gfs2_ail_error(gl, bh); | 68 | gfs2_ail_error(gl, bh); |
66 | } | 69 | } |
67 | gfs2_trans_add_revoke(sdp, bd); | 70 | gfs2_trans_add_revoke(sdp, bd); |
71 | nr_revokes--; | ||
68 | } | 72 | } |
69 | GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count)); | 73 | GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count)); |
70 | spin_unlock(&sdp->sd_ail_lock); | 74 | spin_unlock(&sdp->sd_ail_lock); |
@@ -91,7 +95,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | |||
91 | WARN_ON_ONCE(current->journal_info); | 95 | WARN_ON_ONCE(current->journal_info); |
92 | current->journal_info = &tr; | 96 | current->journal_info = &tr; |
93 | 97 | ||
94 | __gfs2_ail_flush(gl, 0); | 98 | __gfs2_ail_flush(gl, 0, tr.tr_revokes); |
95 | 99 | ||
96 | gfs2_trans_end(sdp); | 100 | gfs2_trans_end(sdp); |
97 | gfs2_log_flush(sdp, NULL); | 101 | gfs2_log_flush(sdp, NULL); |
@@ -101,15 +105,19 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) | |||
101 | { | 105 | { |
102 | struct gfs2_sbd *sdp = gl->gl_sbd; | 106 | struct gfs2_sbd *sdp = gl->gl_sbd; |
103 | unsigned int revokes = atomic_read(&gl->gl_ail_count); | 107 | unsigned int revokes = atomic_read(&gl->gl_ail_count); |
108 | unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64); | ||
104 | int ret; | 109 | int ret; |
105 | 110 | ||
106 | if (!revokes) | 111 | if (!revokes) |
107 | return; | 112 | return; |
108 | 113 | ||
109 | ret = gfs2_trans_begin(sdp, 0, revokes); | 114 | while (revokes > max_revokes) |
115 | max_revokes += (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)) / sizeof(u64); | ||
116 | |||
117 | ret = gfs2_trans_begin(sdp, 0, max_revokes); | ||
110 | if (ret) | 118 | if (ret) |
111 | return; | 119 | return; |
112 | __gfs2_ail_flush(gl, fsync); | 120 | __gfs2_ail_flush(gl, fsync, max_revokes); |
113 | gfs2_trans_end(sdp); | 121 | gfs2_trans_end(sdp); |
114 | gfs2_log_flush(sdp, NULL); | 122 | gfs2_log_flush(sdp, NULL); |
115 | } | 123 | } |