diff options
Diffstat (limited to 'fs')
| -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 | } |
