aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2013-04-05 21:31:46 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2013-04-08 03:46:22 -0400
commit16ca9412d8018188bddda29c3fee88471b94e3cb (patch)
tree4fdd7fdd2ab7ea216e5120c5f484a24bcea01d83
parent20095218fb882139527c0e04b8e63869fa057b14 (diff)
GFS2: replace gfs2_ail structure with gfs2_trans
In order to allow transactions and log flushes to happen at the same time, gfs2 needs to move the transaction accounting and active items list code into the gfs2_trans structure. As a first step toward this, this patch removes the gfs2_ail structure, and handles the active items list in the gfs_trans structure. This keeps gfs2 from allocating an ail structure on log flushes, and gives us a struture that can later be used to store the transaction accounting outside of the gfs2 superblock structure. With this patch, at the end of a transaction, gfs2 will add the gfs2_trans structure to the superblock if there is not one already. This structure now has the active items fields that were previously in gfs2_ail. This is not necessary in the case where the transaction was simply used to add revokes, since these are never written outside of the journal, and thus, don't need an active items list. Also, in order to make sure that the transaction structure is not removed while it's still in use by gfs2_trans_end, unlocking the sd_log_flush_lock has to happen slightly later in ending the transaction. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-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);