aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/log.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2012-04-16 04:28:31 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2012-04-24 11:44:34 -0400
commite8c92ed769008cfc799497f0a34c8faf46243c4d (patch)
tree6e00d9ddfd7d02ac9b1ac50d99de946d42443922 /fs/gfs2/log.c
parent2f7ee358e5a0fedcb45c64bd83dad9dc9a212508 (diff)
GFS2: Clean up log write code path
Prior to this patch, we have two ways of sending i/o to the log. One of those is used when we need to allocate both the data to be written itself and also a buffer head to submit it. This is done via sb_getblk and friends. This is used mostly for writing log headers. The other method is used when writing blocks which have some in-place counterpart. This is the case for all the metadata blocks which are journalled, and when journaled data is in use, for unescaped journalled data blocks. This patch replaces both of those two methods, and about half a dozen separate i/o submission points with a single i/o submission function. We also go direct to bio rather than using buffer heads, since this allows us to build i/o requests of the maximum size for the block device in question. It also reduces the memory required for flushing the log, which can be very useful in low memory situations. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r--fs/gfs2/log.c57
1 files changed, 11 insertions, 46 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index d886a17f671a..f5eacb3589ba 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -357,18 +357,6 @@ retry:
357 return 0; 357 return 0;
358} 358}
359 359
360u64 gfs2_log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
361{
362 struct gfs2_journal_extent *je;
363
364 list_for_each_entry(je, &sdp->sd_jdesc->extent_list, extent_list) {
365 if (lbn >= je->lblock && lbn < je->lblock + je->blocks)
366 return je->dblock + lbn - je->lblock;
367 }
368
369 return -1;
370}
371
372/** 360/**
373 * log_distance - Compute distance between two journal blocks 361 * log_distance - Compute distance between two journal blocks
374 * @sdp: The GFS2 superblock 362 * @sdp: The GFS2 superblock
@@ -464,17 +452,6 @@ static unsigned int current_tail(struct gfs2_sbd *sdp)
464 return tail; 452 return tail;
465} 453}
466 454
467void gfs2_log_incr_head(struct gfs2_sbd *sdp)
468{
469 BUG_ON((sdp->sd_log_flush_head == sdp->sd_log_tail) &&
470 (sdp->sd_log_flush_head != sdp->sd_log_head));
471
472 if (++sdp->sd_log_flush_head == sdp->sd_jdesc->jd_blocks) {
473 sdp->sd_log_flush_head = 0;
474 sdp->sd_log_flush_wrapped = 1;
475 }
476}
477
478static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail) 455static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
479{ 456{
480 unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail); 457 unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail);
@@ -580,23 +557,17 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
580 557
581static void log_write_header(struct gfs2_sbd *sdp, u32 flags) 558static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
582{ 559{
583 u64 blkno = gfs2_log_bmap(sdp, sdp->sd_log_flush_head);
584 struct buffer_head *bh;
585 struct gfs2_log_header *lh; 560 struct gfs2_log_header *lh;
586 unsigned int tail; 561 unsigned int tail;
587 u32 hash; 562 u32 hash;
588 563 int rw = WRITE_FLUSH_FUA | REQ_META;
589 bh = sb_getblk(sdp->sd_vfs, blkno); 564 struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
590 lock_buffer(bh); 565 lh = page_address(page);
591 memset(bh->b_data, 0, bh->b_size); 566 clear_page(lh);
592 set_buffer_uptodate(bh);
593 clear_buffer_dirty(bh);
594 567
595 gfs2_ail1_empty(sdp); 568 gfs2_ail1_empty(sdp);
596 tail = current_tail(sdp); 569 tail = current_tail(sdp);
597 570
598 lh = (struct gfs2_log_header *)bh->b_data;
599 memset(lh, 0, sizeof(struct gfs2_log_header));
600 lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); 571 lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
601 lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); 572 lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
602 lh->lh_header.__pad0 = cpu_to_be64(0); 573 lh->lh_header.__pad0 = cpu_to_be64(0);
@@ -606,29 +577,22 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
606 lh->lh_flags = cpu_to_be32(flags); 577 lh->lh_flags = cpu_to_be32(flags);
607 lh->lh_tail = cpu_to_be32(tail); 578 lh->lh_tail = cpu_to_be32(tail);
608 lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head); 579 lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
609 hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header)); 580 hash = gfs2_disk_hash(page_address(page), sizeof(struct gfs2_log_header));
610 lh->lh_hash = cpu_to_be32(hash); 581 lh->lh_hash = cpu_to_be32(hash);
611 582
612 bh->b_end_io = end_buffer_write_sync;
613 get_bh(bh);
614 if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) { 583 if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) {
615 gfs2_ordered_wait(sdp); 584 gfs2_ordered_wait(sdp);
616 log_flush_wait(sdp); 585 log_flush_wait(sdp);
617 submit_bh(WRITE_SYNC | REQ_META | REQ_PRIO, bh); 586 rw = WRITE_SYNC | REQ_META | REQ_PRIO;
618 } else {
619 submit_bh(WRITE_FLUSH_FUA | REQ_META, bh);
620 } 587 }
621 wait_on_buffer(bh);
622 588
623 if (!buffer_uptodate(bh)) 589 sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
624 gfs2_io_error_bh(sdp, bh); 590 gfs2_log_write_page(sdp, page);
625 brelse(bh); 591 gfs2_log_flush_bio(sdp, rw);
592 log_flush_wait(sdp);
626 593
627 if (sdp->sd_log_tail != tail) 594 if (sdp->sd_log_tail != tail)
628 log_pull_tail(sdp, tail); 595 log_pull_tail(sdp, tail);
629
630 sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
631 gfs2_log_incr_head(sdp);
632} 596}
633 597
634/** 598/**
@@ -674,6 +638,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
674 638
675 gfs2_ordered_write(sdp); 639 gfs2_ordered_write(sdp);
676 lops_before_commit(sdp); 640 lops_before_commit(sdp);
641 gfs2_log_flush_bio(sdp, WRITE);
677 642
678 if (sdp->sd_log_head != sdp->sd_log_flush_head) { 643 if (sdp->sd_log_head != sdp->sd_log_flush_head) {
679 log_write_header(sdp, 0); 644 log_write_header(sdp, 0);