Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Btrfs: break up __btrfs_write_out_cache to cut down stack usage

__btrfs_write_out_cache was one of our stack pigs. This breaks it
up into helper functions and slims it down to 194 bytes.

Signed-off-by: Chris Mason <clm@fb.com>

+194 -120
+194 -120
fs/btrfs/free-space-cache.c
··· 851 851 return ret; 852 852 } 853 853 854 - /** 855 - * __btrfs_write_out_cache - write out cached info to an inode 856 - * @root - the root the inode belongs to 857 - * @ctl - the free space cache we are going to write out 858 - * @block_group - the block_group for this cache if it belongs to a block_group 859 - * @trans - the trans handle 860 - * @path - the path to use 861 - * @offset - the offset for the key we'll insert 862 - * 863 - * This function writes out a free space cache struct to disk for quick recovery 864 - * on mount. This will return 0 if it was successfull in writing the cache out, 865 - * and -1 if it was not. 866 - */ 867 - static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, 868 - struct btrfs_free_space_ctl *ctl, 869 - struct btrfs_block_group_cache *block_group, 870 - struct btrfs_trans_handle *trans, 871 - struct btrfs_path *path, u64 offset) 854 + static noinline_for_stack 855 + int write_cache_extent_entries(struct io_ctl *io_ctl, 856 + struct btrfs_free_space_ctl *ctl, 857 + struct btrfs_block_group_cache *block_group, 858 + int *entries, int *bitmaps, 859 + struct list_head *bitmap_list) 872 860 { 873 - struct btrfs_free_space_header *header; 874 - struct extent_buffer *leaf; 875 - struct rb_node *node; 876 - struct list_head *pos, *n; 877 - struct extent_state *cached_state = NULL; 878 - struct btrfs_free_cluster *cluster = NULL; 879 - struct extent_io_tree *unpin = NULL; 880 - struct io_ctl io_ctl; 881 - struct list_head bitmap_list; 882 - struct btrfs_key key; 883 - u64 start, extent_start, extent_end, len; 884 - int entries = 0; 885 - int bitmaps = 0; 886 861 int ret; 887 - int err = -1; 888 - 889 - INIT_LIST_HEAD(&bitmap_list); 890 - 891 - if (!i_size_read(inode)) 892 - return -1; 893 - 894 - ret = io_ctl_init(&io_ctl, inode, root); 895 - if (ret) 896 - return -1; 862 + struct btrfs_free_cluster *cluster = NULL; 863 + struct rb_node *node = rb_first(&ctl->free_space_offset); 897 864 898 865 /* Get the cluster for this block_group if it exists */ 899 - if (block_group && !list_empty(&block_group->cluster_list)) 866 + if (block_group && !list_empty(&block_group->cluster_list)) { 900 867 cluster = list_entry(block_group->cluster_list.next, 901 868 struct btrfs_free_cluster, 902 869 block_group_list); 870 + } 903 871 904 - /* Lock all pages first so we can lock the extent safely. */ 905 - io_ctl_prepare_pages(&io_ctl, inode, 0); 906 - 907 - lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1, 908 - 0, &cached_state); 909 - 910 - node = rb_first(&ctl->free_space_offset); 911 872 if (!node && cluster) { 912 873 node = rb_first(&cluster->root); 913 874 cluster = NULL; 914 875 } 915 - 916 - /* Make sure we can fit our crcs into the first page */ 917 - if (io_ctl.check_crcs && 918 - (io_ctl.num_pages * sizeof(u32)) >= PAGE_CACHE_SIZE) 919 - goto out_nospc; 920 - 921 - io_ctl_set_generation(&io_ctl, trans->transid); 922 876 923 877 /* Write out the extent entries */ 924 878 while (node) { 925 879 struct btrfs_free_space *e; 926 880 927 881 e = rb_entry(node, struct btrfs_free_space, offset_index); 928 - entries++; 882 + *entries += 1; 929 883 930 - ret = io_ctl_add_entry(&io_ctl, e->offset, e->bytes, 884 + ret = io_ctl_add_entry(io_ctl, e->offset, e->bytes, 931 885 e->bitmap); 932 886 if (ret) 933 - goto out_nospc; 887 + goto fail; 934 888 935 889 if (e->bitmap) { 936 - list_add_tail(&e->list, &bitmap_list); 937 - bitmaps++; 890 + list_add_tail(&e->list, bitmap_list); 891 + *bitmaps += 1; 938 892 } 939 893 node = rb_next(node); 940 894 if (!node && cluster) { ··· 896 942 cluster = NULL; 897 943 } 898 944 } 945 + return 0; 946 + fail: 947 + return -ENOSPC; 948 + } 949 + 950 + static noinline_for_stack int 951 + update_cache_item(struct btrfs_trans_handle *trans, 952 + struct btrfs_root *root, 953 + struct inode *inode, 954 + struct btrfs_path *path, u64 offset, 955 + int entries, int bitmaps) 956 + { 957 + struct btrfs_key key; 958 + struct btrfs_free_space_header *header; 959 + struct extent_buffer *leaf; 960 + int ret; 961 + 962 + key.objectid = BTRFS_FREE_SPACE_OBJECTID; 963 + key.offset = offset; 964 + key.type = 0; 965 + 966 + ret = btrfs_search_slot(trans, root, &key, path, 0, 1); 967 + if (ret < 0) { 968 + clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, inode->i_size - 1, 969 + EXTENT_DIRTY | EXTENT_DELALLOC, 0, 0, NULL, 970 + GFP_NOFS); 971 + goto fail; 972 + } 973 + leaf = path->nodes[0]; 974 + if (ret > 0) { 975 + struct btrfs_key found_key; 976 + ASSERT(path->slots[0]); 977 + path->slots[0]--; 978 + btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 979 + if (found_key.objectid != BTRFS_FREE_SPACE_OBJECTID || 980 + found_key.offset != offset) { 981 + clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, 982 + inode->i_size - 1, 983 + EXTENT_DIRTY | EXTENT_DELALLOC, 0, 0, 984 + NULL, GFP_NOFS); 985 + btrfs_release_path(path); 986 + goto fail; 987 + } 988 + } 989 + 990 + BTRFS_I(inode)->generation = trans->transid; 991 + header = btrfs_item_ptr(leaf, path->slots[0], 992 + struct btrfs_free_space_header); 993 + btrfs_set_free_space_entries(leaf, header, entries); 994 + btrfs_set_free_space_bitmaps(leaf, header, bitmaps); 995 + btrfs_set_free_space_generation(leaf, header, trans->transid); 996 + btrfs_mark_buffer_dirty(leaf); 997 + btrfs_release_path(path); 998 + 999 + return 0; 1000 + 1001 + fail: 1002 + return -1; 1003 + } 1004 + 1005 + static noinline_for_stack int 1006 + add_ioctl_entries(struct btrfs_root *root, 1007 + struct inode *inode, 1008 + struct btrfs_block_group_cache *block_group, 1009 + struct io_ctl *io_ctl, 1010 + struct extent_state **cached_state, 1011 + struct list_head *bitmap_list, 1012 + int *entries) 1013 + { 1014 + u64 start, extent_start, extent_end, len; 1015 + struct list_head *pos, *n; 1016 + struct extent_io_tree *unpin = NULL; 1017 + int ret; 899 1018 900 1019 /* 901 1020 * We want to add any pinned extents to our free space cache 902 1021 * so we don't leak the space 903 - */ 904 - 905 - /* 1022 + * 906 1023 * We shouldn't have switched the pinned extents yet so this is the 907 1024 * right one 908 1025 */ ··· 1002 977 block_group->key.offset, extent_end + 1); 1003 978 len = extent_end - extent_start; 1004 979 1005 - entries++; 1006 - ret = io_ctl_add_entry(&io_ctl, extent_start, len, NULL); 980 + *entries += 1; 981 + ret = io_ctl_add_entry(io_ctl, extent_start, len, NULL); 1007 982 if (ret) 1008 983 goto out_nospc; 1009 984 ··· 1011 986 } 1012 987 1013 988 /* Write out the bitmaps */ 1014 - list_for_each_safe(pos, n, &bitmap_list) { 989 + list_for_each_safe(pos, n, bitmap_list) { 1015 990 struct btrfs_free_space *entry = 1016 991 list_entry(pos, struct btrfs_free_space, list); 1017 992 1018 - ret = io_ctl_add_bitmap(&io_ctl, entry->bitmap); 993 + ret = io_ctl_add_bitmap(io_ctl, entry->bitmap); 1019 994 if (ret) 1020 995 goto out_nospc; 1021 996 list_del_init(&entry->list); 1022 997 } 1023 998 1024 999 /* Zero out the rest of the pages just to make sure */ 1025 - io_ctl_zero_remaining_pages(&io_ctl); 1000 + io_ctl_zero_remaining_pages(io_ctl); 1026 1001 1027 - ret = btrfs_dirty_pages(root, inode, io_ctl.pages, io_ctl.num_pages, 1028 - 0, i_size_read(inode), &cached_state); 1029 - io_ctl_drop_pages(&io_ctl); 1002 + ret = btrfs_dirty_pages(root, inode, io_ctl->pages, io_ctl->num_pages, 1003 + 0, i_size_read(inode), cached_state); 1004 + io_ctl_drop_pages(io_ctl); 1030 1005 unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, 1031 - i_size_read(inode) - 1, &cached_state, GFP_NOFS); 1006 + i_size_read(inode) - 1, cached_state, GFP_NOFS); 1032 1007 1033 1008 if (ret) 1034 - goto out; 1009 + goto fail; 1035 1010 1036 1011 ret = btrfs_wait_ordered_range(inode, 0, (u64)-1); 1037 1012 if (ret) { 1038 1013 clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, inode->i_size - 1, 1039 1014 EXTENT_DIRTY | EXTENT_DELALLOC, 0, 0, NULL, 1040 1015 GFP_NOFS); 1016 + goto fail; 1017 + } 1018 + return 0; 1019 + 1020 + fail: 1021 + return -1; 1022 + 1023 + out_nospc: 1024 + return -ENOSPC; 1025 + } 1026 + 1027 + static void noinline_for_stack 1028 + cleanup_write_cache_enospc(struct inode *inode, 1029 + struct io_ctl *io_ctl, 1030 + struct extent_state **cached_state, 1031 + struct list_head *bitmap_list) 1032 + { 1033 + struct list_head *pos, *n; 1034 + list_for_each_safe(pos, n, bitmap_list) { 1035 + struct btrfs_free_space *entry = 1036 + list_entry(pos, struct btrfs_free_space, list); 1037 + list_del_init(&entry->list); 1038 + } 1039 + io_ctl_drop_pages(io_ctl); 1040 + unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, 1041 + i_size_read(inode) - 1, cached_state, 1042 + GFP_NOFS); 1043 + } 1044 + 1045 + /** 1046 + * __btrfs_write_out_cache - write out cached info to an inode 1047 + * @root - the root the inode belongs to 1048 + * @ctl - the free space cache we are going to write out 1049 + * @block_group - the block_group for this cache if it belongs to a block_group 1050 + * @trans - the trans handle 1051 + * @path - the path to use 1052 + * @offset - the offset for the key we'll insert 1053 + * 1054 + * This function writes out a free space cache struct to disk for quick recovery 1055 + * on mount. This will return 0 if it was successfull in writing the cache out, 1056 + * and -1 if it was not. 1057 + */ 1058 + static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, 1059 + struct btrfs_free_space_ctl *ctl, 1060 + struct btrfs_block_group_cache *block_group, 1061 + struct btrfs_trans_handle *trans, 1062 + struct btrfs_path *path, u64 offset) 1063 + { 1064 + struct extent_state *cached_state = NULL; 1065 + struct io_ctl io_ctl; 1066 + struct list_head bitmap_list; 1067 + int entries = 0; 1068 + int bitmaps = 0; 1069 + int ret; 1070 + int err = -1; 1071 + 1072 + INIT_LIST_HEAD(&bitmap_list); 1073 + 1074 + if (!i_size_read(inode)) 1075 + return -1; 1076 + 1077 + ret = io_ctl_init(&io_ctl, inode, root); 1078 + if (ret) 1079 + return -1; 1080 + 1081 + /* Lock all pages first so we can lock the extent safely. */ 1082 + io_ctl_prepare_pages(&io_ctl, inode, 0); 1083 + 1084 + lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1, 1085 + 0, &cached_state); 1086 + 1087 + 1088 + /* Make sure we can fit our crcs into the first page */ 1089 + if (io_ctl.check_crcs && 1090 + (io_ctl.num_pages * sizeof(u32)) >= PAGE_CACHE_SIZE) 1091 + goto out_nospc; 1092 + 1093 + io_ctl_set_generation(&io_ctl, trans->transid); 1094 + 1095 + ret = write_cache_extent_entries(&io_ctl, ctl, 1096 + block_group, &entries, &bitmaps, 1097 + &bitmap_list); 1098 + if (ret) 1099 + goto out_nospc; 1100 + 1101 + ret = add_ioctl_entries(root, inode, block_group, &io_ctl, 1102 + &cached_state, &bitmap_list, &entries); 1103 + 1104 + if (ret == -ENOSPC) 1105 + goto out_nospc; 1106 + else if (ret) 1041 1107 goto out; 1042 - } 1043 1108 1044 - key.objectid = BTRFS_FREE_SPACE_OBJECTID; 1045 - key.offset = offset; 1046 - key.type = 0; 1109 + err = update_cache_item(trans, root, inode, path, offset, 1110 + entries, bitmaps); 1047 1111 1048 - ret = btrfs_search_slot(trans, root, &key, path, 0, 1); 1049 - if (ret < 0) { 1050 - clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, inode->i_size - 1, 1051 - EXTENT_DIRTY | EXTENT_DELALLOC, 0, 0, NULL, 1052 - GFP_NOFS); 1053 - goto out; 1054 - } 1055 - leaf = path->nodes[0]; 1056 - if (ret > 0) { 1057 - struct btrfs_key found_key; 1058 - ASSERT(path->slots[0]); 1059 - path->slots[0]--; 1060 - btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 1061 - if (found_key.objectid != BTRFS_FREE_SPACE_OBJECTID || 1062 - found_key.offset != offset) { 1063 - clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, 1064 - inode->i_size - 1, 1065 - EXTENT_DIRTY | EXTENT_DELALLOC, 0, 0, 1066 - NULL, GFP_NOFS); 1067 - btrfs_release_path(path); 1068 - goto out; 1069 - } 1070 - } 1071 - 1072 - BTRFS_I(inode)->generation = trans->transid; 1073 - header = btrfs_item_ptr(leaf, path->slots[0], 1074 - struct btrfs_free_space_header); 1075 - btrfs_set_free_space_entries(leaf, header, entries); 1076 - btrfs_set_free_space_bitmaps(leaf, header, bitmaps); 1077 - btrfs_set_free_space_generation(leaf, header, trans->transid); 1078 - btrfs_mark_buffer_dirty(leaf); 1079 - btrfs_release_path(path); 1080 - 1081 - err = 0; 1082 1112 out: 1083 1113 io_ctl_free(&io_ctl); 1084 1114 if (err) { ··· 1144 1064 return err; 1145 1065 1146 1066 out_nospc: 1147 - list_for_each_safe(pos, n, &bitmap_list) { 1148 - struct btrfs_free_space *entry = 1149 - list_entry(pos, struct btrfs_free_space, list); 1150 - list_del_init(&entry->list); 1151 - } 1152 - io_ctl_drop_pages(&io_ctl); 1153 - unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, 1154 - i_size_read(inode) - 1, &cached_state, GFP_NOFS); 1067 + 1068 + cleanup_write_cache_enospc(inode, &io_ctl, &cached_state, &bitmap_list); 1155 1069 goto out; 1156 1070 } 1157 1071