aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2017-12-18 13:48:29 -0500
committerBob Peterson <rpeterso@redhat.com>2017-12-22 08:51:29 -0500
commit588bff95c94efc05f9e1a0b19015c9408ed7c0ef (patch)
tree2c85e871e881f39874265f91653328694c1e2d35
parent850d2d915fa69011bef9bd668499cce889fdd8b3 (diff)
GFS2: Reduce code redundancy writing log headers
Before this patch, there was a lot of code redundancy between functions log_write_header (which uses bio) and clean_journal (which uses buffer_head). This patch reduces the redundancy to simplify the code and make log header writing more consistent. We want more consistency and reduced redundancy because we plan to add a bunch of new fields to improve performance (by eliminating the local statfs and quota files) improve metadata integrity (by adding new crcs and such) and for better debugging (by adding new fields to track when and where metadata was pushed through the journals.) We don't want to duplicate setting these new fields, nor allow for human error in the process. This reduction in code redundancy is accomplished by introducing a new helper function, gfs2_write_log_header which uses bio rather than bh. That simplifies recovery function clean_journal() to use the new helper function and iomap rather than redundancy and block_map (and eventually we can maybe remove block_map). It also reduces our dependency on buffer_heads. Signed-off-by: Bob Peterson <rpeterso@redhat.com>
-rw-r--r--fs/gfs2/log.c46
-rw-r--r--fs/gfs2/log.h2
-rw-r--r--fs/gfs2/recovery.c59
3 files changed, 43 insertions, 64 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index f72c44231406..27e97d3de1e0 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -648,49 +648,67 @@ out_of_blocks:
648} 648}
649 649
650/** 650/**
651 * log_write_header - Get and initialize a journal header buffer 651 * write_log_header - Write a journal log header buffer at sd_log_flush_head
652 * @sdp: The GFS2 superblock 652 * @sdp: The GFS2 superblock
653 * @seq: sequence number
654 * @tail: tail of the log
655 * @flags: log header flags
656 * @op_flags: flags to pass to the bio
653 * 657 *
654 * Returns: the initialized log buffer descriptor 658 * Returns: the initialized log buffer descriptor
655 */ 659 */
656 660
657static void log_write_header(struct gfs2_sbd *sdp, u32 flags) 661void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
662 u32 flags, int op_flags)
658{ 663{
659 struct gfs2_log_header *lh; 664 struct gfs2_log_header *lh;
660 unsigned int tail;
661 u32 hash; 665 u32 hash;
662 int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC;
663 struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO); 666 struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
664 enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); 667
665 lh = page_address(page); 668 lh = page_address(page);
666 clear_page(lh); 669 clear_page(lh);
667 670
668 gfs2_assert_withdraw(sdp, (state != SFS_FROZEN));
669
670 tail = current_tail(sdp);
671
672 lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); 671 lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
673 lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); 672 lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
674 lh->lh_header.__pad0 = cpu_to_be64(0); 673 lh->lh_header.__pad0 = cpu_to_be64(0);
675 lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); 674 lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH);
676 lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); 675 lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
677 lh->lh_sequence = cpu_to_be64(sdp->sd_log_sequence++); 676 lh->lh_sequence = cpu_to_be64(seq);
678 lh->lh_flags = cpu_to_be32(flags); 677 lh->lh_flags = cpu_to_be32(flags);
679 lh->lh_tail = cpu_to_be32(tail); 678 lh->lh_tail = cpu_to_be32(tail);
680 lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head); 679 lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
681 hash = gfs2_disk_hash(page_address(page), sizeof(struct gfs2_log_header)); 680 hash = gfs2_disk_hash(page_address(page), sizeof(struct gfs2_log_header));
682 lh->lh_hash = cpu_to_be32(hash); 681 lh->lh_hash = cpu_to_be32(hash);
683 682
683 gfs2_log_write_page(sdp, page);
684 gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags);
685 log_flush_wait(sdp);
686}
687
688/**
689 * log_write_header - Get and initialize a journal header buffer
690 * @sdp: The GFS2 superblock
691 *
692 * Returns: the initialized log buffer descriptor
693 */
694
695static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
696{
697 unsigned int tail;
698 int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC;
699 enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state);
700
701 gfs2_assert_withdraw(sdp, (state != SFS_FROZEN));
702 tail = current_tail(sdp);
703
684 if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) { 704 if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) {
685 gfs2_ordered_wait(sdp); 705 gfs2_ordered_wait(sdp);
686 log_flush_wait(sdp); 706 log_flush_wait(sdp);
687 op_flags = REQ_SYNC | REQ_META | REQ_PRIO; 707 op_flags = REQ_SYNC | REQ_META | REQ_PRIO;
688 } 708 }
689
690 sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); 709 sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
691 gfs2_log_write_page(sdp, page); 710 gfs2_write_log_header(sdp, sdp->sd_log_sequence++, tail, flags,
692 gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags); 711 op_flags);
693 log_flush_wait(sdp);
694 712
695 if (sdp->sd_log_tail != tail) 713 if (sdp->sd_log_tail != tail)
696 log_pull_tail(sdp, tail); 714 log_pull_tail(sdp, tail);
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h
index 9499a6049212..619de9a1ff4f 100644
--- a/fs/gfs2/log.h
+++ b/fs/gfs2/log.h
@@ -71,6 +71,8 @@ enum gfs2_flush_type {
71 SHUTDOWN_FLUSH, 71 SHUTDOWN_FLUSH,
72 FREEZE_FLUSH 72 FREEZE_FLUSH
73}; 73};
74extern void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
75 u32 flags, int op_flags);
74extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, 76extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
75 enum gfs2_flush_type type); 77 enum gfs2_flush_type type);
76extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); 78extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 9395a3db1a60..5d3431219425 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -20,6 +20,7 @@
20#include "bmap.h" 20#include "bmap.h"
21#include "glock.h" 21#include "glock.h"
22#include "glops.h" 22#include "glops.h"
23#include "log.h"
23#include "lops.h" 24#include "lops.h"
24#include "meta_io.h" 25#include "meta_io.h"
25#include "recovery.h" 26#include "recovery.h"
@@ -370,62 +371,22 @@ static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start,
370 371
371/** 372/**
372 * clean_journal - mark a dirty journal as being clean 373 * clean_journal - mark a dirty journal as being clean
373 * @sdp: the filesystem
374 * @jd: the journal 374 * @jd: the journal
375 * @gl: the journal's glock
376 * @head: the head journal to start from 375 * @head: the head journal to start from
377 * 376 *
378 * Returns: errno 377 * Returns: errno
379 */ 378 */
380 379
381static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head) 380static void clean_journal(struct gfs2_jdesc *jd,
381 struct gfs2_log_header_host *head)
382{ 382{
383 struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
384 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); 383 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
385 unsigned int lblock;
386 struct gfs2_log_header *lh;
387 u32 hash;
388 struct buffer_head *bh;
389 int error;
390 struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 };
391
392 lblock = head->lh_blkno;
393 gfs2_replay_incr_blk(jd, &lblock);
394 bh_map.b_size = 1 << ip->i_inode.i_blkbits;
395 error = gfs2_block_map(&ip->i_inode, lblock, &bh_map, 0);
396 if (error)
397 return error;
398 if (!bh_map.b_blocknr) {
399 gfs2_consist_inode(ip);
400 return -EIO;
401 }
402
403 bh = sb_getblk(sdp->sd_vfs, bh_map.b_blocknr);
404 lock_buffer(bh);
405 memset(bh->b_data, 0, bh->b_size);
406 set_buffer_uptodate(bh);
407 clear_buffer_dirty(bh);
408 unlock_buffer(bh);
409
410 lh = (struct gfs2_log_header *)bh->b_data;
411 memset(lh, 0, sizeof(struct gfs2_log_header));
412 lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
413 lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
414 lh->lh_header.__pad0 = cpu_to_be64(0);
415 lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH);
416 lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
417 lh->lh_sequence = cpu_to_be64(head->lh_sequence + 1);
418 lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT);
419 lh->lh_blkno = cpu_to_be32(lblock);
420 hash = gfs2_disk_hash((const char *)lh, sizeof(struct gfs2_log_header));
421 lh->lh_hash = cpu_to_be32(hash);
422
423 set_buffer_dirty(bh);
424 if (sync_dirty_buffer(bh))
425 gfs2_io_error_bh(sdp, bh);
426 brelse(bh);
427 384
428 return error; 385 sdp->sd_log_flush_head = head->lh_blkno;
386 gfs2_replay_incr_blk(jd, &sdp->sd_log_flush_head);
387 gfs2_write_log_header(sdp, head->lh_sequence + 1, 0,
388 GFS2_LOG_HEAD_UNMOUNT, REQ_PREFLUSH |
389 REQ_FUA | REQ_META | REQ_SYNC);
429} 390}
430 391
431 392
@@ -552,9 +513,7 @@ void gfs2_recover_func(struct work_struct *work)
552 goto fail_gunlock_thaw; 513 goto fail_gunlock_thaw;
553 } 514 }
554 515
555 error = clean_journal(jd, &head); 516 clean_journal(jd, &head);
556 if (error)
557 goto fail_gunlock_thaw;
558 517
559 gfs2_glock_dq_uninit(&thaw_gh); 518 gfs2_glock_dq_uninit(&thaw_gh);
560 t = DIV_ROUND_UP(jiffies - t, HZ); 519 t = DIV_ROUND_UP(jiffies - t, HZ);