diff options
-rw-r--r-- | fs/gfs2/glops.c | 4 | ||||
-rw-r--r-- | fs/gfs2/log.c | 6 | ||||
-rw-r--r-- | fs/gfs2/ops_address.c | 132 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 2 |
4 files changed, 24 insertions, 120 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 777ca46010e8..88342e0b4bc7 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -156,9 +156,11 @@ static void inode_go_sync(struct gfs2_glock *gl) | |||
156 | ip = NULL; | 156 | ip = NULL; |
157 | 157 | ||
158 | if (test_bit(GLF_DIRTY, &gl->gl_flags)) { | 158 | if (test_bit(GLF_DIRTY, &gl->gl_flags)) { |
159 | if (ip) | 159 | if (ip && !gfs2_is_jdata(ip)) |
160 | filemap_fdatawrite(ip->i_inode.i_mapping); | 160 | filemap_fdatawrite(ip->i_inode.i_mapping); |
161 | gfs2_log_flush(gl->gl_sbd, gl); | 161 | gfs2_log_flush(gl->gl_sbd, gl); |
162 | if (ip && gfs2_is_jdata(ip)) | ||
163 | filemap_fdatawrite(ip->i_inode.i_mapping); | ||
162 | gfs2_meta_sync(gl); | 164 | gfs2_meta_sync(gl); |
163 | if (ip) { | 165 | if (ip) { |
164 | struct address_space *mapping = ip->i_inode.i_mapping; | 166 | struct address_space *mapping = ip->i_inode.i_mapping; |
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 00ab6c070a15..d0e6b42c86e1 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -229,8 +229,10 @@ static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
229 | list_del(&bd->bd_ail_st_list); | 229 | list_del(&bd->bd_ail_st_list); |
230 | list_del(&bd->bd_ail_gl_list); | 230 | list_del(&bd->bd_ail_gl_list); |
231 | atomic_dec(&bd->bd_gl->gl_ail_count); | 231 | atomic_dec(&bd->bd_gl->gl_ail_count); |
232 | bh_ip = GFS2_I(bd->bd_bh->b_page->mapping->host); | 232 | if (bd->bd_bh->b_page->mapping) { |
233 | gfs2_meta_cache_flush(bh_ip); | 233 | bh_ip = GFS2_I(bd->bd_bh->b_page->mapping->host); |
234 | gfs2_meta_cache_flush(bh_ip); | ||
235 | } | ||
234 | brelse(bd->bd_bh); | 236 | brelse(bd->bd_bh); |
235 | } | 237 | } |
236 | } | 238 | } |
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 42a5f58f6fca..8407d1db4eac 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -616,58 +616,13 @@ static sector_t gfs2_bmap(struct address_space *mapping, sector_t lblock) | |||
616 | return dblock; | 616 | return dblock; |
617 | } | 617 | } |
618 | 618 | ||
619 | static void discard_buffer(struct gfs2_sbd *sdp, struct buffer_head *bh) | ||
620 | { | ||
621 | struct gfs2_bufdata *bd; | ||
622 | |||
623 | gfs2_log_lock(sdp); | ||
624 | bd = bh->b_private; | ||
625 | if (bd) { | ||
626 | bd->bd_bh = NULL; | ||
627 | bh->b_private = NULL; | ||
628 | if (!bd->bd_ail && list_empty(&bd->bd_le.le_list)) | ||
629 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
630 | } | ||
631 | gfs2_log_unlock(sdp); | ||
632 | |||
633 | lock_buffer(bh); | ||
634 | clear_buffer_dirty(bh); | ||
635 | bh->b_bdev = NULL; | ||
636 | clear_buffer_mapped(bh); | ||
637 | clear_buffer_req(bh); | ||
638 | clear_buffer_new(bh); | ||
639 | clear_buffer_delay(bh); | ||
640 | unlock_buffer(bh); | ||
641 | } | ||
642 | |||
643 | static void gfs2_invalidatepage(struct page *page, unsigned long offset) | 619 | static void gfs2_invalidatepage(struct page *page, unsigned long offset) |
644 | { | 620 | { |
645 | struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host); | ||
646 | struct buffer_head *head, *bh, *next; | ||
647 | unsigned int curr_off = 0; | ||
648 | |||
649 | BUG_ON(!PageLocked(page)); | 621 | BUG_ON(!PageLocked(page)); |
650 | if (offset == 0) | 622 | if (offset == 0) |
651 | ClearPageChecked(page); | 623 | ClearPageChecked(page); |
652 | if (!page_has_buffers(page)) | ||
653 | return; | ||
654 | 624 | ||
655 | bh = head = page_buffers(page); | 625 | block_invalidatepage(page, offset); |
656 | do { | ||
657 | unsigned int next_off = curr_off + bh->b_size; | ||
658 | next = bh->b_this_page; | ||
659 | |||
660 | if (offset <= curr_off) | ||
661 | discard_buffer(sdp, bh); | ||
662 | |||
663 | curr_off = next_off; | ||
664 | bh = next; | ||
665 | } while (bh != head); | ||
666 | |||
667 | if (!offset) | ||
668 | try_to_release_page(page, 0); | ||
669 | |||
670 | return; | ||
671 | } | 626 | } |
672 | 627 | ||
673 | /** | 628 | /** |
@@ -736,59 +691,6 @@ out: | |||
736 | } | 691 | } |
737 | 692 | ||
738 | /** | 693 | /** |
739 | * stuck_releasepage - We're stuck in gfs2_releasepage(). Print stuff out. | ||
740 | * @bh: the buffer we're stuck on | ||
741 | * | ||
742 | */ | ||
743 | |||
744 | static void stuck_releasepage(struct buffer_head *bh) | ||
745 | { | ||
746 | struct inode *inode = bh->b_page->mapping->host; | ||
747 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | ||
748 | struct gfs2_bufdata *bd = bh->b_private; | ||
749 | struct gfs2_glock *gl; | ||
750 | static unsigned limit = 0; | ||
751 | |||
752 | if (limit > 3) | ||
753 | return; | ||
754 | limit++; | ||
755 | |||
756 | fs_warn(sdp, "stuck in gfs2_releasepage() %p\n", inode); | ||
757 | fs_warn(sdp, "blkno = %llu, bh->b_count = %d\n", | ||
758 | (unsigned long long)bh->b_blocknr, atomic_read(&bh->b_count)); | ||
759 | fs_warn(sdp, "pinned = %u\n", buffer_pinned(bh)); | ||
760 | fs_warn(sdp, "bh->b_private = %s\n", (bd) ? "!NULL" : "NULL"); | ||
761 | |||
762 | if (!bd) | ||
763 | return; | ||
764 | |||
765 | gl = bd->bd_gl; | ||
766 | |||
767 | fs_warn(sdp, "gl = (%u, %llu)\n", | ||
768 | gl->gl_name.ln_type, (unsigned long long)gl->gl_name.ln_number); | ||
769 | |||
770 | fs_warn(sdp, "bd_list_tr = %s, bd_le.le_list = %s\n", | ||
771 | (list_empty(&bd->bd_list_tr)) ? "no" : "yes", | ||
772 | (list_empty(&bd->bd_le.le_list)) ? "no" : "yes"); | ||
773 | |||
774 | if (gl->gl_ops == &gfs2_inode_glops) { | ||
775 | struct gfs2_inode *ip = gl->gl_object; | ||
776 | unsigned int x; | ||
777 | |||
778 | if (!ip) | ||
779 | return; | ||
780 | |||
781 | fs_warn(sdp, "ip = %llu %llu\n", | ||
782 | (unsigned long long)ip->i_no_formal_ino, | ||
783 | (unsigned long long)ip->i_no_addr); | ||
784 | |||
785 | for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) | ||
786 | fs_warn(sdp, "ip->i_cache[%u] = %s\n", | ||
787 | x, (ip->i_cache[x]) ? "!NULL" : "NULL"); | ||
788 | } | ||
789 | } | ||
790 | |||
791 | /** | ||
792 | * gfs2_releasepage - free the metadata associated with a page | 694 | * gfs2_releasepage - free the metadata associated with a page |
793 | * @page: the page that's being released | 695 | * @page: the page that's being released |
794 | * @gfp_mask: passed from Linux VFS, ignored by us | 696 | * @gfp_mask: passed from Linux VFS, ignored by us |
@@ -805,38 +707,31 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
805 | struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info; | 707 | struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info; |
806 | struct buffer_head *bh, *head; | 708 | struct buffer_head *bh, *head; |
807 | struct gfs2_bufdata *bd; | 709 | struct gfs2_bufdata *bd; |
808 | unsigned long t = jiffies + gfs2_tune_get(sdp, gt_stall_secs) * HZ; | ||
809 | 710 | ||
810 | if (!page_has_buffers(page)) | 711 | if (!page_has_buffers(page)) |
811 | goto out; | 712 | goto out; |
812 | 713 | ||
714 | gfs2_log_lock(sdp); | ||
813 | head = bh = page_buffers(page); | 715 | head = bh = page_buffers(page); |
814 | do { | 716 | do { |
815 | while (atomic_read(&bh->b_count)) { | 717 | if (atomic_read(&bh->b_count)) |
816 | if (!atomic_read(&aspace->i_writecount)) | 718 | goto cannot_release; |
817 | return 0; | 719 | bd = bh->b_private; |
818 | 720 | if (bd && bd->bd_ail) | |
819 | if (!(gfp_mask & __GFP_WAIT)) | 721 | goto cannot_release; |
820 | return 0; | ||
821 | |||
822 | if (time_after_eq(jiffies, t)) { | ||
823 | stuck_releasepage(bh); | ||
824 | /* should we withdraw here? */ | ||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | yield(); | ||
829 | } | ||
830 | |||
831 | gfs2_assert_warn(sdp, !buffer_pinned(bh)); | 722 | gfs2_assert_warn(sdp, !buffer_pinned(bh)); |
832 | gfs2_assert_warn(sdp, !buffer_dirty(bh)); | 723 | gfs2_assert_warn(sdp, !buffer_dirty(bh)); |
724 | bh = bh->b_this_page; | ||
725 | } while(bh != head); | ||
726 | gfs2_log_unlock(sdp); | ||
833 | 727 | ||
728 | head = bh = page_buffers(page); | ||
729 | do { | ||
834 | gfs2_log_lock(sdp); | 730 | gfs2_log_lock(sdp); |
835 | bd = bh->b_private; | 731 | bd = bh->b_private; |
836 | if (bd) { | 732 | if (bd) { |
837 | gfs2_assert_warn(sdp, bd->bd_bh == bh); | 733 | gfs2_assert_warn(sdp, bd->bd_bh == bh); |
838 | gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr)); | 734 | gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr)); |
839 | gfs2_assert_warn(sdp, !bd->bd_ail); | ||
840 | bd->bd_bh = NULL; | 735 | bd->bd_bh = NULL; |
841 | if (!list_empty(&bd->bd_le.le_list)) | 736 | if (!list_empty(&bd->bd_le.le_list)) |
842 | bd = NULL; | 737 | bd = NULL; |
@@ -851,6 +746,9 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
851 | 746 | ||
852 | out: | 747 | out: |
853 | return try_to_free_buffers(page); | 748 | return try_to_free_buffers(page); |
749 | cannot_release: | ||
750 | gfs2_log_unlock(sdp); | ||
751 | return 0; | ||
854 | } | 752 | } |
855 | 753 | ||
856 | const struct address_space_operations gfs2_file_aops = { | 754 | const struct address_space_operations gfs2_file_aops = { |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index c1c6672ebb83..9e0e9be1e41d 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "super.h" | 35 | #include "super.h" |
36 | #include "sys.h" | 36 | #include "sys.h" |
37 | #include "util.h" | 37 | #include "util.h" |
38 | #include "log.h" | ||
38 | 39 | ||
39 | #define DO 0 | 40 | #define DO 0 |
40 | #define UNDO 1 | 41 | #define UNDO 1 |
@@ -887,6 +888,7 @@ error: | |||
887 | static void gfs2_kill_sb(struct super_block *sb) | 888 | static void gfs2_kill_sb(struct super_block *sb) |
888 | { | 889 | { |
889 | gfs2_delete_debugfs_file(sb->s_fs_info); | 890 | gfs2_delete_debugfs_file(sb->s_fs_info); |
891 | gfs2_meta_syncfs(sb->s_fs_info); | ||
890 | kill_block_super(sb); | 892 | kill_block_super(sb); |
891 | } | 893 | } |
892 | 894 | ||