2 * Copyright (C) 2015 Facebook. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
21 #include "free-space-cache.h"
22 #include "free-space-tree.h"
23 #include "transaction.h"
25 static struct btrfs_free_space_info
*
26 search_free_space_info(struct btrfs_trans_handle
*trans
,
27 struct btrfs_fs_info
*fs_info
,
28 struct btrfs_block_group_cache
*block_group
,
29 struct btrfs_path
*path
, int cow
)
31 struct btrfs_root
*root
= fs_info
->free_space_root
;
35 key
.objectid
= block_group
->key
.objectid
;
36 key
.type
= BTRFS_FREE_SPACE_INFO_KEY
;
37 key
.offset
= block_group
->key
.offset
;
39 ret
= btrfs_search_slot(trans
, root
, &key
, path
, 0, cow
);
43 return ERR_PTR(-ENOENT
);
45 return btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
46 struct btrfs_free_space_info
);
49 static int free_space_test_bit(struct btrfs_block_group_cache
*block_group
,
50 struct btrfs_path
*path
, u64 offset
,
53 struct extent_buffer
*leaf
;
55 u64 found_start
, found_end
;
58 leaf
= path
->nodes
[0];
59 btrfs_item_key_to_cpu(leaf
, &key
, path
->slots
[0]);
60 ASSERT(key
.type
== BTRFS_FREE_SPACE_BITMAP_KEY
);
62 found_start
= key
.objectid
;
63 found_end
= key
.objectid
+ key
.offset
;
64 ASSERT(offset
>= found_start
&& offset
< found_end
);
66 ptr
= btrfs_item_ptr_offset(leaf
, path
->slots
[0]);
67 i
= (offset
- found_start
) / sectorsize
;
68 return !!extent_buffer_test_bit(leaf
, ptr
, i
);
71 static int clear_free_space_tree(struct btrfs_trans_handle
*trans
,
72 struct btrfs_root
*root
)
74 struct btrfs_path
*path
;
79 path
= btrfs_alloc_path();
88 ret
= btrfs_search_slot(trans
, root
, &key
, path
, -1, 1);
92 nr
= btrfs_header_nritems(path
->nodes
[0]);
97 ret
= btrfs_del_items(trans
, root
, path
, 0, nr
);
101 btrfs_release_path(path
);
106 btrfs_free_path(path
);
110 int btrfs_clear_free_space_tree(struct btrfs_fs_info
*fs_info
)
112 struct btrfs_trans_handle
*trans
;
113 struct btrfs_root
*tree_root
= fs_info
->tree_root
;
114 struct btrfs_root
*free_space_root
= fs_info
->free_space_root
;
118 trans
= btrfs_start_transaction(tree_root
, 0);
120 return PTR_ERR(trans
);
122 features
= btrfs_super_compat_ro_flags(fs_info
->super_copy
);
123 features
&= ~(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID
|
124 BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE
);
125 btrfs_set_super_compat_ro_flags(fs_info
->super_copy
, features
);
126 fs_info
->free_space_root
= NULL
;
128 ret
= clear_free_space_tree(trans
, free_space_root
);
132 ret
= btrfs_del_root(trans
, tree_root
, &free_space_root
->root_key
);
136 list_del(&free_space_root
->dirty_list
);
138 ret
= clean_tree_block(free_space_root
->node
);
141 ret
= btrfs_free_tree_block(trans
, free_space_root
,
142 free_space_root
->node
, 0, 1);
146 free_extent_buffer(free_space_root
->node
);
147 free_extent_buffer(free_space_root
->commit_root
);
148 kfree(free_space_root
);
150 ret
= btrfs_commit_transaction(trans
, tree_root
);
156 static int load_free_space_bitmaps(struct btrfs_fs_info
*fs_info
,
157 struct btrfs_block_group_cache
*block_group
,
158 struct btrfs_path
*path
,
159 u32 expected_extent_count
,
162 struct btrfs_root
*root
= fs_info
->free_space_root
;
163 struct btrfs_key key
;
164 int prev_bit
= 0, bit
;
165 u64 extent_start
= 0;
166 u64 start
, end
, offset
;
167 u32 extent_count
= 0;
170 start
= block_group
->key
.objectid
;
171 end
= block_group
->key
.objectid
+ block_group
->key
.offset
;
174 ret
= btrfs_next_item(root
, path
);
180 btrfs_item_key_to_cpu(path
->nodes
[0], &key
, path
->slots
[0]);
182 if (key
.type
== BTRFS_FREE_SPACE_INFO_KEY
)
185 if (key
.type
!= BTRFS_FREE_SPACE_BITMAP_KEY
) {
186 fprintf(stderr
, "unexpected key of type %u\n", key
.type
);
190 if (key
.objectid
>= end
) {
192 "free space bitmap starts at %llu, beyond end of block group %llu-%llu\n",
193 key
.objectid
, start
, end
);
197 if (key
.objectid
+ key
.offset
> end
) {
199 "free space bitmap ends at %llu, beyond end of block group %llu-%llu\n",
200 key
.objectid
, start
, end
);
205 offset
= key
.objectid
;
206 while (offset
< key
.objectid
+ key
.offset
) {
207 bit
= free_space_test_bit(block_group
, path
, offset
,
208 fs_info
->sectorsize
);
209 if (prev_bit
== 0 && bit
== 1) {
210 extent_start
= offset
;
211 } else if (prev_bit
== 1 && bit
== 0) {
212 add_new_free_space(block_group
, fs_info
, extent_start
, offset
);
216 offset
+= fs_info
->sectorsize
;
221 add_new_free_space(block_group
, fs_info
, extent_start
, end
);
225 if (extent_count
!= expected_extent_count
) {
226 fprintf(stderr
, "free space info recorded %u extents, counted %u\n",
227 expected_extent_count
, extent_count
);
236 static int load_free_space_extents(struct btrfs_fs_info
*fs_info
,
237 struct btrfs_block_group_cache
*block_group
,
238 struct btrfs_path
*path
,
239 u32 expected_extent_count
,
242 struct btrfs_root
*root
= fs_info
->free_space_root
;
243 struct btrfs_key key
, prev_key
;
246 u32 extent_count
= 0;
249 start
= block_group
->key
.objectid
;
250 end
= block_group
->key
.objectid
+ block_group
->key
.offset
;
253 ret
= btrfs_next_item(root
, path
);
259 btrfs_item_key_to_cpu(path
->nodes
[0], &key
, path
->slots
[0]);
261 if (key
.type
== BTRFS_FREE_SPACE_INFO_KEY
)
264 if (key
.type
!= BTRFS_FREE_SPACE_EXTENT_KEY
) {
265 fprintf(stderr
, "unexpected key of type %u\n", key
.type
);
269 if (key
.objectid
>= end
) {
271 "free space extent starts at %llu, beyond end of block group %llu-%llu\n",
272 key
.objectid
, start
, end
);
276 if (key
.objectid
+ key
.offset
> end
) {
278 "free space extent ends at %llu, beyond end of block group %llu-%llu\n",
279 key
.objectid
+ key
.offset
, start
, end
);
285 u64 cur_start
= key
.objectid
;
286 u64 cur_end
= cur_start
+ key
.offset
;
287 u64 prev_start
= prev_key
.objectid
;
288 u64 prev_end
= prev_start
+ prev_key
.offset
;
290 if (cur_start
< prev_end
) {
292 "free space extent %llu-%llu overlaps with previous %llu-%llu\n",
294 prev_start
, prev_end
);
296 } else if (cur_start
== prev_end
) {
298 "free space extent %llu-%llu is unmerged with previous %llu-%llu\n",
300 prev_start
, prev_end
);
305 add_new_free_space(block_group
, fs_info
, key
.objectid
, key
.objectid
+ key
.offset
);
312 if (extent_count
!= expected_extent_count
) {
313 fprintf(stderr
, "free space info recorded %u extents, counted %u\n",
314 expected_extent_count
, extent_count
);
323 int load_free_space_tree(struct btrfs_fs_info
*fs_info
,
324 struct btrfs_block_group_cache
*block_group
)
326 struct btrfs_free_space_info
*info
;
327 struct btrfs_path
*path
;
328 u32 extent_count
, flags
;
332 path
= btrfs_alloc_path();
337 info
= search_free_space_info(NULL
, fs_info
, block_group
, path
, 0);
342 extent_count
= btrfs_free_space_extent_count(path
->nodes
[0], info
);
343 flags
= btrfs_free_space_flags(path
->nodes
[0], info
);
345 if (flags
& BTRFS_FREE_SPACE_USING_BITMAPS
) {
346 ret
= load_free_space_bitmaps(fs_info
, block_group
, path
,
347 extent_count
, &errors
);
349 ret
= load_free_space_extents(fs_info
, block_group
, path
,
350 extent_count
, &errors
);
357 btrfs_free_path(path
);
358 return ret
? ret
: errors
;