Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

GFS2: Move log buffer lists into transaction

Over time, we hope to be able to improve the concurrency available
in the log code. This is one small step towards that, by moving
the buffer lists from the super block, and into the transaction
structure, so that each transaction builds its own buffer lists.

At transaction commit time, the buffer lists are merged into
the currently accumulating transaction. That transaction then
is passed into the before and after commit functions at journal
flush time. Thus there should be no change in overall behaviour
yet.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>

+53 -29
+2
fs/gfs2/glops.c
··· 82 82 struct gfs2_trans tr; 83 83 84 84 memset(&tr, 0, sizeof(tr)); 85 + INIT_LIST_HEAD(&tr.tr_buf); 86 + INIT_LIST_HEAD(&tr.tr_databuf); 85 87 tr.tr_revokes = atomic_read(&gl->gl_ail_count); 86 88 87 89 if (!tr.tr_revokes)
+3 -3
fs/gfs2/incore.h
··· 52 52 */ 53 53 54 54 struct 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 56 void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr); 57 57 void (*lo_before_scan) (struct gfs2_jdesc *jd, 58 58 struct gfs2_log_header_host *head, int pass); ··· 476 476 unsigned int tr_num_revoke_rm; 477 477 478 478 struct list_head tr_list; 479 + struct list_head tr_databuf; 480 + struct list_head tr_buf; 479 481 480 482 unsigned int tr_first; 481 483 struct list_head tr_ail1_list; ··· 758 756 unsigned int sd_log_num_rg; 759 757 unsigned int sd_log_num_databuf; 760 758 761 - struct list_head sd_log_le_buf; 762 759 struct list_head sd_log_le_revoke; 763 - struct list_head sd_log_le_databuf; 764 760 struct list_head sd_log_le_ordered; 765 761 spinlock_t sd_ordered_lock; 766 762
+25 -3
fs/gfs2/log.c
··· 712 712 tr->tr_first = sdp->sd_log_flush_head; 713 713 714 714 gfs2_ordered_write(sdp); 715 - lops_before_commit(sdp); 715 + lops_before_commit(sdp, tr); 716 716 gfs2_log_flush_bio(sdp, WRITE); 717 717 718 718 if (sdp->sd_log_head != sdp->sd_log_flush_head) { ··· 744 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 + 753 + static 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 + 747 768 static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 748 769 { 749 770 unsigned int reserved; ··· 787 766 sdp->sd_jdesc->jd_blocks); 788 767 sdp->sd_log_blks_reserved = reserved; 789 768 790 - if (sdp->sd_log_tr == NULL && 791 - (tr->tr_num_buf_new || tr->tr_num_databuf_new)) { 769 + if (sdp->sd_log_tr) { 770 + gfs2_merge_trans(sdp->sd_log_tr, tr); 771 + } else if (tr->tr_num_buf_new || tr->tr_num_databuf_new) { 792 772 gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl); 793 773 sdp->sd_log_tr = tr; 794 774 tr->tr_attached = 1;
+15 -17
fs/gfs2/lops.c
··· 491 491 gfs2_log_unlock(sdp); 492 492 } 493 493 494 - static void buf_lo_before_commit(struct gfs2_sbd *sdp) 494 + static void buf_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 495 495 { 496 496 unsigned int limit = buf_limit(sdp); /* 503 for 4k blocks */ 497 - 498 - gfs2_before_commit(sdp, limit, sdp->sd_log_num_buf, 499 - &sdp->sd_log_le_buf, 0); 497 + if (tr == NULL) 498 + return; 499 + gfs2_before_commit(sdp, limit, sdp->sd_log_num_buf, &tr->tr_buf, 0); 500 500 } 501 501 502 502 static 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 505 struct gfs2_bufdata *bd; 506 506 507 - if (tr == NULL) { 508 - gfs2_assert(sdp, list_empty(head)); 507 + if (tr == NULL) 509 508 return; 510 - } 511 509 510 + head = &tr->tr_buf; 512 511 while (!list_empty(head)) { 513 512 bd = list_entry(head->next, struct gfs2_bufdata, bd_list); 514 513 list_del_init(&bd->bd_list); ··· 619 620 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks); 620 621 } 621 622 622 - static void revoke_lo_before_commit(struct gfs2_sbd *sdp) 623 + static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 623 624 { 624 625 struct gfs2_meta_header *mh; 625 626 unsigned int offset; ··· 759 760 * 760 761 */ 761 762 762 - static void databuf_lo_before_commit(struct gfs2_sbd *sdp) 763 + static void databuf_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 763 764 { 764 765 unsigned int limit = buf_limit(sdp) / 2; 765 - 766 - gfs2_before_commit(sdp, limit, sdp->sd_log_num_databuf, 767 - &sdp->sd_log_le_databuf, 1); 766 + if (tr == NULL) 767 + return; 768 + gfs2_before_commit(sdp, limit, sdp->sd_log_num_databuf, &tr->tr_databuf, 1); 768 769 } 769 770 770 771 static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, ··· 839 840 840 841 static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 841 842 { 842 - struct list_head *head = &sdp->sd_log_le_databuf; 843 + struct list_head *head; 843 844 struct gfs2_bufdata *bd; 844 845 845 - if (tr == NULL) { 846 - gfs2_assert(sdp, list_empty(head)); 846 + if (tr == NULL) 847 847 return; 848 - } 849 848 849 + head = &tr->tr_databuf; 850 850 while (!list_empty(head)) { 851 851 bd = list_entry(head->next, struct gfs2_bufdata, bd_list); 852 852 list_del_init(&bd->bd_list);
+3 -2
fs/gfs2/lops.h
··· 46 46 return limit; 47 47 } 48 48 49 - static inline void lops_before_commit(struct gfs2_sbd *sdp) 49 + static inline void lops_before_commit(struct gfs2_sbd *sdp, 50 + struct gfs2_trans *tr) 50 51 { 51 52 int x; 52 53 for (x = 0; gfs2_log_ops[x]; x++) 53 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 57 58 static inline void lops_after_commit(struct gfs2_sbd *sdp,
-2
fs/gfs2/ops_fstype.c
··· 114 114 115 115 spin_lock_init(&sdp->sd_log_lock); 116 116 atomic_set(&sdp->sd_log_pinned, 0); 117 - INIT_LIST_HEAD(&sdp->sd_log_le_buf); 118 117 INIT_LIST_HEAD(&sdp->sd_log_le_revoke); 119 - INIT_LIST_HEAD(&sdp->sd_log_le_databuf); 120 118 INIT_LIST_HEAD(&sdp->sd_log_le_ordered); 121 119 spin_lock_init(&sdp->sd_ordered_lock); 122 120
+5 -2
fs/gfs2/trans.c
··· 51 51 if (revokes) 52 52 tr->tr_reserved += gfs2_struct2blk(sdp, revokes, 53 53 sizeof(u64)); 54 + INIT_LIST_HEAD(&tr->tr_databuf); 55 + INIT_LIST_HEAD(&tr->tr_buf); 56 + 54 57 sb_start_intwrite(sdp->sd_vfs); 55 58 gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh); 56 59 ··· 214 211 gfs2_pin(sdp, bd->bd_bh); 215 212 tr->tr_num_databuf_new++; 216 213 sdp->sd_log_num_databuf++; 217 - list_add_tail(&bd->bd_list, &sdp->sd_log_le_databuf); 214 + list_add_tail(&bd->bd_list, &tr->tr_databuf); 218 215 } 219 216 gfs2_log_unlock(sdp); 220 217 unlock_buffer(bh); ··· 242 239 mh->__pad0 = cpu_to_be64(0); 243 240 mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); 244 241 sdp->sd_log_num_buf++; 245 - list_add(&bd->bd_list, &sdp->sd_log_le_buf); 242 + list_add(&bd->bd_list, &tr->tr_buf); 246 243 tr->tr_num_buf_new++; 247 244 } 248 245