aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/glops.c2
-rw-r--r--fs/gfs2/incore.h6
-rw-r--r--fs/gfs2/log.c28
-rw-r--r--fs/gfs2/lops.c32
-rw-r--r--fs/gfs2/lops.h5
-rw-r--r--fs/gfs2/ops_fstype.c2
-rw-r--r--fs/gfs2/trans.c7
7 files changed, 53 insertions, 29 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 3bf0631b5d56..54b66809e818 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -82,6 +82,8 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
82 struct gfs2_trans tr; 82 struct gfs2_trans tr;
83 83
84 memset(&tr, 0, sizeof(tr)); 84 memset(&tr, 0, sizeof(tr));
85 INIT_LIST_HEAD(&tr.tr_buf);
86 INIT_LIST_HEAD(&tr.tr_databuf);
85 tr.tr_revokes = atomic_read(&gl->gl_ail_count); 87 tr.tr_revokes = atomic_read(&gl->gl_ail_count);
86 88
87 if (!tr.tr_revokes) 89 if (!tr.tr_revokes)
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 645655cccdc8..99aab64c771a 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -52,7 +52,7 @@ struct gfs2_log_header_host {
52 */ 52 */
53 53
54struct gfs2_log_operations { 54struct gfs2_log_operations {
55 void (*lo_before_commit) (struct gfs2_sbd *sdp); 55 void (*lo_before_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr);
56 void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr); 56 void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr);
57 void (*lo_before_scan) (struct gfs2_jdesc *jd, 57 void (*lo_before_scan) (struct gfs2_jdesc *jd,
58 struct gfs2_log_header_host *head, int pass); 58 struct gfs2_log_header_host *head, int pass);
@@ -476,6 +476,8 @@ struct gfs2_trans {
476 unsigned int tr_num_revoke_rm; 476 unsigned int tr_num_revoke_rm;
477 477
478 struct list_head tr_list; 478 struct list_head tr_list;
479 struct list_head tr_databuf;
480 struct list_head tr_buf;
479 481
480 unsigned int tr_first; 482 unsigned int tr_first;
481 struct list_head tr_ail1_list; 483 struct list_head tr_ail1_list;
@@ -756,9 +758,7 @@ struct gfs2_sbd {
756 unsigned int sd_log_num_rg; 758 unsigned int sd_log_num_rg;
757 unsigned int sd_log_num_databuf; 759 unsigned int sd_log_num_databuf;
758 760
759 struct list_head sd_log_le_buf;
760 struct list_head sd_log_le_revoke; 761 struct list_head sd_log_le_revoke;
761 struct list_head sd_log_le_databuf;
762 struct list_head sd_log_le_ordered; 762 struct list_head sd_log_le_ordered;
763 spinlock_t sd_ordered_lock; 763 spinlock_t sd_ordered_lock;
764 764
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 1e1bda0de43d..975712c6660b 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -712,7 +712,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
712 tr->tr_first = sdp->sd_log_flush_head; 712 tr->tr_first = sdp->sd_log_flush_head;
713 713
714 gfs2_ordered_write(sdp); 714 gfs2_ordered_write(sdp);
715 lops_before_commit(sdp); 715 lops_before_commit(sdp, tr);
716 gfs2_log_flush_bio(sdp, WRITE); 716 gfs2_log_flush_bio(sdp, WRITE);
717 717
718 if (sdp->sd_log_head != sdp->sd_log_flush_head) { 718 if (sdp->sd_log_head != sdp->sd_log_flush_head) {
@@ -744,6 +744,27 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
744 kfree(tr); 744 kfree(tr);
745} 745}
746 746
747/**
748 * gfs2_merge_trans - Merge a new transaction into a cached transaction
749 * @old: Original transaction to be expanded
750 * @new: New transaction to be merged
751 */
752
753static void gfs2_merge_trans(struct gfs2_trans *old, struct gfs2_trans *new)
754{
755 WARN_ON_ONCE(old->tr_attached != 1);
756
757 old->tr_num_buf_new += new->tr_num_buf_new;
758 old->tr_num_databuf_new += new->tr_num_databuf_new;
759 old->tr_num_buf_rm += new->tr_num_buf_rm;
760 old->tr_num_databuf_rm += new->tr_num_databuf_rm;
761 old->tr_num_revoke += new->tr_num_revoke;
762 old->tr_num_revoke_rm += new->tr_num_revoke_rm;
763
764 list_splice_tail_init(&new->tr_databuf, &old->tr_databuf);
765 list_splice_tail_init(&new->tr_buf, &old->tr_buf);
766}
767
747static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 768static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
748{ 769{
749 unsigned int reserved; 770 unsigned int reserved;
@@ -766,8 +787,9 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
766 sdp->sd_jdesc->jd_blocks); 787 sdp->sd_jdesc->jd_blocks);
767 sdp->sd_log_blks_reserved = reserved; 788 sdp->sd_log_blks_reserved = reserved;
768 789
769 if (sdp->sd_log_tr == NULL && 790 if (sdp->sd_log_tr) {
770 (tr->tr_num_buf_new || tr->tr_num_databuf_new)) { 791 gfs2_merge_trans(sdp->sd_log_tr, tr);
792 } else if (tr->tr_num_buf_new || tr->tr_num_databuf_new) {
771 gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl); 793 gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl);
772 sdp->sd_log_tr = tr; 794 sdp->sd_log_tr = tr;
773 tr->tr_attached = 1; 795 tr->tr_attached = 1;
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 76693793cedd..ee9ec7fa3011 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -491,24 +491,23 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit,
491 gfs2_log_unlock(sdp); 491 gfs2_log_unlock(sdp);
492} 492}
493 493
494static void buf_lo_before_commit(struct gfs2_sbd *sdp) 494static void buf_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
495{ 495{
496 unsigned int limit = buf_limit(sdp); /* 503 for 4k blocks */ 496 unsigned int limit = buf_limit(sdp); /* 503 for 4k blocks */
497 497 if (tr == NULL)
498 gfs2_before_commit(sdp, limit, sdp->sd_log_num_buf, 498 return;
499 &sdp->sd_log_le_buf, 0); 499 gfs2_before_commit(sdp, limit, sdp->sd_log_num_buf, &tr->tr_buf, 0);
500} 500}
501 501
502static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 502static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
503{ 503{
504 struct list_head *head = &sdp->sd_log_le_buf; 504 struct list_head *head;
505 struct gfs2_bufdata *bd; 505 struct gfs2_bufdata *bd;
506 506
507 if (tr == NULL) { 507 if (tr == NULL)
508 gfs2_assert(sdp, list_empty(head));
509 return; 508 return;
510 }
511 509
510 head = &tr->tr_buf;
512 while (!list_empty(head)) { 511 while (!list_empty(head)) {
513 bd = list_entry(head->next, struct gfs2_bufdata, bd_list); 512 bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
514 list_del_init(&bd->bd_list); 513 list_del_init(&bd->bd_list);
@@ -620,7 +619,7 @@ static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
620 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks); 619 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);
621} 620}
622 621
623static void revoke_lo_before_commit(struct gfs2_sbd *sdp) 622static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
624{ 623{
625 struct gfs2_meta_header *mh; 624 struct gfs2_meta_header *mh;
626 unsigned int offset; 625 unsigned int offset;
@@ -760,12 +759,12 @@ static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
760 * 759 *
761 */ 760 */
762 761
763static void databuf_lo_before_commit(struct gfs2_sbd *sdp) 762static void databuf_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
764{ 763{
765 unsigned int limit = buf_limit(sdp) / 2; 764 unsigned int limit = buf_limit(sdp) / 2;
766 765 if (tr == NULL)
767 gfs2_before_commit(sdp, limit, sdp->sd_log_num_databuf, 766 return;
768 &sdp->sd_log_le_databuf, 1); 767 gfs2_before_commit(sdp, limit, sdp->sd_log_num_databuf, &tr->tr_databuf, 1);
769} 768}
770 769
771static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, 770static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
@@ -840,14 +839,13 @@ static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
840 839
841static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 840static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
842{ 841{
843 struct list_head *head = &sdp->sd_log_le_databuf; 842 struct list_head *head;
844 struct gfs2_bufdata *bd; 843 struct gfs2_bufdata *bd;
845 844
846 if (tr == NULL) { 845 if (tr == NULL)
847 gfs2_assert(sdp, list_empty(head));
848 return; 846 return;
849 }
850 847
848 head = &tr->tr_databuf;
851 while (!list_empty(head)) { 849 while (!list_empty(head)) {
852 bd = list_entry(head->next, struct gfs2_bufdata, bd_list); 850 bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
853 list_del_init(&bd->bd_list); 851 list_del_init(&bd->bd_list);
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
index 9ca2e6438419..a65a7ba32ffd 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -46,12 +46,13 @@ static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
46 return limit; 46 return limit;
47} 47}
48 48
49static inline void lops_before_commit(struct gfs2_sbd *sdp) 49static inline void lops_before_commit(struct gfs2_sbd *sdp,
50 struct gfs2_trans *tr)
50{ 51{
51 int x; 52 int x;
52 for (x = 0; gfs2_log_ops[x]; x++) 53 for (x = 0; gfs2_log_ops[x]; x++)
53 if (gfs2_log_ops[x]->lo_before_commit) 54 if (gfs2_log_ops[x]->lo_before_commit)
54 gfs2_log_ops[x]->lo_before_commit(sdp); 55 gfs2_log_ops[x]->lo_before_commit(sdp, tr);
55} 56}
56 57
57static inline void lops_after_commit(struct gfs2_sbd *sdp, 58static inline void lops_after_commit(struct gfs2_sbd *sdp,
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index c6872d09561a..1f855a74a4ec 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -114,9 +114,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
114 114
115 spin_lock_init(&sdp->sd_log_lock); 115 spin_lock_init(&sdp->sd_log_lock);
116 atomic_set(&sdp->sd_log_pinned, 0); 116 atomic_set(&sdp->sd_log_pinned, 0);
117 INIT_LIST_HEAD(&sdp->sd_log_le_buf);
118 INIT_LIST_HEAD(&sdp->sd_log_le_revoke); 117 INIT_LIST_HEAD(&sdp->sd_log_le_revoke);
119 INIT_LIST_HEAD(&sdp->sd_log_le_databuf);
120 INIT_LIST_HEAD(&sdp->sd_log_le_ordered); 118 INIT_LIST_HEAD(&sdp->sd_log_le_ordered);
121 spin_lock_init(&sdp->sd_ordered_lock); 119 spin_lock_init(&sdp->sd_ordered_lock);
122 120
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 963b28c50fd4..e0464a22908c 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -51,6 +51,9 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
51 if (revokes) 51 if (revokes)
52 tr->tr_reserved += gfs2_struct2blk(sdp, revokes, 52 tr->tr_reserved += gfs2_struct2blk(sdp, revokes,
53 sizeof(u64)); 53 sizeof(u64));
54 INIT_LIST_HEAD(&tr->tr_databuf);
55 INIT_LIST_HEAD(&tr->tr_buf);
56
54 sb_start_intwrite(sdp->sd_vfs); 57 sb_start_intwrite(sdp->sd_vfs);
55 gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh); 58 gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh);
56 59
@@ -211,7 +214,7 @@ void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
211 gfs2_pin(sdp, bd->bd_bh); 214 gfs2_pin(sdp, bd->bd_bh);
212 tr->tr_num_databuf_new++; 215 tr->tr_num_databuf_new++;
213 sdp->sd_log_num_databuf++; 216 sdp->sd_log_num_databuf++;
214 list_add_tail(&bd->bd_list, &sdp->sd_log_le_databuf); 217 list_add_tail(&bd->bd_list, &tr->tr_databuf);
215 } 218 }
216 gfs2_log_unlock(sdp); 219 gfs2_log_unlock(sdp);
217 unlock_buffer(bh); 220 unlock_buffer(bh);
@@ -239,7 +242,7 @@ static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
239 mh->__pad0 = cpu_to_be64(0); 242 mh->__pad0 = cpu_to_be64(0);
240 mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); 243 mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
241 sdp->sd_log_num_buf++; 244 sdp->sd_log_num_buf++;
242 list_add(&bd->bd_list, &sdp->sd_log_le_buf); 245 list_add(&bd->bd_list, &tr->tr_buf);
243 tr->tr_num_buf_new++; 246 tr->tr_num_buf_new++;
244} 247}
245 248