aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/aops.c2
-rw-r--r--fs/gfs2/incore.h17
-rw-r--r--fs/gfs2/log.c104
-rw-r--r--fs/gfs2/lops.c32
-rw-r--r--fs/gfs2/lops.h5
-rw-r--r--fs/gfs2/meta_io.c2
-rw-r--r--fs/gfs2/trans.c4
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;
31struct gfs2_glock; 31struct gfs2_glock;
32struct gfs2_quota_data; 32struct gfs2_quota_data;
33struct gfs2_trans; 33struct gfs2_trans;
34struct gfs2_ail;
35struct gfs2_jdesc; 34struct gfs2_jdesc;
36struct gfs2_sbd; 35struct gfs2_sbd;
37struct lm_lockops; 36struct lm_lockops;
@@ -53,7 +52,7 @@ struct gfs2_log_header_host {
53 52
54struct gfs2_log_operations { 53struct 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
445struct 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
453struct gfs2_journal_extent { 451struct 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
74void gfs2_remove_from_ail(struct gfs2_bufdata *bd) 74void 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
91static int gfs2_ail1_start_one(struct gfs2_sbd *sdp, 91static 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)
144void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc) 144void 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);
151restart: 151restart:
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
186static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) 186static 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
211static int gfs2_ail1_empty(struct gfs2_sbd *sdp) 211static 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
230static void gfs2_ail1_wait(struct gfs2_sbd *sdp) 230static 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
259static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) 259static 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
272static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) 272static 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
436static unsigned int current_tail(struct gfs2_sbd *sdp) 436static 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
601void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) 602void 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
668static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 673static 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)
708void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 719void 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
96static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, 96static 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
483static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) 483static 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
616static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) 621static 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
794static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) 799static 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
58static inline void lops_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) 58static 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
66static inline void lops_before_scan(struct gfs2_jdesc *jd, 67static 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);