aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/log.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2007-09-17 05:59:52 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2007-10-10 03:56:24 -0400
commit16615be18cadf53ee6f8a4f0bdd647f0753421b1 (patch)
tree670c75e931e6d606211f338ee5e8b1d603c96521 /fs/gfs2/log.c
parent55c0c4ac0be144014651b19e77c9b77f367955de (diff)
[GFS2] Clean up journaled data writing
This patch cleans up the code for writing journaled data into the log. It also removes the need to allocate a small "tag" structure for each block written into the log. Instead we just keep count of the outstanding I/O so that we can be sure that its all been written at the correct time. Another result of this patch is that a number of ll_rw_block() calls have become submit_bh() calls, closing some races at the same time. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r--fs/gfs2/log.c145
1 files changed, 83 insertions, 62 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 4d04e6f19706..ee704676b2f1 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -104,11 +104,8 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
104 gfs2_assert(sdp, bd->bd_ail == ai); 104 gfs2_assert(sdp, bd->bd_ail == ai);
105 105
106 if (!buffer_busy(bh)) { 106 if (!buffer_busy(bh)) {
107 if (!buffer_uptodate(bh)) { 107 if (!buffer_uptodate(bh))
108 gfs2_log_unlock(sdp);
109 gfs2_io_error_bh(sdp, bh); 108 gfs2_io_error_bh(sdp, bh);
110 gfs2_log_lock(sdp);
111 }
112 list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); 109 list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
113 continue; 110 continue;
114 } 111 }
@@ -118,9 +115,16 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
118 115
119 list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list); 116 list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list);
120 117
118 get_bh(bh);
121 gfs2_log_unlock(sdp); 119 gfs2_log_unlock(sdp);
122 wait_on_buffer(bh); 120 lock_buffer(bh);
123 ll_rw_block(WRITE, 1, &bh); 121 if (test_clear_buffer_dirty(bh)) {
122 bh->b_end_io = end_buffer_write_sync;
123 submit_bh(WRITE, bh);
124 } else {
125 unlock_buffer(bh);
126 brelse(bh);
127 }
124 gfs2_log_lock(sdp); 128 gfs2_log_lock(sdp);
125 129
126 retry = 1; 130 retry = 1;
@@ -446,10 +450,10 @@ static unsigned int current_tail(struct gfs2_sbd *sdp)
446 return tail; 450 return tail;
447} 451}
448 452
449static inline void log_incr_head(struct gfs2_sbd *sdp) 453void gfs2_log_incr_head(struct gfs2_sbd *sdp)
450{ 454{
451 if (sdp->sd_log_flush_head == sdp->sd_log_tail) 455 if (sdp->sd_log_flush_head == sdp->sd_log_tail)
452 gfs2_assert_withdraw(sdp, sdp->sd_log_flush_head == sdp->sd_log_head); 456 BUG_ON(sdp->sd_log_flush_head != sdp->sd_log_head);
453 457
454 if (++sdp->sd_log_flush_head == sdp->sd_jdesc->jd_blocks) { 458 if (++sdp->sd_log_flush_head == sdp->sd_jdesc->jd_blocks) {
455 sdp->sd_log_flush_head = 0; 459 sdp->sd_log_flush_head = 0;
@@ -458,6 +462,23 @@ static inline void log_incr_head(struct gfs2_sbd *sdp)
458} 462}
459 463
460/** 464/**
465 * gfs2_log_write_endio - End of I/O for a log buffer
466 * @bh: The buffer head
467 * @uptodate: I/O Status
468 *
469 */
470
471static void gfs2_log_write_endio(struct buffer_head *bh, int uptodate)
472{
473 struct gfs2_sbd *sdp = bh->b_private;
474 bh->b_private = NULL;
475
476 end_buffer_write_sync(bh, uptodate);
477 if (atomic_dec_and_test(&sdp->sd_log_in_flight))
478 wake_up(&sdp->sd_log_flush_wait);
479}
480
481/**
461 * gfs2_log_get_buf - Get and initialize a buffer to use for log control data 482 * gfs2_log_get_buf - Get and initialize a buffer to use for log control data
462 * @sdp: The GFS2 superblock 483 * @sdp: The GFS2 superblock
463 * 484 *
@@ -467,25 +488,42 @@ static inline void log_incr_head(struct gfs2_sbd *sdp)
467struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp) 488struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp)
468{ 489{
469 u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head); 490 u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head);
470 struct gfs2_log_buf *lb;
471 struct buffer_head *bh; 491 struct buffer_head *bh;
472 492
473 lb = kzalloc(sizeof(struct gfs2_log_buf), GFP_NOFS | __GFP_NOFAIL); 493 bh = sb_getblk(sdp->sd_vfs, blkno);
474 list_add(&lb->lb_list, &sdp->sd_log_flush_list);
475
476 bh = lb->lb_bh = sb_getblk(sdp->sd_vfs, blkno);
477 lock_buffer(bh); 494 lock_buffer(bh);
478 memset(bh->b_data, 0, bh->b_size); 495 memset(bh->b_data, 0, bh->b_size);
479 set_buffer_uptodate(bh); 496 set_buffer_uptodate(bh);
480 clear_buffer_dirty(bh); 497 clear_buffer_dirty(bh);
481 unlock_buffer(bh); 498 gfs2_log_incr_head(sdp);
482 499 atomic_inc(&sdp->sd_log_in_flight);
483 log_incr_head(sdp); 500 bh->b_private = sdp;
501 bh->b_end_io = gfs2_log_write_endio;
484 502
485 return bh; 503 return bh;
486} 504}
487 505
488/** 506/**
507 * gfs2_fake_write_endio -
508 * @bh: The buffer head
509 * @uptodate: The I/O Status
510 *
511 */
512
513static void gfs2_fake_write_endio(struct buffer_head *bh, int uptodate)
514{
515 struct buffer_head *real_bh = bh->b_private;
516 struct gfs2_sbd *sdp = GFS2_SB(real_bh->b_page->mapping->host);
517
518 end_buffer_write_sync(bh, uptodate);
519 free_buffer_head(bh);
520 unlock_buffer(real_bh);
521 brelse(real_bh);
522 if (atomic_dec_and_test(&sdp->sd_log_in_flight))
523 wake_up(&sdp->sd_log_flush_wait);
524}
525
526/**
489 * gfs2_log_fake_buf - Build a fake buffer head to write metadata buffer to log 527 * gfs2_log_fake_buf - Build a fake buffer head to write metadata buffer to log
490 * @sdp: the filesystem 528 * @sdp: the filesystem
491 * @data: the data the buffer_head should point to 529 * @data: the data the buffer_head should point to
@@ -497,22 +535,20 @@ struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
497 struct buffer_head *real) 535 struct buffer_head *real)
498{ 536{
499 u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head); 537 u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head);
500 struct gfs2_log_buf *lb;
501 struct buffer_head *bh; 538 struct buffer_head *bh;
502 539
503 lb = kzalloc(sizeof(struct gfs2_log_buf), GFP_NOFS | __GFP_NOFAIL); 540 bh = alloc_buffer_head(GFP_NOFS | __GFP_NOFAIL);
504 list_add(&lb->lb_list, &sdp->sd_log_flush_list);
505 lb->lb_real = real;
506
507 bh = lb->lb_bh = alloc_buffer_head(GFP_NOFS | __GFP_NOFAIL);
508 atomic_set(&bh->b_count, 1); 541 atomic_set(&bh->b_count, 1);
509 bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate); 542 bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate) | (1 << BH_Lock);
510 set_bh_page(bh, real->b_page, bh_offset(real)); 543 set_bh_page(bh, real->b_page, bh_offset(real));
511 bh->b_blocknr = blkno; 544 bh->b_blocknr = blkno;
512 bh->b_size = sdp->sd_sb.sb_bsize; 545 bh->b_size = sdp->sd_sb.sb_bsize;
513 bh->b_bdev = sdp->sd_vfs->s_bdev; 546 bh->b_bdev = sdp->sd_vfs->s_bdev;
547 bh->b_private = real;
548 bh->b_end_io = gfs2_fake_write_endio;
514 549
515 log_incr_head(sdp); 550 gfs2_log_incr_head(sdp);
551 atomic_inc(&sdp->sd_log_in_flight);
516 552
517 return bh; 553 return bh;
518} 554}
@@ -579,45 +615,24 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
579 gfs2_assert_withdraw(sdp, !pull); 615 gfs2_assert_withdraw(sdp, !pull);
580 616
581 sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); 617 sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
582 log_incr_head(sdp); 618 gfs2_log_incr_head(sdp);
583} 619}
584 620
585static void log_flush_commit(struct gfs2_sbd *sdp) 621static void log_flush_commit(struct gfs2_sbd *sdp)
586{ 622{
587 struct list_head *head = &sdp->sd_log_flush_list; 623 DEFINE_WAIT(wait);
588 struct gfs2_log_buf *lb; 624
589 struct buffer_head *bh; 625 if (atomic_read(&sdp->sd_log_in_flight)) {
590 int flushcount = 0; 626 do {
591 627 prepare_to_wait(&sdp->sd_log_flush_wait, &wait,
592 while (!list_empty(head)) { 628 TASK_UNINTERRUPTIBLE);
593 lb = list_entry(head->next, struct gfs2_log_buf, lb_list); 629 if (atomic_read(&sdp->sd_log_in_flight))
594 list_del(&lb->lb_list); 630 io_schedule();
595 bh = lb->lb_bh; 631 } while(atomic_read(&sdp->sd_log_in_flight));
596 632 finish_wait(&sdp->sd_log_flush_wait, &wait);
597 wait_on_buffer(bh);
598 if (!buffer_uptodate(bh))
599 gfs2_io_error_bh(sdp, bh);
600 if (lb->lb_real) {
601 while (atomic_read(&bh->b_count) != 1) /* Grrrr... */
602 schedule();
603 free_buffer_head(bh);
604 } else
605 brelse(bh);
606 kfree(lb);
607 flushcount++;
608 } 633 }
609 634
610 /* If nothing was journaled, the header is unplanned and unwanted. */ 635 log_write_header(sdp, 0, 0);
611 if (flushcount) {
612 log_write_header(sdp, 0, 0);
613 } else {
614 unsigned int tail;
615 tail = current_tail(sdp);
616
617 gfs2_ail1_empty(sdp, 0);
618 if (sdp->sd_log_tail != tail)
619 log_pull_tail(sdp, tail);
620 }
621} 636}
622 637
623static void gfs2_ordered_write(struct gfs2_sbd *sdp) 638static void gfs2_ordered_write(struct gfs2_sbd *sdp)
@@ -698,10 +713,16 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
698 INIT_LIST_HEAD(&ai->ai_ail1_list); 713 INIT_LIST_HEAD(&ai->ai_ail1_list);
699 INIT_LIST_HEAD(&ai->ai_ail2_list); 714 INIT_LIST_HEAD(&ai->ai_ail2_list);
700 715
701 gfs2_assert_withdraw(sdp, 716 if (sdp->sd_log_num_buf != sdp->sd_log_commited_buf) {
702 sdp->sd_log_num_buf + sdp->sd_log_num_databuf == 717 printk(KERN_INFO "GFS2: log buf %u %u\n", sdp->sd_log_num_buf,
703 sdp->sd_log_commited_buf + 718 sdp->sd_log_commited_buf);
704 sdp->sd_log_commited_databuf); 719 gfs2_assert_withdraw(sdp, 0);
720 }
721 if (sdp->sd_log_num_databuf != sdp->sd_log_commited_databuf) {
722 printk(KERN_INFO "GFS2: log databuf %u %u\n",
723 sdp->sd_log_num_databuf, sdp->sd_log_commited_databuf);
724 gfs2_assert_withdraw(sdp, 0);
725 }
705 gfs2_assert_withdraw(sdp, 726 gfs2_assert_withdraw(sdp,
706 sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); 727 sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);
707 728
@@ -713,7 +734,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
713 lops_before_commit(sdp); 734 lops_before_commit(sdp);
714 gfs2_ordered_wait(sdp); 735 gfs2_ordered_wait(sdp);
715 736
716 if (!list_empty(&sdp->sd_log_flush_list)) 737 if (sdp->sd_log_head != sdp->sd_log_flush_head)
717 log_flush_commit(sdp); 738 log_flush_commit(sdp);
718 else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ 739 else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
719 gfs2_log_lock(sdp); 740 gfs2_log_lock(sdp);