diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-10-15 16:17:34 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:56 -0400 |
commit | 6b80053d02be41886344b5007d04e345311ec0b5 (patch) | |
tree | c935b3f2f4a582697167c52f57b0985137a95206 /fs/btrfs/ctree.c | |
parent | 09e71a326341f40111400c88aaf0498ef622824b (diff) |
Btrfs: Add back the online defragging code
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 177 |
1 files changed, 88 insertions, 89 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 34de83630ae9..08ddf1873ab1 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -155,55 +155,49 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
155 | return ret; | 155 | return ret; |
156 | } | 156 | } |
157 | 157 | ||
158 | #if 0 | 158 | static int close_blocks(u64 blocknr, u64 other, u32 blocksize) |
159 | static int close_blocks(u64 blocknr, u64 other) | ||
160 | { | 159 | { |
161 | if (blocknr < other && other - blocknr < 8) | 160 | if (blocknr < other && other - (blocknr + blocksize) < 32768) |
162 | return 1; | 161 | return 1; |
163 | if (blocknr > other && blocknr - other < 8) | 162 | if (blocknr > other && blocknr - (other + blocksize) < 32768) |
164 | return 1; | 163 | return 1; |
165 | return 0; | 164 | return 0; |
166 | } | 165 | } |
167 | 166 | ||
168 | static int should_defrag_leaf(struct extent_buffer *eb) | 167 | static int should_defrag_leaf(struct extent_buffer *leaf) |
169 | { | 168 | { |
170 | return 0; | 169 | struct btrfs_key key; |
171 | struct btrfs_leaf *leaf = btrfs_buffer_leaf(eb); | ||
172 | struct btrfs_disk_key *key; | ||
173 | u32 nritems; | 170 | u32 nritems; |
174 | 171 | ||
175 | if (buffer_defrag(bh)) | 172 | if (btrfs_buffer_defrag(leaf)) |
176 | return 1; | 173 | return 1; |
177 | 174 | ||
178 | nritems = btrfs_header_nritems(&leaf->header); | 175 | nritems = btrfs_header_nritems(leaf); |
179 | if (nritems == 0) | 176 | if (nritems == 0) |
180 | return 0; | 177 | return 0; |
181 | 178 | ||
182 | key = &leaf->items[0].key; | 179 | btrfs_item_key_to_cpu(leaf, &key, 0); |
183 | if (btrfs_disk_key_type(key) == BTRFS_DIR_ITEM_KEY) | 180 | if (key.type == BTRFS_DIR_ITEM_KEY) |
184 | return 1; | 181 | return 1; |
185 | 182 | ||
186 | key = &leaf->items[nritems-1].key; | 183 | |
187 | if (btrfs_disk_key_type(key) == BTRFS_DIR_ITEM_KEY) | 184 | btrfs_item_key_to_cpu(leaf, &key, nritems - 1); |
185 | if (key.type == BTRFS_DIR_ITEM_KEY) | ||
188 | return 1; | 186 | return 1; |
189 | if (nritems > 4) { | 187 | if (nritems > 4) { |
190 | key = &leaf->items[nritems/2].key; | 188 | btrfs_item_key_to_cpu(leaf, &key, nritems / 2); |
191 | if (btrfs_disk_key_type(key) == BTRFS_DIR_ITEM_KEY) | 189 | if (key.type == BTRFS_DIR_ITEM_KEY) |
192 | return 1; | 190 | return 1; |
193 | } | 191 | } |
194 | return 0; | 192 | return 0; |
195 | } | 193 | } |
196 | #endif | ||
197 | 194 | ||
198 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, | 195 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, |
199 | struct btrfs_root *root, struct extent_buffer *parent, | 196 | struct btrfs_root *root, struct extent_buffer *parent, |
200 | int cache_only, u64 *last_ret) | 197 | int cache_only, u64 *last_ret) |
201 | { | 198 | { |
202 | return 0; | 199 | struct extent_buffer *cur; |
203 | #if 0 | 200 | struct extent_buffer *tmp; |
204 | struct btrfs_node *parent_node; | ||
205 | struct extent_buffer *cur_eb; | ||
206 | struct extent_buffer *tmp_eb; | ||
207 | u64 blocknr; | 201 | u64 blocknr; |
208 | u64 search_start = *last_ret; | 202 | u64 search_start = *last_ret; |
209 | u64 last_block = 0; | 203 | u64 last_block = 0; |
@@ -214,6 +208,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
214 | int i; | 208 | int i; |
215 | int err = 0; | 209 | int err = 0; |
216 | int parent_level; | 210 | int parent_level; |
211 | int uptodate; | ||
212 | u32 blocksize; | ||
217 | 213 | ||
218 | if (trans->transaction != root->fs_info->running_transaction) { | 214 | if (trans->transaction != root->fs_info->running_transaction) { |
219 | printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid, | 215 | printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid, |
@@ -225,12 +221,12 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
225 | root->fs_info->generation); | 221 | root->fs_info->generation); |
226 | WARN_ON(1); | 222 | WARN_ON(1); |
227 | } | 223 | } |
228 | if (buffer_defrag_done(parent)) | 224 | if (btrfs_buffer_defrag_done(parent)) |
229 | return 0; | 225 | return 0; |
230 | 226 | ||
231 | parent_node = btrfs_buffer_node(parent); | 227 | parent_nritems = btrfs_header_nritems(parent); |
232 | parent_nritems = btrfs_header_nritems(&parent_node->header); | 228 | parent_level = btrfs_header_level(parent); |
233 | parent_level = btrfs_header_level(&parent_node->header); | 229 | blocksize = btrfs_level_size(root, parent_level - 1); |
234 | 230 | ||
235 | start_slot = 0; | 231 | start_slot = 0; |
236 | end_slot = parent_nritems; | 232 | end_slot = parent_nritems; |
@@ -240,56 +236,60 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
240 | 236 | ||
241 | for (i = start_slot; i < end_slot; i++) { | 237 | for (i = start_slot; i < end_slot; i++) { |
242 | int close = 1; | 238 | int close = 1; |
243 | blocknr = btrfs_node_blockptr(parent_node, i); | 239 | blocknr = btrfs_node_blockptr(parent, i); |
244 | if (last_block == 0) | 240 | if (last_block == 0) |
245 | last_block = blocknr; | 241 | last_block = blocknr; |
246 | if (i > 0) { | 242 | if (i > 0) { |
247 | other = btrfs_node_blockptr(parent_node, i - 1); | 243 | other = btrfs_node_blockptr(parent, i - 1); |
248 | close = close_blocks(blocknr, other); | 244 | close = close_blocks(blocknr, other, blocksize); |
249 | } | 245 | } |
250 | if (close && i < end_slot - 1) { | 246 | if (close && i < end_slot - 1) { |
251 | other = btrfs_node_blockptr(parent_node, i + 1); | 247 | other = btrfs_node_blockptr(parent, i + 1); |
252 | close = close_blocks(blocknr, other); | 248 | close = close_blocks(blocknr, other, blocksize); |
253 | } | 249 | } |
254 | if (close) { | 250 | if (close) { |
255 | last_block = blocknr; | 251 | last_block = blocknr; |
256 | continue; | 252 | continue; |
257 | } | 253 | } |
258 | 254 | ||
259 | cur_bh = btrfs_find_tree_block(root, blocknr); | 255 | cur = btrfs_find_tree_block(root, blocknr, blocksize); |
260 | if (!cur_bh || !buffer_uptodate(cur_bh) || | 256 | if (cur) |
261 | buffer_locked(cur_bh) || | 257 | uptodate = btrfs_buffer_uptodate(cur); |
262 | (parent_level != 1 && !buffer_defrag(cur_bh)) || | 258 | else |
263 | (parent_level == 1 && !should_defrag_leaf(cur_bh))) { | 259 | uptodate = 0; |
260 | if (!cur || !uptodate || | ||
261 | (parent_level != 1 && !btrfs_buffer_defrag(cur)) || | ||
262 | (parent_level == 1 && !should_defrag_leaf(cur))) { | ||
264 | if (cache_only) { | 263 | if (cache_only) { |
265 | brelse(cur_bh); | 264 | free_extent_buffer(cur); |
266 | continue; | 265 | continue; |
267 | } | 266 | } |
268 | if (!cur_bh || !buffer_uptodate(cur_bh) || | 267 | if (!cur) { |
269 | buffer_locked(cur_bh)) { | 268 | cur = read_tree_block(root, blocknr, |
270 | brelse(cur_bh); | 269 | blocksize); |
271 | cur_bh = read_tree_block(root, blocknr); | 270 | } else if (!uptodate) { |
271 | btrfs_read_buffer(cur); | ||
272 | } | 272 | } |
273 | } | 273 | } |
274 | if (search_start == 0) | 274 | if (search_start == 0) |
275 | search_start = last_block & ~((u64)65535); | 275 | search_start = last_block; |
276 | 276 | ||
277 | err = __btrfs_cow_block(trans, root, cur_bh, parent, i, | 277 | err = __btrfs_cow_block(trans, root, cur, parent, i, |
278 | &tmp_bh, search_start, | 278 | &tmp, search_start, |
279 | min(8, end_slot - i)); | 279 | min(16 * blocksize, |
280 | (end_slot - i) * blocksize)); | ||
280 | if (err) { | 281 | if (err) { |
281 | brelse(cur_bh); | 282 | free_extent_buffer(cur); |
282 | break; | 283 | break; |
283 | } | 284 | } |
284 | search_start = bh_blocknr(tmp_bh); | 285 | search_start = tmp->start; |
285 | *last_ret = search_start; | 286 | *last_ret = search_start; |
286 | if (parent_level == 1) | 287 | if (parent_level == 1) |
287 | clear_buffer_defrag(tmp_bh); | 288 | btrfs_clear_buffer_defrag(tmp); |
288 | set_buffer_defrag_done(tmp_bh); | 289 | btrfs_set_buffer_defrag_done(tmp); |
289 | brelse(tmp_bh); | 290 | free_extent_buffer(tmp); |
290 | } | 291 | } |
291 | return err; | 292 | return err; |
292 | #endif | ||
293 | } | 293 | } |
294 | 294 | ||
295 | /* | 295 | /* |
@@ -892,22 +892,17 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
892 | static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, | 892 | static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, |
893 | int level, int slot) | 893 | int level, int slot) |
894 | { | 894 | { |
895 | return; | ||
896 | #if 0 | ||
897 | struct extent_buffer *node; | 895 | struct extent_buffer *node; |
898 | int i; | ||
899 | u32 nritems; | 896 | u32 nritems; |
900 | u64 bytenr; | ||
901 | u64 search; | 897 | u64 search; |
902 | u64 cluster_start; | 898 | u64 lowest_read; |
903 | int ret; | 899 | u64 highest_read; |
904 | int nread = 0; | 900 | u64 nread = 0; |
905 | int direction = path->reada; | 901 | int direction = path->reada; |
906 | int level; | ||
907 | struct radix_tree_root found; | ||
908 | unsigned long gang[8]; | ||
909 | struct extent_buffer *eb; | 902 | struct extent_buffer *eb; |
910 | 903 | u32 nr; | |
904 | u32 blocksize; | ||
905 | u32 nscan = 0; | ||
911 | 906 | ||
912 | if (level == 0) | 907 | if (level == 0) |
913 | return; | 908 | return; |
@@ -917,42 +912,46 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, | |||
917 | 912 | ||
918 | node = path->nodes[level]; | 913 | node = path->nodes[level]; |
919 | search = btrfs_node_blockptr(node, slot); | 914 | search = btrfs_node_blockptr(node, slot); |
920 | eb = btrfs_find_tree_block(root, search); | 915 | blocksize = btrfs_level_size(root, level - 1); |
916 | eb = btrfs_find_tree_block(root, search, blocksize); | ||
921 | if (eb) { | 917 | if (eb) { |
922 | free_extent_buffer(eb); | 918 | free_extent_buffer(eb); |
923 | return; | 919 | return; |
924 | } | 920 | } |
925 | 921 | ||
926 | init_bit_radix(&found); | 922 | highest_read = search; |
923 | lowest_read = search; | ||
924 | |||
927 | nritems = btrfs_header_nritems(node); | 925 | nritems = btrfs_header_nritems(node); |
928 | level = btrfs_header_level(node) - 1; | 926 | nr = slot; |
929 | for (i = slot; i < nritems; i++) { | ||
930 | bytenr = btrfs_node_blockptr(node, i); | ||
931 | set_radix_bit(&found, blocknr); | ||
932 | } | ||
933 | if (direction > 0) { | ||
934 | cluster_start = search - 4; | ||
935 | if (cluster_start > search) | ||
936 | cluster_start = 0; | ||
937 | } else | ||
938 | cluster_start = search + 4; | ||
939 | while(1) { | 927 | while(1) { |
940 | ret = find_first_radix_bit(&found, gang, 0, ARRAY_SIZE(gang)); | 928 | if (direction < 0) { |
941 | if (!ret) | 929 | if (nr == 0) |
942 | break; | 930 | break; |
943 | for (i = 0; i < ret; i++) { | 931 | nr--; |
944 | blocknr = gang[i]; | 932 | } else if (direction > 0) { |
945 | clear_radix_bit(&found, blocknr); | 933 | nr++; |
946 | if (path->reada == 1 && nread > 16) | 934 | if (nr >= nritems) |
947 | continue; | 935 | break; |
948 | if (close_blocks(cluster_start, blocknr)) { | ||
949 | readahead_tree_block(root, blocknr); | ||
950 | nread++; | ||
951 | cluster_start = blocknr; | ||
952 | } | ||
953 | } | 936 | } |
937 | search = btrfs_node_blockptr(node, nr); | ||
938 | if ((search >= lowest_read && search <= highest_read) || | ||
939 | (search < lowest_read && lowest_read - search <= 32768) || | ||
940 | (search > highest_read && search - highest_read <= 32768)) { | ||
941 | readahead_tree_block(root, search, blocksize); | ||
942 | nread += blocksize; | ||
943 | } | ||
944 | nscan++; | ||
945 | if (path->reada < 2 && (nread > (256 * 1024) || nscan > 32)) | ||
946 | break; | ||
947 | if(nread > (1024 * 1024) || nscan > 128) | ||
948 | break; | ||
949 | |||
950 | if (search < lowest_read) | ||
951 | lowest_read = search; | ||
952 | if (search > highest_read) | ||
953 | highest_read = search; | ||
954 | } | 954 | } |
955 | #endif | ||
956 | } | 955 | } |
957 | /* | 956 | /* |
958 | * look for key in the tree. path is filled in with nodes along the way | 957 | * look for key in the tree. path is filled in with nodes along the way |