diff options
-rw-r--r-- | fs/gfs2/aops.c | 2 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 17 | ||||
-rw-r--r-- | fs/gfs2/log.c | 104 | ||||
-rw-r--r-- | fs/gfs2/lops.c | 32 | ||||
-rw-r--r-- | fs/gfs2/lops.h | 5 | ||||
-rw-r--r-- | fs/gfs2/meta_io.c | 2 | ||||
-rw-r--r-- | fs/gfs2/trans.c | 4 |
7 files changed, 94 insertions, 72 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 24f414f0ce61..9883694f1e7c 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -1055,7 +1055,7 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
1055 | if (atomic_read(&bh->b_count)) | 1055 | if (atomic_read(&bh->b_count)) |
1056 | goto cannot_release; | 1056 | goto cannot_release; |
1057 | bd = bh->b_private; | 1057 | bd = bh->b_private; |
1058 | if (bd && bd->bd_ail) | 1058 | if (bd && bd->bd_tr) |
1059 | goto cannot_release; | 1059 | goto cannot_release; |
1060 | if (buffer_pinned(bh) || buffer_dirty(bh)) | 1060 | if (buffer_pinned(bh) || buffer_dirty(bh)) |
1061 | goto not_possible; | 1061 | goto not_possible; |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 5c29216e9cc1..2532f7ec6b00 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -31,7 +31,6 @@ struct gfs2_holder; | |||
31 | struct gfs2_glock; | 31 | struct gfs2_glock; |
32 | struct gfs2_quota_data; | 32 | struct gfs2_quota_data; |
33 | struct gfs2_trans; | 33 | struct gfs2_trans; |
34 | struct gfs2_ail; | ||
35 | struct gfs2_jdesc; | 34 | struct gfs2_jdesc; |
36 | struct gfs2_sbd; | 35 | struct gfs2_sbd; |
37 | struct lm_lockops; | 36 | struct lm_lockops; |
@@ -53,7 +52,7 @@ struct gfs2_log_header_host { | |||
53 | 52 | ||
54 | struct gfs2_log_operations { | 53 | struct gfs2_log_operations { |
55 | void (*lo_before_commit) (struct gfs2_sbd *sdp); | 54 | void (*lo_before_commit) (struct gfs2_sbd *sdp); |
56 | void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai); | 55 | void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr); |
57 | void (*lo_before_scan) (struct gfs2_jdesc *jd, | 56 | void (*lo_before_scan) (struct gfs2_jdesc *jd, |
58 | struct gfs2_log_header_host *head, int pass); | 57 | struct gfs2_log_header_host *head, int pass); |
59 | int (*lo_scan_elements) (struct gfs2_jdesc *jd, unsigned int start, | 58 | int (*lo_scan_elements) (struct gfs2_jdesc *jd, unsigned int start, |
@@ -139,7 +138,7 @@ struct gfs2_bufdata { | |||
139 | struct list_head bd_list; | 138 | struct list_head bd_list; |
140 | const struct gfs2_log_operations *bd_ops; | 139 | const struct gfs2_log_operations *bd_ops; |
141 | 140 | ||
142 | struct gfs2_ail *bd_ail; | 141 | struct gfs2_trans *bd_tr; |
143 | struct list_head bd_ail_st_list; | 142 | struct list_head bd_ail_st_list; |
144 | struct list_head bd_ail_gl_list; | 143 | struct list_head bd_ail_gl_list; |
145 | }; | 144 | }; |
@@ -433,6 +432,7 @@ struct gfs2_trans { | |||
433 | struct gfs2_holder tr_t_gh; | 432 | struct gfs2_holder tr_t_gh; |
434 | 433 | ||
435 | int tr_touched; | 434 | int tr_touched; |
435 | int tr_attached; | ||
436 | 436 | ||
437 | unsigned int tr_num_buf_new; | 437 | unsigned int tr_num_buf_new; |
438 | unsigned int tr_num_databuf_new; | 438 | unsigned int tr_num_databuf_new; |
@@ -440,14 +440,12 @@ struct gfs2_trans { | |||
440 | unsigned int tr_num_databuf_rm; | 440 | unsigned int tr_num_databuf_rm; |
441 | unsigned int tr_num_revoke; | 441 | unsigned int tr_num_revoke; |
442 | unsigned int tr_num_revoke_rm; | 442 | unsigned int tr_num_revoke_rm; |
443 | }; | ||
444 | 443 | ||
445 | struct gfs2_ail { | 444 | struct list_head tr_list; |
446 | struct list_head ai_list; | ||
447 | 445 | ||
448 | unsigned int ai_first; | 446 | unsigned int tr_first; |
449 | struct list_head ai_ail1_list; | 447 | struct list_head tr_ail1_list; |
450 | struct list_head ai_ail2_list; | 448 | struct list_head tr_ail2_list; |
451 | }; | 449 | }; |
452 | 450 | ||
453 | struct gfs2_journal_extent { | 451 | struct gfs2_journal_extent { |
@@ -710,6 +708,7 @@ struct gfs2_sbd { | |||
710 | 708 | ||
711 | spinlock_t sd_log_lock; | 709 | spinlock_t sd_log_lock; |
712 | 710 | ||
711 | struct gfs2_trans *sd_log_tr; | ||
713 | unsigned int sd_log_blks_reserved; | 712 | unsigned int sd_log_blks_reserved; |
714 | unsigned int sd_log_commited_buf; | 713 | unsigned int sd_log_commited_buf; |
715 | unsigned int sd_log_commited_databuf; | 714 | unsigned int sd_log_commited_databuf; |
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 9a2ca8be7647..b404f4853034 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -73,7 +73,7 @@ unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, | |||
73 | 73 | ||
74 | void gfs2_remove_from_ail(struct gfs2_bufdata *bd) | 74 | void gfs2_remove_from_ail(struct gfs2_bufdata *bd) |
75 | { | 75 | { |
76 | bd->bd_ail = NULL; | 76 | bd->bd_tr = NULL; |
77 | list_del_init(&bd->bd_ail_st_list); | 77 | list_del_init(&bd->bd_ail_st_list); |
78 | list_del_init(&bd->bd_ail_gl_list); | 78 | list_del_init(&bd->bd_ail_gl_list); |
79 | atomic_dec(&bd->bd_gl->gl_ail_count); | 79 | atomic_dec(&bd->bd_gl->gl_ail_count); |
@@ -90,7 +90,7 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd) | |||
90 | 90 | ||
91 | static int gfs2_ail1_start_one(struct gfs2_sbd *sdp, | 91 | static int gfs2_ail1_start_one(struct gfs2_sbd *sdp, |
92 | struct writeback_control *wbc, | 92 | struct writeback_control *wbc, |
93 | struct gfs2_ail *ai) | 93 | struct gfs2_trans *tr) |
94 | __releases(&sdp->sd_ail_lock) | 94 | __releases(&sdp->sd_ail_lock) |
95 | __acquires(&sdp->sd_ail_lock) | 95 | __acquires(&sdp->sd_ail_lock) |
96 | { | 96 | { |
@@ -99,15 +99,15 @@ __acquires(&sdp->sd_ail_lock) | |||
99 | struct gfs2_bufdata *bd, *s; | 99 | struct gfs2_bufdata *bd, *s; |
100 | struct buffer_head *bh; | 100 | struct buffer_head *bh; |
101 | 101 | ||
102 | list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, bd_ail_st_list) { | 102 | list_for_each_entry_safe_reverse(bd, s, &tr->tr_ail1_list, bd_ail_st_list) { |
103 | bh = bd->bd_bh; | 103 | bh = bd->bd_bh; |
104 | 104 | ||
105 | gfs2_assert(sdp, bd->bd_ail == ai); | 105 | gfs2_assert(sdp, bd->bd_tr == tr); |
106 | 106 | ||
107 | if (!buffer_busy(bh)) { | 107 | if (!buffer_busy(bh)) { |
108 | if (!buffer_uptodate(bh)) | 108 | if (!buffer_uptodate(bh)) |
109 | gfs2_io_error_bh(sdp, bh); | 109 | gfs2_io_error_bh(sdp, bh); |
110 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | 110 | list_move(&bd->bd_ail_st_list, &tr->tr_ail2_list); |
111 | continue; | 111 | continue; |
112 | } | 112 | } |
113 | 113 | ||
@@ -116,7 +116,7 @@ __acquires(&sdp->sd_ail_lock) | |||
116 | if (gl == bd->bd_gl) | 116 | if (gl == bd->bd_gl) |
117 | continue; | 117 | continue; |
118 | gl = bd->bd_gl; | 118 | gl = bd->bd_gl; |
119 | list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list); | 119 | list_move(&bd->bd_ail_st_list, &tr->tr_ail1_list); |
120 | mapping = bh->b_page->mapping; | 120 | mapping = bh->b_page->mapping; |
121 | if (!mapping) | 121 | if (!mapping) |
122 | continue; | 122 | continue; |
@@ -144,15 +144,15 @@ __acquires(&sdp->sd_ail_lock) | |||
144 | void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc) | 144 | void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc) |
145 | { | 145 | { |
146 | struct list_head *head = &sdp->sd_ail1_list; | 146 | struct list_head *head = &sdp->sd_ail1_list; |
147 | struct gfs2_ail *ai; | 147 | struct gfs2_trans *tr; |
148 | 148 | ||
149 | trace_gfs2_ail_flush(sdp, wbc, 1); | 149 | trace_gfs2_ail_flush(sdp, wbc, 1); |
150 | spin_lock(&sdp->sd_ail_lock); | 150 | spin_lock(&sdp->sd_ail_lock); |
151 | restart: | 151 | restart: |
152 | list_for_each_entry_reverse(ai, head, ai_list) { | 152 | list_for_each_entry_reverse(tr, head, tr_list) { |
153 | if (wbc->nr_to_write <= 0) | 153 | if (wbc->nr_to_write <= 0) |
154 | break; | 154 | break; |
155 | if (gfs2_ail1_start_one(sdp, wbc, ai)) | 155 | if (gfs2_ail1_start_one(sdp, wbc, tr)) |
156 | goto restart; | 156 | goto restart; |
157 | } | 157 | } |
158 | spin_unlock(&sdp->sd_ail_lock); | 158 | spin_unlock(&sdp->sd_ail_lock); |
@@ -183,20 +183,20 @@ static void gfs2_ail1_start(struct gfs2_sbd *sdp) | |||
183 | * | 183 | * |
184 | */ | 184 | */ |
185 | 185 | ||
186 | static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | 186 | static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
187 | { | 187 | { |
188 | struct gfs2_bufdata *bd, *s; | 188 | struct gfs2_bufdata *bd, *s; |
189 | struct buffer_head *bh; | 189 | struct buffer_head *bh; |
190 | 190 | ||
191 | list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, | 191 | list_for_each_entry_safe_reverse(bd, s, &tr->tr_ail1_list, |
192 | bd_ail_st_list) { | 192 | bd_ail_st_list) { |
193 | bh = bd->bd_bh; | 193 | bh = bd->bd_bh; |
194 | gfs2_assert(sdp, bd->bd_ail == ai); | 194 | gfs2_assert(sdp, bd->bd_tr == tr); |
195 | if (buffer_busy(bh)) | 195 | if (buffer_busy(bh)) |
196 | continue; | 196 | continue; |
197 | if (!buffer_uptodate(bh)) | 197 | if (!buffer_uptodate(bh)) |
198 | gfs2_io_error_bh(sdp, bh); | 198 | gfs2_io_error_bh(sdp, bh); |
199 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | 199 | list_move(&bd->bd_ail_st_list, &tr->tr_ail2_list); |
200 | } | 200 | } |
201 | 201 | ||
202 | } | 202 | } |
@@ -210,14 +210,14 @@ static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
210 | 210 | ||
211 | static int gfs2_ail1_empty(struct gfs2_sbd *sdp) | 211 | static int gfs2_ail1_empty(struct gfs2_sbd *sdp) |
212 | { | 212 | { |
213 | struct gfs2_ail *ai, *s; | 213 | struct gfs2_trans *tr, *s; |
214 | int ret; | 214 | int ret; |
215 | 215 | ||
216 | spin_lock(&sdp->sd_ail_lock); | 216 | spin_lock(&sdp->sd_ail_lock); |
217 | list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) { | 217 | list_for_each_entry_safe_reverse(tr, s, &sdp->sd_ail1_list, tr_list) { |
218 | gfs2_ail1_empty_one(sdp, ai); | 218 | gfs2_ail1_empty_one(sdp, tr); |
219 | if (list_empty(&ai->ai_ail1_list)) | 219 | if (list_empty(&tr->tr_ail1_list)) |
220 | list_move(&ai->ai_list, &sdp->sd_ail2_list); | 220 | list_move(&tr->tr_list, &sdp->sd_ail2_list); |
221 | else | 221 | else |
222 | break; | 222 | break; |
223 | } | 223 | } |
@@ -229,13 +229,13 @@ static int gfs2_ail1_empty(struct gfs2_sbd *sdp) | |||
229 | 229 | ||
230 | static void gfs2_ail1_wait(struct gfs2_sbd *sdp) | 230 | static void gfs2_ail1_wait(struct gfs2_sbd *sdp) |
231 | { | 231 | { |
232 | struct gfs2_ail *ai; | 232 | struct gfs2_trans *tr; |
233 | struct gfs2_bufdata *bd; | 233 | struct gfs2_bufdata *bd; |
234 | struct buffer_head *bh; | 234 | struct buffer_head *bh; |
235 | 235 | ||
236 | spin_lock(&sdp->sd_ail_lock); | 236 | spin_lock(&sdp->sd_ail_lock); |
237 | list_for_each_entry_reverse(ai, &sdp->sd_ail1_list, ai_list) { | 237 | list_for_each_entry_reverse(tr, &sdp->sd_ail1_list, tr_list) { |
238 | list_for_each_entry(bd, &ai->ai_ail1_list, bd_ail_st_list) { | 238 | list_for_each_entry(bd, &tr->tr_ail1_list, bd_ail_st_list) { |
239 | bh = bd->bd_bh; | 239 | bh = bd->bd_bh; |
240 | if (!buffer_locked(bh)) | 240 | if (!buffer_locked(bh)) |
241 | continue; | 241 | continue; |
@@ -256,40 +256,40 @@ static void gfs2_ail1_wait(struct gfs2_sbd *sdp) | |||
256 | * | 256 | * |
257 | */ | 257 | */ |
258 | 258 | ||
259 | static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | 259 | static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
260 | { | 260 | { |
261 | struct list_head *head = &ai->ai_ail2_list; | 261 | struct list_head *head = &tr->tr_ail2_list; |
262 | struct gfs2_bufdata *bd; | 262 | struct gfs2_bufdata *bd; |
263 | 263 | ||
264 | while (!list_empty(head)) { | 264 | while (!list_empty(head)) { |
265 | bd = list_entry(head->prev, struct gfs2_bufdata, | 265 | bd = list_entry(head->prev, struct gfs2_bufdata, |
266 | bd_ail_st_list); | 266 | bd_ail_st_list); |
267 | gfs2_assert(sdp, bd->bd_ail == ai); | 267 | gfs2_assert(sdp, bd->bd_tr == tr); |
268 | gfs2_remove_from_ail(bd); | 268 | gfs2_remove_from_ail(bd); |
269 | } | 269 | } |
270 | } | 270 | } |
271 | 271 | ||
272 | static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) | 272 | static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) |
273 | { | 273 | { |
274 | struct gfs2_ail *ai, *safe; | 274 | struct gfs2_trans *tr, *safe; |
275 | unsigned int old_tail = sdp->sd_log_tail; | 275 | unsigned int old_tail = sdp->sd_log_tail; |
276 | int wrap = (new_tail < old_tail); | 276 | int wrap = (new_tail < old_tail); |
277 | int a, b, rm; | 277 | int a, b, rm; |
278 | 278 | ||
279 | spin_lock(&sdp->sd_ail_lock); | 279 | spin_lock(&sdp->sd_ail_lock); |
280 | 280 | ||
281 | list_for_each_entry_safe(ai, safe, &sdp->sd_ail2_list, ai_list) { | 281 | list_for_each_entry_safe(tr, safe, &sdp->sd_ail2_list, tr_list) { |
282 | a = (old_tail <= ai->ai_first); | 282 | a = (old_tail <= tr->tr_first); |
283 | b = (ai->ai_first < new_tail); | 283 | b = (tr->tr_first < new_tail); |
284 | rm = (wrap) ? (a || b) : (a && b); | 284 | rm = (wrap) ? (a || b) : (a && b); |
285 | if (!rm) | 285 | if (!rm) |
286 | continue; | 286 | continue; |
287 | 287 | ||
288 | gfs2_ail2_empty_one(sdp, ai); | 288 | gfs2_ail2_empty_one(sdp, tr); |
289 | list_del(&ai->ai_list); | 289 | list_del(&tr->tr_list); |
290 | gfs2_assert_warn(sdp, list_empty(&ai->ai_ail1_list)); | 290 | gfs2_assert_warn(sdp, list_empty(&tr->tr_ail1_list)); |
291 | gfs2_assert_warn(sdp, list_empty(&ai->ai_ail2_list)); | 291 | gfs2_assert_warn(sdp, list_empty(&tr->tr_ail2_list)); |
292 | kfree(ai); | 292 | kfree(tr); |
293 | } | 293 | } |
294 | 294 | ||
295 | spin_unlock(&sdp->sd_ail_lock); | 295 | spin_unlock(&sdp->sd_ail_lock); |
@@ -435,7 +435,7 @@ static unsigned int calc_reserved(struct gfs2_sbd *sdp) | |||
435 | 435 | ||
436 | static unsigned int current_tail(struct gfs2_sbd *sdp) | 436 | static unsigned int current_tail(struct gfs2_sbd *sdp) |
437 | { | 437 | { |
438 | struct gfs2_ail *ai; | 438 | struct gfs2_trans *tr; |
439 | unsigned int tail; | 439 | unsigned int tail; |
440 | 440 | ||
441 | spin_lock(&sdp->sd_ail_lock); | 441 | spin_lock(&sdp->sd_ail_lock); |
@@ -443,8 +443,9 @@ static unsigned int current_tail(struct gfs2_sbd *sdp) | |||
443 | if (list_empty(&sdp->sd_ail1_list)) { | 443 | if (list_empty(&sdp->sd_ail1_list)) { |
444 | tail = sdp->sd_log_head; | 444 | tail = sdp->sd_log_head; |
445 | } else { | 445 | } else { |
446 | ai = list_entry(sdp->sd_ail1_list.prev, struct gfs2_ail, ai_list); | 446 | tr = list_entry(sdp->sd_ail1_list.prev, struct gfs2_trans, |
447 | tail = ai->ai_first; | 447 | tr_list); |
448 | tail = tr->tr_first; | ||
448 | } | 449 | } |
449 | 450 | ||
450 | spin_unlock(&sdp->sd_ail_lock); | 451 | spin_unlock(&sdp->sd_ail_lock); |
@@ -600,7 +601,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags) | |||
600 | 601 | ||
601 | void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | 602 | void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) |
602 | { | 603 | { |
603 | struct gfs2_ail *ai; | 604 | struct gfs2_trans *tr; |
604 | 605 | ||
605 | down_write(&sdp->sd_log_flush_lock); | 606 | down_write(&sdp->sd_log_flush_lock); |
606 | 607 | ||
@@ -611,9 +612,12 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
611 | } | 612 | } |
612 | trace_gfs2_log_flush(sdp, 1); | 613 | trace_gfs2_log_flush(sdp, 1); |
613 | 614 | ||
614 | ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL); | 615 | tr = sdp->sd_log_tr; |
615 | INIT_LIST_HEAD(&ai->ai_ail1_list); | 616 | if (tr) { |
616 | INIT_LIST_HEAD(&ai->ai_ail2_list); | 617 | sdp->sd_log_tr = NULL; |
618 | INIT_LIST_HEAD(&tr->tr_ail1_list); | ||
619 | INIT_LIST_HEAD(&tr->tr_ail2_list); | ||
620 | } | ||
617 | 621 | ||
618 | if (sdp->sd_log_num_buf != sdp->sd_log_commited_buf) { | 622 | if (sdp->sd_log_num_buf != sdp->sd_log_commited_buf) { |
619 | printk(KERN_INFO "GFS2: log buf %u %u\n", sdp->sd_log_num_buf, | 623 | printk(KERN_INFO "GFS2: log buf %u %u\n", sdp->sd_log_num_buf, |
@@ -630,7 +634,8 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
630 | 634 | ||
631 | sdp->sd_log_flush_head = sdp->sd_log_head; | 635 | sdp->sd_log_flush_head = sdp->sd_log_head; |
632 | sdp->sd_log_flush_wrapped = 0; | 636 | sdp->sd_log_flush_wrapped = 0; |
633 | ai->ai_first = sdp->sd_log_flush_head; | 637 | if (tr) |
638 | tr->tr_first = sdp->sd_log_flush_head; | ||
634 | 639 | ||
635 | gfs2_ordered_write(sdp); | 640 | gfs2_ordered_write(sdp); |
636 | lops_before_commit(sdp); | 641 | lops_before_commit(sdp); |
@@ -643,7 +648,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
643 | trace_gfs2_log_blocks(sdp, -1); | 648 | trace_gfs2_log_blocks(sdp, -1); |
644 | log_write_header(sdp, 0); | 649 | log_write_header(sdp, 0); |
645 | } | 650 | } |
646 | lops_after_commit(sdp, ai); | 651 | lops_after_commit(sdp, tr); |
647 | 652 | ||
648 | gfs2_log_lock(sdp); | 653 | gfs2_log_lock(sdp); |
649 | sdp->sd_log_head = sdp->sd_log_flush_head; | 654 | sdp->sd_log_head = sdp->sd_log_flush_head; |
@@ -653,16 +658,16 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
653 | sdp->sd_log_commited_revoke = 0; | 658 | sdp->sd_log_commited_revoke = 0; |
654 | 659 | ||
655 | spin_lock(&sdp->sd_ail_lock); | 660 | spin_lock(&sdp->sd_ail_lock); |
656 | if (!list_empty(&ai->ai_ail1_list)) { | 661 | if (tr && !list_empty(&tr->tr_ail1_list)) { |
657 | list_add(&ai->ai_list, &sdp->sd_ail1_list); | 662 | list_add(&tr->tr_list, &sdp->sd_ail1_list); |
658 | ai = NULL; | 663 | tr = NULL; |
659 | } | 664 | } |
660 | spin_unlock(&sdp->sd_ail_lock); | 665 | spin_unlock(&sdp->sd_ail_lock); |
661 | gfs2_log_unlock(sdp); | 666 | gfs2_log_unlock(sdp); |
662 | trace_gfs2_log_flush(sdp, 0); | 667 | trace_gfs2_log_flush(sdp, 0); |
663 | up_write(&sdp->sd_log_flush_lock); | 668 | up_write(&sdp->sd_log_flush_lock); |
664 | 669 | ||
665 | kfree(ai); | 670 | kfree(tr); |
666 | } | 671 | } |
667 | 672 | ||
668 | static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | 673 | static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
@@ -687,6 +692,12 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | |||
687 | sdp->sd_jdesc->jd_blocks); | 692 | sdp->sd_jdesc->jd_blocks); |
688 | sdp->sd_log_blks_reserved = reserved; | 693 | sdp->sd_log_blks_reserved = reserved; |
689 | 694 | ||
695 | if (sdp->sd_log_tr == NULL && | ||
696 | (tr->tr_num_buf_new || tr->tr_num_databuf_new)) { | ||
697 | gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl); | ||
698 | sdp->sd_log_tr = tr; | ||
699 | tr->tr_attached = 1; | ||
700 | } | ||
690 | gfs2_log_unlock(sdp); | 701 | gfs2_log_unlock(sdp); |
691 | } | 702 | } |
692 | 703 | ||
@@ -708,7 +719,6 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | |||
708 | void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | 719 | void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
709 | { | 720 | { |
710 | log_refund(sdp, tr); | 721 | log_refund(sdp, tr); |
711 | up_read(&sdp->sd_log_flush_lock); | ||
712 | 722 | ||
713 | if (atomic_read(&sdp->sd_log_pinned) > atomic_read(&sdp->sd_log_thresh1) || | 723 | if (atomic_read(&sdp->sd_log_pinned) > atomic_read(&sdp->sd_log_thresh1) || |
714 | ((sdp->sd_jdesc->jd_blocks - atomic_read(&sdp->sd_log_blks_free)) > | 724 | ((sdp->sd_jdesc->jd_blocks - atomic_read(&sdp->sd_log_blks_free)) > |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index a5055977a214..7318abf9d0fb 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -53,8 +53,8 @@ void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh) | |||
53 | * to in-place disk block, remove it from the AIL. | 53 | * to in-place disk block, remove it from the AIL. |
54 | */ | 54 | */ |
55 | spin_lock(&sdp->sd_ail_lock); | 55 | spin_lock(&sdp->sd_ail_lock); |
56 | if (bd->bd_ail) | 56 | if (bd->bd_tr) |
57 | list_move(&bd->bd_ail_st_list, &bd->bd_ail->ai_ail2_list); | 57 | list_move(&bd->bd_ail_st_list, &bd->bd_tr->tr_ail2_list); |
58 | spin_unlock(&sdp->sd_ail_lock); | 58 | spin_unlock(&sdp->sd_ail_lock); |
59 | get_bh(bh); | 59 | get_bh(bh); |
60 | atomic_inc(&sdp->sd_log_pinned); | 60 | atomic_inc(&sdp->sd_log_pinned); |
@@ -94,7 +94,7 @@ static void maybe_release_space(struct gfs2_bufdata *bd) | |||
94 | */ | 94 | */ |
95 | 95 | ||
96 | static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | 96 | static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, |
97 | struct gfs2_ail *ai) | 97 | struct gfs2_trans *tr) |
98 | { | 98 | { |
99 | struct gfs2_bufdata *bd = bh->b_private; | 99 | struct gfs2_bufdata *bd = bh->b_private; |
100 | 100 | ||
@@ -109,7 +109,7 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | |||
109 | maybe_release_space(bd); | 109 | maybe_release_space(bd); |
110 | 110 | ||
111 | spin_lock(&sdp->sd_ail_lock); | 111 | spin_lock(&sdp->sd_ail_lock); |
112 | if (bd->bd_ail) { | 112 | if (bd->bd_tr) { |
113 | list_del(&bd->bd_ail_st_list); | 113 | list_del(&bd->bd_ail_st_list); |
114 | brelse(bh); | 114 | brelse(bh); |
115 | } else { | 115 | } else { |
@@ -117,8 +117,8 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | |||
117 | list_add(&bd->bd_ail_gl_list, &gl->gl_ail_list); | 117 | list_add(&bd->bd_ail_gl_list, &gl->gl_ail_list); |
118 | atomic_inc(&gl->gl_ail_count); | 118 | atomic_inc(&gl->gl_ail_count); |
119 | } | 119 | } |
120 | bd->bd_ail = ai; | 120 | bd->bd_tr = tr; |
121 | list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list); | 121 | list_add(&bd->bd_ail_st_list, &tr->tr_ail1_list); |
122 | spin_unlock(&sdp->sd_ail_lock); | 122 | spin_unlock(&sdp->sd_ail_lock); |
123 | 123 | ||
124 | clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); | 124 | clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); |
@@ -480,17 +480,22 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) | |||
480 | &sdp->sd_log_le_buf, 0); | 480 | &sdp->sd_log_le_buf, 0); |
481 | } | 481 | } |
482 | 482 | ||
483 | static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | 483 | static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
484 | { | 484 | { |
485 | struct list_head *head = &sdp->sd_log_le_buf; | 485 | struct list_head *head = &sdp->sd_log_le_buf; |
486 | struct gfs2_bufdata *bd; | 486 | struct gfs2_bufdata *bd; |
487 | 487 | ||
488 | if (tr == NULL) { | ||
489 | gfs2_assert(sdp, list_empty(head)); | ||
490 | return; | ||
491 | } | ||
492 | |||
488 | while (!list_empty(head)) { | 493 | while (!list_empty(head)) { |
489 | bd = list_entry(head->next, struct gfs2_bufdata, bd_list); | 494 | bd = list_entry(head->next, struct gfs2_bufdata, bd_list); |
490 | list_del_init(&bd->bd_list); | 495 | list_del_init(&bd->bd_list); |
491 | sdp->sd_log_num_buf--; | 496 | sdp->sd_log_num_buf--; |
492 | 497 | ||
493 | gfs2_unpin(sdp, bd->bd_bh, ai); | 498 | gfs2_unpin(sdp, bd->bd_bh, tr); |
494 | } | 499 | } |
495 | gfs2_assert_warn(sdp, !sdp->sd_log_num_buf); | 500 | gfs2_assert_warn(sdp, !sdp->sd_log_num_buf); |
496 | } | 501 | } |
@@ -613,7 +618,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | |||
613 | gfs2_log_write_page(sdp, page); | 618 | gfs2_log_write_page(sdp, page); |
614 | } | 619 | } |
615 | 620 | ||
616 | static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | 621 | static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
617 | { | 622 | { |
618 | struct list_head *head = &sdp->sd_log_le_revoke; | 623 | struct list_head *head = &sdp->sd_log_le_revoke; |
619 | struct gfs2_bufdata *bd; | 624 | struct gfs2_bufdata *bd; |
@@ -791,16 +796,21 @@ static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) | |||
791 | jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks); | 796 | jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks); |
792 | } | 797 | } |
793 | 798 | ||
794 | static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | 799 | static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
795 | { | 800 | { |
796 | struct list_head *head = &sdp->sd_log_le_databuf; | 801 | struct list_head *head = &sdp->sd_log_le_databuf; |
797 | struct gfs2_bufdata *bd; | 802 | struct gfs2_bufdata *bd; |
798 | 803 | ||
804 | if (tr == NULL) { | ||
805 | gfs2_assert(sdp, list_empty(head)); | ||
806 | return; | ||
807 | } | ||
808 | |||
799 | while (!list_empty(head)) { | 809 | while (!list_empty(head)) { |
800 | bd = list_entry(head->next, struct gfs2_bufdata, bd_list); | 810 | bd = list_entry(head->next, struct gfs2_bufdata, bd_list); |
801 | list_del_init(&bd->bd_list); | 811 | list_del_init(&bd->bd_list); |
802 | sdp->sd_log_num_databuf--; | 812 | sdp->sd_log_num_databuf--; |
803 | gfs2_unpin(sdp, bd->bd_bh, ai); | 813 | gfs2_unpin(sdp, bd->bd_bh, tr); |
804 | } | 814 | } |
805 | gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf); | 815 | gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf); |
806 | } | 816 | } |
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h index ba77b7da8325..87e062e05c92 100644 --- a/fs/gfs2/lops.h +++ b/fs/gfs2/lops.h | |||
@@ -55,12 +55,13 @@ static inline void lops_before_commit(struct gfs2_sbd *sdp) | |||
55 | gfs2_log_ops[x]->lo_before_commit(sdp); | 55 | gfs2_log_ops[x]->lo_before_commit(sdp); |
56 | } | 56 | } |
57 | 57 | ||
58 | static inline void lops_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | 58 | static inline void lops_after_commit(struct gfs2_sbd *sdp, |
59 | struct gfs2_trans *tr) | ||
59 | { | 60 | { |
60 | int x; | 61 | int x; |
61 | for (x = 0; gfs2_log_ops[x]; x++) | 62 | for (x = 0; gfs2_log_ops[x]; x++) |
62 | if (gfs2_log_ops[x]->lo_after_commit) | 63 | if (gfs2_log_ops[x]->lo_after_commit) |
63 | gfs2_log_ops[x]->lo_after_commit(sdp, ai); | 64 | gfs2_log_ops[x]->lo_after_commit(sdp, tr); |
64 | } | 65 | } |
65 | 66 | ||
66 | static inline void lops_before_scan(struct gfs2_jdesc *jd, | 67 | static inline void lops_before_scan(struct gfs2_jdesc *jd, |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index b059bbb5059e..1a89afb68472 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -295,7 +295,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int | |||
295 | } | 295 | } |
296 | if (bd) { | 296 | if (bd) { |
297 | spin_lock(&sdp->sd_ail_lock); | 297 | spin_lock(&sdp->sd_ail_lock); |
298 | if (bd->bd_ail) { | 298 | if (bd->bd_tr) { |
299 | gfs2_remove_from_ail(bd); | 299 | gfs2_remove_from_ail(bd); |
300 | bh->b_private = NULL; | 300 | bh->b_private = NULL; |
301 | bd->bd_bh = NULL; | 301 | bd->bd_bh = NULL; |
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index 88162fae27a5..3bb4ac758857 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c | |||
@@ -135,8 +135,10 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) | |||
135 | if (tr->tr_t_gh.gh_gl) { | 135 | if (tr->tr_t_gh.gh_gl) { |
136 | gfs2_glock_dq(&tr->tr_t_gh); | 136 | gfs2_glock_dq(&tr->tr_t_gh); |
137 | gfs2_holder_uninit(&tr->tr_t_gh); | 137 | gfs2_holder_uninit(&tr->tr_t_gh); |
138 | kfree(tr); | 138 | if (!tr->tr_attached) |
139 | kfree(tr); | ||
139 | } | 140 | } |
141 | up_read(&sdp->sd_log_flush_lock); | ||
140 | 142 | ||
141 | if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) | 143 | if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) |
142 | gfs2_log_flush(sdp, NULL); | 144 | gfs2_log_flush(sdp, NULL); |