diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 412 |
1 files changed, 405 insertions, 7 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 51d2e4de34eb..b531c36455d8 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -44,6 +44,20 @@ | |||
44 | static struct extent_io_ops btree_extent_io_ops; | 44 | static struct extent_io_ops btree_extent_io_ops; |
45 | static void end_workqueue_fn(struct btrfs_work *work); | 45 | static void end_workqueue_fn(struct btrfs_work *work); |
46 | static void free_fs_root(struct btrfs_root *root); | 46 | static void free_fs_root(struct btrfs_root *root); |
47 | static void btrfs_check_super_valid(struct btrfs_fs_info *fs_info, | ||
48 | int read_only); | ||
49 | static int btrfs_destroy_ordered_operations(struct btrfs_root *root); | ||
50 | static int btrfs_destroy_ordered_extents(struct btrfs_root *root); | ||
51 | static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | ||
52 | struct btrfs_root *root); | ||
53 | static int btrfs_destroy_pending_snapshots(struct btrfs_transaction *t); | ||
54 | static int btrfs_destroy_delalloc_inodes(struct btrfs_root *root); | ||
55 | static int btrfs_destroy_marked_extents(struct btrfs_root *root, | ||
56 | struct extent_io_tree *dirty_pages, | ||
57 | int mark); | ||
58 | static int btrfs_destroy_pinned_extent(struct btrfs_root *root, | ||
59 | struct extent_io_tree *pinned_extents); | ||
60 | static int btrfs_cleanup_transaction(struct btrfs_root *root); | ||
47 | 61 | ||
48 | /* | 62 | /* |
49 | * end_io_wq structs are used to do processing in task context when an IO is | 63 | * end_io_wq structs are used to do processing in task context when an IO is |
@@ -353,6 +367,10 @@ static int csum_dirty_buffer(struct btrfs_root *root, struct page *page) | |||
353 | WARN_ON(len == 0); | 367 | WARN_ON(len == 0); |
354 | 368 | ||
355 | eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); | 369 | eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); |
370 | if (eb == NULL) { | ||
371 | WARN_ON(1); | ||
372 | goto out; | ||
373 | } | ||
356 | ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE, | 374 | ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE, |
357 | btrfs_header_generation(eb)); | 375 | btrfs_header_generation(eb)); |
358 | BUG_ON(ret); | 376 | BUG_ON(ret); |
@@ -427,6 +445,10 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
427 | WARN_ON(len == 0); | 445 | WARN_ON(len == 0); |
428 | 446 | ||
429 | eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); | 447 | eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); |
448 | if (eb == NULL) { | ||
449 | ret = -EIO; | ||
450 | goto out; | ||
451 | } | ||
430 | 452 | ||
431 | found_start = btrfs_header_bytenr(eb); | 453 | found_start = btrfs_header_bytenr(eb); |
432 | if (found_start != start) { | 454 | if (found_start != start) { |
@@ -1145,6 +1167,7 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, | |||
1145 | } | 1167 | } |
1146 | btrfs_free_path(path); | 1168 | btrfs_free_path(path); |
1147 | if (ret) { | 1169 | if (ret) { |
1170 | kfree(root); | ||
1148 | if (ret > 0) | 1171 | if (ret > 0) |
1149 | ret = -ENOENT; | 1172 | ret = -ENOENT; |
1150 | return ERR_PTR(ret); | 1173 | return ERR_PTR(ret); |
@@ -1713,8 +1736,10 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1713 | fs_info, BTRFS_ROOT_TREE_OBJECTID); | 1736 | fs_info, BTRFS_ROOT_TREE_OBJECTID); |
1714 | 1737 | ||
1715 | bh = btrfs_read_dev_super(fs_devices->latest_bdev); | 1738 | bh = btrfs_read_dev_super(fs_devices->latest_bdev); |
1716 | if (!bh) | 1739 | if (!bh) { |
1740 | err = -EINVAL; | ||
1717 | goto fail_iput; | 1741 | goto fail_iput; |
1742 | } | ||
1718 | 1743 | ||
1719 | memcpy(&fs_info->super_copy, bh->b_data, sizeof(fs_info->super_copy)); | 1744 | memcpy(&fs_info->super_copy, bh->b_data, sizeof(fs_info->super_copy)); |
1720 | memcpy(&fs_info->super_for_commit, &fs_info->super_copy, | 1745 | memcpy(&fs_info->super_for_commit, &fs_info->super_copy, |
@@ -1727,6 +1752,11 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1727 | if (!btrfs_super_root(disk_super)) | 1752 | if (!btrfs_super_root(disk_super)) |
1728 | goto fail_iput; | 1753 | goto fail_iput; |
1729 | 1754 | ||
1755 | /* check FS state, whether FS is broken. */ | ||
1756 | fs_info->fs_state |= btrfs_super_flags(disk_super); | ||
1757 | |||
1758 | btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY); | ||
1759 | |||
1730 | ret = btrfs_parse_options(tree_root, options); | 1760 | ret = btrfs_parse_options(tree_root, options); |
1731 | if (ret) { | 1761 | if (ret) { |
1732 | err = ret; | 1762 | err = ret; |
@@ -1744,10 +1774,10 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1744 | } | 1774 | } |
1745 | 1775 | ||
1746 | features = btrfs_super_incompat_flags(disk_super); | 1776 | features = btrfs_super_incompat_flags(disk_super); |
1747 | if (!(features & BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF)) { | 1777 | features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF; |
1748 | features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF; | 1778 | if (tree_root->fs_info->compress_type & BTRFS_COMPRESS_LZO) |
1749 | btrfs_set_super_incompat_flags(disk_super, features); | 1779 | features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; |
1750 | } | 1780 | btrfs_set_super_incompat_flags(disk_super, features); |
1751 | 1781 | ||
1752 | features = btrfs_super_compat_ro_flags(disk_super) & | 1782 | features = btrfs_super_compat_ro_flags(disk_super) & |
1753 | ~BTRFS_FEATURE_COMPAT_RO_SUPP; | 1783 | ~BTRFS_FEATURE_COMPAT_RO_SUPP; |
@@ -1957,7 +1987,9 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1957 | btrfs_set_opt(fs_info->mount_opt, SSD); | 1987 | btrfs_set_opt(fs_info->mount_opt, SSD); |
1958 | } | 1988 | } |
1959 | 1989 | ||
1960 | if (btrfs_super_log_root(disk_super) != 0) { | 1990 | /* do not make disk changes in broken FS */ |
1991 | if (btrfs_super_log_root(disk_super) != 0 && | ||
1992 | !(fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)) { | ||
1961 | u64 bytenr = btrfs_super_log_root(disk_super); | 1993 | u64 bytenr = btrfs_super_log_root(disk_super); |
1962 | 1994 | ||
1963 | if (fs_devices->rw_devices == 0) { | 1995 | if (fs_devices->rw_devices == 0) { |
@@ -2442,8 +2474,28 @@ int close_ctree(struct btrfs_root *root) | |||
2442 | smp_mb(); | 2474 | smp_mb(); |
2443 | 2475 | ||
2444 | btrfs_put_block_group_cache(fs_info); | 2476 | btrfs_put_block_group_cache(fs_info); |
2477 | |||
2478 | /* | ||
2479 | * Here come 2 situations when btrfs is broken to flip readonly: | ||
2480 | * | ||
2481 | * 1. when btrfs flips readonly somewhere else before | ||
2482 | * btrfs_commit_super, sb->s_flags has MS_RDONLY flag, | ||
2483 | * and btrfs will skip to write sb directly to keep | ||
2484 | * ERROR state on disk. | ||
2485 | * | ||
2486 | * 2. when btrfs flips readonly just in btrfs_commit_super, | ||
2487 | * and in such case, btrfs cannnot write sb via btrfs_commit_super, | ||
2488 | * and since fs_state has been set BTRFS_SUPER_FLAG_ERROR flag, | ||
2489 | * btrfs will cleanup all FS resources first and write sb then. | ||
2490 | */ | ||
2445 | if (!(fs_info->sb->s_flags & MS_RDONLY)) { | 2491 | if (!(fs_info->sb->s_flags & MS_RDONLY)) { |
2446 | ret = btrfs_commit_super(root); | 2492 | ret = btrfs_commit_super(root); |
2493 | if (ret) | ||
2494 | printk(KERN_ERR "btrfs: commit super ret %d\n", ret); | ||
2495 | } | ||
2496 | |||
2497 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { | ||
2498 | ret = btrfs_error_commit_super(root); | ||
2447 | if (ret) | 2499 | if (ret) |
2448 | printk(KERN_ERR "btrfs: commit super ret %d\n", ret); | 2500 | printk(KERN_ERR "btrfs: commit super ret %d\n", ret); |
2449 | } | 2501 | } |
@@ -2619,6 +2671,352 @@ out: | |||
2619 | return 0; | 2671 | return 0; |
2620 | } | 2672 | } |
2621 | 2673 | ||
2674 | static void btrfs_check_super_valid(struct btrfs_fs_info *fs_info, | ||
2675 | int read_only) | ||
2676 | { | ||
2677 | if (read_only) | ||
2678 | return; | ||
2679 | |||
2680 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) | ||
2681 | printk(KERN_WARNING "warning: mount fs with errors, " | ||
2682 | "running btrfsck is recommended\n"); | ||
2683 | } | ||
2684 | |||
2685 | int btrfs_error_commit_super(struct btrfs_root *root) | ||
2686 | { | ||
2687 | int ret; | ||
2688 | |||
2689 | mutex_lock(&root->fs_info->cleaner_mutex); | ||
2690 | btrfs_run_delayed_iputs(root); | ||
2691 | mutex_unlock(&root->fs_info->cleaner_mutex); | ||
2692 | |||
2693 | down_write(&root->fs_info->cleanup_work_sem); | ||
2694 | up_write(&root->fs_info->cleanup_work_sem); | ||
2695 | |||
2696 | /* cleanup FS via transaction */ | ||
2697 | btrfs_cleanup_transaction(root); | ||
2698 | |||
2699 | ret = write_ctree_super(NULL, root, 0); | ||
2700 | |||
2701 | return ret; | ||
2702 | } | ||
2703 | |||
2704 | static int btrfs_destroy_ordered_operations(struct btrfs_root *root) | ||
2705 | { | ||
2706 | struct btrfs_inode *btrfs_inode; | ||
2707 | struct list_head splice; | ||
2708 | |||
2709 | INIT_LIST_HEAD(&splice); | ||
2710 | |||
2711 | mutex_lock(&root->fs_info->ordered_operations_mutex); | ||
2712 | spin_lock(&root->fs_info->ordered_extent_lock); | ||
2713 | |||
2714 | list_splice_init(&root->fs_info->ordered_operations, &splice); | ||
2715 | while (!list_empty(&splice)) { | ||
2716 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, | ||
2717 | ordered_operations); | ||
2718 | |||
2719 | list_del_init(&btrfs_inode->ordered_operations); | ||
2720 | |||
2721 | btrfs_invalidate_inodes(btrfs_inode->root); | ||
2722 | } | ||
2723 | |||
2724 | spin_unlock(&root->fs_info->ordered_extent_lock); | ||
2725 | mutex_unlock(&root->fs_info->ordered_operations_mutex); | ||
2726 | |||
2727 | return 0; | ||
2728 | } | ||
2729 | |||
2730 | static int btrfs_destroy_ordered_extents(struct btrfs_root *root) | ||
2731 | { | ||
2732 | struct list_head splice; | ||
2733 | struct btrfs_ordered_extent *ordered; | ||
2734 | struct inode *inode; | ||
2735 | |||
2736 | INIT_LIST_HEAD(&splice); | ||
2737 | |||
2738 | spin_lock(&root->fs_info->ordered_extent_lock); | ||
2739 | |||
2740 | list_splice_init(&root->fs_info->ordered_extents, &splice); | ||
2741 | while (!list_empty(&splice)) { | ||
2742 | ordered = list_entry(splice.next, struct btrfs_ordered_extent, | ||
2743 | root_extent_list); | ||
2744 | |||
2745 | list_del_init(&ordered->root_extent_list); | ||
2746 | atomic_inc(&ordered->refs); | ||
2747 | |||
2748 | /* the inode may be getting freed (in sys_unlink path). */ | ||
2749 | inode = igrab(ordered->inode); | ||
2750 | |||
2751 | spin_unlock(&root->fs_info->ordered_extent_lock); | ||
2752 | if (inode) | ||
2753 | iput(inode); | ||
2754 | |||
2755 | atomic_set(&ordered->refs, 1); | ||
2756 | btrfs_put_ordered_extent(ordered); | ||
2757 | |||
2758 | spin_lock(&root->fs_info->ordered_extent_lock); | ||
2759 | } | ||
2760 | |||
2761 | spin_unlock(&root->fs_info->ordered_extent_lock); | ||
2762 | |||
2763 | return 0; | ||
2764 | } | ||
2765 | |||
2766 | static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | ||
2767 | struct btrfs_root *root) | ||
2768 | { | ||
2769 | struct rb_node *node; | ||
2770 | struct btrfs_delayed_ref_root *delayed_refs; | ||
2771 | struct btrfs_delayed_ref_node *ref; | ||
2772 | int ret = 0; | ||
2773 | |||
2774 | delayed_refs = &trans->delayed_refs; | ||
2775 | |||
2776 | spin_lock(&delayed_refs->lock); | ||
2777 | if (delayed_refs->num_entries == 0) { | ||
2778 | printk(KERN_INFO "delayed_refs has NO entry\n"); | ||
2779 | return ret; | ||
2780 | } | ||
2781 | |||
2782 | node = rb_first(&delayed_refs->root); | ||
2783 | while (node) { | ||
2784 | ref = rb_entry(node, struct btrfs_delayed_ref_node, rb_node); | ||
2785 | node = rb_next(node); | ||
2786 | |||
2787 | ref->in_tree = 0; | ||
2788 | rb_erase(&ref->rb_node, &delayed_refs->root); | ||
2789 | delayed_refs->num_entries--; | ||
2790 | |||
2791 | atomic_set(&ref->refs, 1); | ||
2792 | if (btrfs_delayed_ref_is_head(ref)) { | ||
2793 | struct btrfs_delayed_ref_head *head; | ||
2794 | |||
2795 | head = btrfs_delayed_node_to_head(ref); | ||
2796 | mutex_lock(&head->mutex); | ||
2797 | kfree(head->extent_op); | ||
2798 | delayed_refs->num_heads--; | ||
2799 | if (list_empty(&head->cluster)) | ||
2800 | delayed_refs->num_heads_ready--; | ||
2801 | list_del_init(&head->cluster); | ||
2802 | mutex_unlock(&head->mutex); | ||
2803 | } | ||
2804 | |||
2805 | spin_unlock(&delayed_refs->lock); | ||
2806 | btrfs_put_delayed_ref(ref); | ||
2807 | |||
2808 | cond_resched(); | ||
2809 | spin_lock(&delayed_refs->lock); | ||
2810 | } | ||
2811 | |||
2812 | spin_unlock(&delayed_refs->lock); | ||
2813 | |||
2814 | return ret; | ||
2815 | } | ||
2816 | |||
2817 | static int btrfs_destroy_pending_snapshots(struct btrfs_transaction *t) | ||
2818 | { | ||
2819 | struct btrfs_pending_snapshot *snapshot; | ||
2820 | struct list_head splice; | ||
2821 | |||
2822 | INIT_LIST_HEAD(&splice); | ||
2823 | |||
2824 | list_splice_init(&t->pending_snapshots, &splice); | ||
2825 | |||
2826 | while (!list_empty(&splice)) { | ||
2827 | snapshot = list_entry(splice.next, | ||
2828 | struct btrfs_pending_snapshot, | ||
2829 | list); | ||
2830 | |||
2831 | list_del_init(&snapshot->list); | ||
2832 | |||
2833 | kfree(snapshot); | ||
2834 | } | ||
2835 | |||
2836 | return 0; | ||
2837 | } | ||
2838 | |||
2839 | static int btrfs_destroy_delalloc_inodes(struct btrfs_root *root) | ||
2840 | { | ||
2841 | struct btrfs_inode *btrfs_inode; | ||
2842 | struct list_head splice; | ||
2843 | |||
2844 | INIT_LIST_HEAD(&splice); | ||
2845 | |||
2846 | list_splice_init(&root->fs_info->delalloc_inodes, &splice); | ||
2847 | |||
2848 | spin_lock(&root->fs_info->delalloc_lock); | ||
2849 | |||
2850 | while (!list_empty(&splice)) { | ||
2851 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, | ||
2852 | delalloc_inodes); | ||
2853 | |||
2854 | list_del_init(&btrfs_inode->delalloc_inodes); | ||
2855 | |||
2856 | btrfs_invalidate_inodes(btrfs_inode->root); | ||
2857 | } | ||
2858 | |||
2859 | spin_unlock(&root->fs_info->delalloc_lock); | ||
2860 | |||
2861 | return 0; | ||
2862 | } | ||
2863 | |||
2864 | static int btrfs_destroy_marked_extents(struct btrfs_root *root, | ||
2865 | struct extent_io_tree *dirty_pages, | ||
2866 | int mark) | ||
2867 | { | ||
2868 | int ret; | ||
2869 | struct page *page; | ||
2870 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
2871 | struct extent_buffer *eb; | ||
2872 | u64 start = 0; | ||
2873 | u64 end; | ||
2874 | u64 offset; | ||
2875 | unsigned long index; | ||
2876 | |||
2877 | while (1) { | ||
2878 | ret = find_first_extent_bit(dirty_pages, start, &start, &end, | ||
2879 | mark); | ||
2880 | if (ret) | ||
2881 | break; | ||
2882 | |||
2883 | clear_extent_bits(dirty_pages, start, end, mark, GFP_NOFS); | ||
2884 | while (start <= end) { | ||
2885 | index = start >> PAGE_CACHE_SHIFT; | ||
2886 | start = (u64)(index + 1) << PAGE_CACHE_SHIFT; | ||
2887 | page = find_get_page(btree_inode->i_mapping, index); | ||
2888 | if (!page) | ||
2889 | continue; | ||
2890 | offset = page_offset(page); | ||
2891 | |||
2892 | spin_lock(&dirty_pages->buffer_lock); | ||
2893 | eb = radix_tree_lookup( | ||
2894 | &(&BTRFS_I(page->mapping->host)->io_tree)->buffer, | ||
2895 | offset >> PAGE_CACHE_SHIFT); | ||
2896 | spin_unlock(&dirty_pages->buffer_lock); | ||
2897 | if (eb) { | ||
2898 | ret = test_and_clear_bit(EXTENT_BUFFER_DIRTY, | ||
2899 | &eb->bflags); | ||
2900 | atomic_set(&eb->refs, 1); | ||
2901 | } | ||
2902 | if (PageWriteback(page)) | ||
2903 | end_page_writeback(page); | ||
2904 | |||
2905 | lock_page(page); | ||
2906 | if (PageDirty(page)) { | ||
2907 | clear_page_dirty_for_io(page); | ||
2908 | spin_lock_irq(&page->mapping->tree_lock); | ||
2909 | radix_tree_tag_clear(&page->mapping->page_tree, | ||
2910 | page_index(page), | ||
2911 | PAGECACHE_TAG_DIRTY); | ||
2912 | spin_unlock_irq(&page->mapping->tree_lock); | ||
2913 | } | ||
2914 | |||
2915 | page->mapping->a_ops->invalidatepage(page, 0); | ||
2916 | unlock_page(page); | ||
2917 | } | ||
2918 | } | ||
2919 | |||
2920 | return ret; | ||
2921 | } | ||
2922 | |||
2923 | static int btrfs_destroy_pinned_extent(struct btrfs_root *root, | ||
2924 | struct extent_io_tree *pinned_extents) | ||
2925 | { | ||
2926 | struct extent_io_tree *unpin; | ||
2927 | u64 start; | ||
2928 | u64 end; | ||
2929 | int ret; | ||
2930 | |||
2931 | unpin = pinned_extents; | ||
2932 | while (1) { | ||
2933 | ret = find_first_extent_bit(unpin, 0, &start, &end, | ||
2934 | EXTENT_DIRTY); | ||
2935 | if (ret) | ||
2936 | break; | ||
2937 | |||
2938 | /* opt_discard */ | ||
2939 | ret = btrfs_error_discard_extent(root, start, end + 1 - start); | ||
2940 | |||
2941 | clear_extent_dirty(unpin, start, end, GFP_NOFS); | ||
2942 | btrfs_error_unpin_extent_range(root, start, end); | ||
2943 | cond_resched(); | ||
2944 | } | ||
2945 | |||
2946 | return 0; | ||
2947 | } | ||
2948 | |||
2949 | static int btrfs_cleanup_transaction(struct btrfs_root *root) | ||
2950 | { | ||
2951 | struct btrfs_transaction *t; | ||
2952 | LIST_HEAD(list); | ||
2953 | |||
2954 | WARN_ON(1); | ||
2955 | |||
2956 | mutex_lock(&root->fs_info->trans_mutex); | ||
2957 | mutex_lock(&root->fs_info->transaction_kthread_mutex); | ||
2958 | |||
2959 | list_splice_init(&root->fs_info->trans_list, &list); | ||
2960 | while (!list_empty(&list)) { | ||
2961 | t = list_entry(list.next, struct btrfs_transaction, list); | ||
2962 | if (!t) | ||
2963 | break; | ||
2964 | |||
2965 | btrfs_destroy_ordered_operations(root); | ||
2966 | |||
2967 | btrfs_destroy_ordered_extents(root); | ||
2968 | |||
2969 | btrfs_destroy_delayed_refs(t, root); | ||
2970 | |||
2971 | btrfs_block_rsv_release(root, | ||
2972 | &root->fs_info->trans_block_rsv, | ||
2973 | t->dirty_pages.dirty_bytes); | ||
2974 | |||
2975 | /* FIXME: cleanup wait for commit */ | ||
2976 | t->in_commit = 1; | ||
2977 | t->blocked = 1; | ||
2978 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) | ||
2979 | wake_up(&root->fs_info->transaction_blocked_wait); | ||
2980 | |||
2981 | t->blocked = 0; | ||
2982 | if (waitqueue_active(&root->fs_info->transaction_wait)) | ||
2983 | wake_up(&root->fs_info->transaction_wait); | ||
2984 | mutex_unlock(&root->fs_info->trans_mutex); | ||
2985 | |||
2986 | mutex_lock(&root->fs_info->trans_mutex); | ||
2987 | t->commit_done = 1; | ||
2988 | if (waitqueue_active(&t->commit_wait)) | ||
2989 | wake_up(&t->commit_wait); | ||
2990 | mutex_unlock(&root->fs_info->trans_mutex); | ||
2991 | |||
2992 | mutex_lock(&root->fs_info->trans_mutex); | ||
2993 | |||
2994 | btrfs_destroy_pending_snapshots(t); | ||
2995 | |||
2996 | btrfs_destroy_delalloc_inodes(root); | ||
2997 | |||
2998 | spin_lock(&root->fs_info->new_trans_lock); | ||
2999 | root->fs_info->running_transaction = NULL; | ||
3000 | spin_unlock(&root->fs_info->new_trans_lock); | ||
3001 | |||
3002 | btrfs_destroy_marked_extents(root, &t->dirty_pages, | ||
3003 | EXTENT_DIRTY); | ||
3004 | |||
3005 | btrfs_destroy_pinned_extent(root, | ||
3006 | root->fs_info->pinned_extents); | ||
3007 | |||
3008 | t->use_count = 0; | ||
3009 | list_del_init(&t->list); | ||
3010 | memset(t, 0, sizeof(*t)); | ||
3011 | kmem_cache_free(btrfs_transaction_cachep, t); | ||
3012 | } | ||
3013 | |||
3014 | mutex_unlock(&root->fs_info->transaction_kthread_mutex); | ||
3015 | mutex_unlock(&root->fs_info->trans_mutex); | ||
3016 | |||
3017 | return 0; | ||
3018 | } | ||
3019 | |||
2622 | static struct extent_io_ops btree_extent_io_ops = { | 3020 | static struct extent_io_ops btree_extent_io_ops = { |
2623 | .write_cache_pages_lock_hook = btree_lock_page_hook, | 3021 | .write_cache_pages_lock_hook = btree_lock_page_hook, |
2624 | .readpage_end_io_hook = btree_readpage_end_io_hook, | 3022 | .readpage_end_io_hook = btree_readpage_end_io_hook, |