diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/log.c | 46 | ||||
-rw-r--r-- | fs/gfs2/log.h | 2 | ||||
-rw-r--r-- | fs/gfs2/recovery.c | 59 |
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: } /** - * 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); 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 { 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); 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 @@ #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); |