GFS2: Reduce code redundancy writing log headers
authorBob Peterson <rpeterso@redhat.com>
Mon, 18 Dec 2017 18:48:29 +0000 (12:48 -0600)
committerBob Peterson <rpeterso@redhat.com>
Fri, 22 Dec 2017 13:51:29 +0000 (07:51 -0600)
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>
fs/gfs2/log.c
fs/gfs2/log.h
fs/gfs2/recovery.c

index f72c442314062c4835ecaa3e0b92b538522f759a..27e97d3de1e0d1789081af0e58f1d44c5c0faedb 100644 (file)
@@ -648,49 +648,67 @@ out_of_blocks:
 }
 
 /**
- * log_write_header - Get and initialize a journal header buffer
+ * write_log_header - Write a journal log header buffer at sd_log_flush_head
  * @sdp: The GFS2 superblock
+ * @seq: sequence number
+ * @tail: tail of the log
+ * @flags: log header flags
+ * @op_flags: flags to pass to the bio
  *
  * Returns: the initialized log buffer descriptor
  */
 
-static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
+void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
+                          u32 flags, int op_flags)
 {
        struct gfs2_log_header *lh;
-       unsigned int tail;
        u32 hash;
-       int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC;
        struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
-       enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state);
+
        lh = page_address(page);
        clear_page(lh);
 
-       gfs2_assert_withdraw(sdp, (state != SFS_FROZEN));
-
-       tail = current_tail(sdp);
-
        lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
        lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
        lh->lh_header.__pad0 = cpu_to_be64(0);
        lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH);
        lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
-       lh->lh_sequence = cpu_to_be64(sdp->sd_log_sequence++);
+       lh->lh_sequence = cpu_to_be64(seq);
        lh->lh_flags = cpu_to_be32(flags);
        lh->lh_tail = cpu_to_be32(tail);
        lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
        hash = gfs2_disk_hash(page_address(page), sizeof(struct gfs2_log_header));
        lh->lh_hash = cpu_to_be32(hash);
 
+       gfs2_log_write_page(sdp, page);
+       gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags);
+       log_flush_wait(sdp);
+}
+
+/**
+ * log_write_header - Get and initialize a journal header buffer
+ * @sdp: The GFS2 superblock
+ *
+ * Returns: the initialized log buffer descriptor
+ */
+
+static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
+{
+       unsigned int tail;
+       int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC;
+       enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state);
+
+       gfs2_assert_withdraw(sdp, (state != SFS_FROZEN));
+       tail = current_tail(sdp);
+
        if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) {
                gfs2_ordered_wait(sdp);
                log_flush_wait(sdp);
                op_flags = REQ_SYNC | REQ_META | REQ_PRIO;
        }
-
        sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
-       gfs2_log_write_page(sdp, page);
-       gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags);
-       log_flush_wait(sdp);
+       gfs2_write_log_header(sdp, sdp->sd_log_sequence++, tail, flags,
+                             op_flags);
 
        if (sdp->sd_log_tail != tail)
                log_pull_tail(sdp, tail);
index 9499a6049212932cc0422db7e453c41e8430e4b2..619de9a1ff4f79c34d70c2aa0481a58b7e00c657 100644 (file)
@@ -71,6 +71,8 @@ enum gfs2_flush_type {
        SHUTDOWN_FLUSH,
        FREEZE_FLUSH
 };
+extern void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail,
+                                 u32 flags, int op_flags);
 extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
                           enum gfs2_flush_type type);
 extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
index 9395a3db1a601461e525ad116e8cfb58805965bd..5d34312194252a9969ea3392ad242249cbe008d9 100644 (file)
@@ -20,6 +20,7 @@
 #include "bmap.h"
 #include "glock.h"
 #include "glops.h"
+#include "log.h"
 #include "lops.h"
 #include "meta_io.h"
 #include "recovery.h"
@@ -370,62 +371,22 @@ static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start,
 
 /**
  * clean_journal - mark a dirty journal as being clean
- * @sdp: the filesystem
  * @jd: the journal
- * @gl: the journal's glock
  * @head: the head journal to start from
  *
  * Returns: errno
  */
 
-static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
+static void clean_journal(struct gfs2_jdesc *jd,
+                         struct gfs2_log_header_host *head)
 {
-       struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
        struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
-       unsigned int lblock;
-       struct gfs2_log_header *lh;
-       u32 hash;
-       struct buffer_head *bh;
-       int error;
-       struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 };
-
-       lblock = head->lh_blkno;
-       gfs2_replay_incr_blk(jd, &lblock);
-       bh_map.b_size = 1 << ip->i_inode.i_blkbits;
-       error = gfs2_block_map(&ip->i_inode, lblock, &bh_map, 0);
-       if (error)
-               return error;
-       if (!bh_map.b_blocknr) {
-               gfs2_consist_inode(ip);
-               return -EIO;
-       }
-
-       bh = sb_getblk(sdp->sd_vfs, bh_map.b_blocknr);
-       lock_buffer(bh);
-       memset(bh->b_data, 0, bh->b_size);
-       set_buffer_uptodate(bh);
-       clear_buffer_dirty(bh);
-       unlock_buffer(bh);
-
-       lh = (struct gfs2_log_header *)bh->b_data;
-       memset(lh, 0, sizeof(struct gfs2_log_header));
-       lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
-       lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
-       lh->lh_header.__pad0 = cpu_to_be64(0);
-       lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH);
-       lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
-       lh->lh_sequence = cpu_to_be64(head->lh_sequence + 1);
-       lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT);
-       lh->lh_blkno = cpu_to_be32(lblock);
-       hash = gfs2_disk_hash((const char *)lh, sizeof(struct gfs2_log_header));
-       lh->lh_hash = cpu_to_be32(hash);
-
-       set_buffer_dirty(bh);
-       if (sync_dirty_buffer(bh))
-               gfs2_io_error_bh(sdp, bh);
-       brelse(bh);
 
-       return error;
+       sdp->sd_log_flush_head = head->lh_blkno;
+       gfs2_replay_incr_blk(jd, &sdp->sd_log_flush_head);
+       gfs2_write_log_header(sdp, head->lh_sequence + 1, 0,
+                             GFS2_LOG_HEAD_UNMOUNT, REQ_PREFLUSH |
+                             REQ_FUA | REQ_META | REQ_SYNC);
 }
 
 
@@ -552,9 +513,7 @@ void gfs2_recover_func(struct work_struct *work)
                                goto fail_gunlock_thaw;
                }
 
-               error = clean_journal(jd, &head);
-               if (error)
-                       goto fail_gunlock_thaw;
+               clean_journal(jd, &head);
 
                gfs2_glock_dq_uninit(&thaw_gh);
                t = DIV_ROUND_UP(jiffies - t, HZ);