diff options
-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: | |||
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 | ||
657 | static void log_write_header(struct gfs2_sbd *sdp, u32 flags) | 661 | void 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 | |||
695 | static 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 | }; |
74 | extern void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail, | ||
75 | u32 flags, int op_flags); | ||
74 | extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, | 76 | extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, |
75 | enum gfs2_flush_type type); | 77 | enum gfs2_flush_type type); |
76 | extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); | 78 | 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 @@ | |||
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 | ||
381 | static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head) | 380 | static 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); |