diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-01-29 15:55:23 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:00 -0400 |
commit | 291d673e6a22d9c6834e939f66c7cfef90669021 (patch) | |
tree | 841e9be40bb5fbf7c978c789ee67183cef596686 /fs/btrfs | |
parent | 9c58309d6cf22471dacbcb6de54d00cef9ca20d4 (diff) |
Btrfs: Do delalloc accounting via hooks in the extent_state code
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 6 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 25 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 4 | ||||
-rw-r--r-- | fs/btrfs/file.c | 4 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 60 |
5 files changed, 53 insertions, 46 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c4fe37791d3f..90718f77bbc0 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2180,7 +2180,6 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start, | |||
2180 | unsigned long last_index; | 2180 | unsigned long last_index; |
2181 | unsigned long i; | 2181 | unsigned long i; |
2182 | struct page *page; | 2182 | struct page *page; |
2183 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
2184 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 2183 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
2185 | struct file_ra_state *ra; | 2184 | struct file_ra_state *ra; |
2186 | 2185 | ||
@@ -2220,11 +2219,6 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start, | |||
2220 | set_extent_delalloc(io_tree, page_start, | 2219 | set_extent_delalloc(io_tree, page_start, |
2221 | page_end, GFP_NOFS); | 2220 | page_end, GFP_NOFS); |
2222 | 2221 | ||
2223 | spin_lock(&root->fs_info->delalloc_lock); | ||
2224 | root->fs_info->delalloc_bytes += PAGE_CACHE_SIZE - | ||
2225 | existing_delalloc; | ||
2226 | spin_unlock(&root->fs_info->delalloc_lock); | ||
2227 | |||
2228 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); | 2222 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); |
2229 | set_page_dirty(page); | 2223 | set_page_dirty(page); |
2230 | unlock_page(page); | 2224 | unlock_page(page); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8aec72253a17..e81b35b06187 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -256,6 +256,26 @@ static int merge_state(struct extent_io_tree *tree, | |||
256 | return 0; | 256 | return 0; |
257 | } | 257 | } |
258 | 258 | ||
259 | static void set_state_cb(struct extent_io_tree *tree, | ||
260 | struct extent_state *state, | ||
261 | unsigned long bits) | ||
262 | { | ||
263 | if (tree->ops && tree->ops->set_bit_hook) { | ||
264 | tree->ops->set_bit_hook(tree->mapping->host, state->start, | ||
265 | state->end, bits); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | static void clear_state_cb(struct extent_io_tree *tree, | ||
270 | struct extent_state *state, | ||
271 | unsigned long bits) | ||
272 | { | ||
273 | if (tree->ops && tree->ops->set_bit_hook) { | ||
274 | tree->ops->clear_bit_hook(tree->mapping->host, state->start, | ||
275 | state->end, bits); | ||
276 | } | ||
277 | } | ||
278 | |||
259 | /* | 279 | /* |
260 | * insert an extent_state struct into the tree. 'bits' are set on the | 280 | * insert an extent_state struct into the tree. 'bits' are set on the |
261 | * struct before it is inserted. | 281 | * struct before it is inserted. |
@@ -281,6 +301,7 @@ static int insert_state(struct extent_io_tree *tree, | |||
281 | state->state |= bits; | 301 | state->state |= bits; |
282 | state->start = start; | 302 | state->start = start; |
283 | state->end = end; | 303 | state->end = end; |
304 | set_state_cb(tree, state, bits); | ||
284 | node = tree_insert(&tree->state, end, &state->rb_node); | 305 | node = tree_insert(&tree->state, end, &state->rb_node); |
285 | if (node) { | 306 | if (node) { |
286 | struct extent_state *found; | 307 | struct extent_state *found; |
@@ -349,6 +370,7 @@ static int clear_state_bit(struct extent_io_tree *tree, | |||
349 | tree->dirty_bytes -= range; | 370 | tree->dirty_bytes -= range; |
350 | } | 371 | } |
351 | state->state &= ~bits; | 372 | state->state &= ~bits; |
373 | clear_state_cb(tree, state, bits); | ||
352 | if (wake) | 374 | if (wake) |
353 | wake_up(&state->wq); | 375 | wake_up(&state->wq); |
354 | if (delete || state->state == 0) { | 376 | if (delete || state->state == 0) { |
@@ -553,6 +575,7 @@ static void set_state_bits(struct extent_io_tree *tree, | |||
553 | tree->dirty_bytes += range; | 575 | tree->dirty_bytes += range; |
554 | } | 576 | } |
555 | state->state |= bits; | 577 | state->state |= bits; |
578 | set_state_cb(tree, state, bits); | ||
556 | } | 579 | } |
557 | 580 | ||
558 | /* | 581 | /* |
@@ -975,6 +998,7 @@ search_again: | |||
975 | goto search_again; | 998 | goto search_again; |
976 | } | 999 | } |
977 | state->state |= EXTENT_LOCKED; | 1000 | state->state |= EXTENT_LOCKED; |
1001 | set_state_cb(tree, state, EXTENT_LOCKED); | ||
978 | if (!found) | 1002 | if (!found) |
979 | *start = state->start; | 1003 | *start = state->start; |
980 | found++; | 1004 | found++; |
@@ -1474,6 +1498,7 @@ static int end_bio_extent_readpage(struct bio *bio, | |||
1474 | state = NULL; | 1498 | state = NULL; |
1475 | } | 1499 | } |
1476 | clear->state |= EXTENT_UPTODATE; | 1500 | clear->state |= EXTENT_UPTODATE; |
1501 | set_state_cb(tree, clear, EXTENT_UPTODATE); | ||
1477 | clear_state_bit(tree, clear, EXTENT_LOCKED, | 1502 | clear_state_bit(tree, clear, EXTENT_LOCKED, |
1478 | 1, 0); | 1503 | 1, 0); |
1479 | if (cur == start) | 1504 | if (cur == start) |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index f1e8bf251f32..a96c5a14134e 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -33,6 +33,10 @@ struct extent_io_ops { | |||
33 | struct extent_state *state); | 33 | struct extent_state *state); |
34 | void (*writepage_end_io_hook)(struct page *page, u64 start, u64 end, | 34 | void (*writepage_end_io_hook)(struct page *page, u64 start, u64 end, |
35 | struct extent_state *state); | 35 | struct extent_state *state); |
36 | int (*set_bit_hook)(struct inode *inode, u64 start, u64 end, | ||
37 | unsigned long bits); | ||
38 | int (*clear_bit_hook)(struct inode *inode, u64 start, u64 end, | ||
39 | unsigned long bits); | ||
36 | }; | 40 | }; |
37 | 41 | ||
38 | struct extent_io_tree { | 42 | struct extent_io_tree { |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index c5bb00f92396..8e210616d702 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -323,10 +323,6 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
323 | } | 323 | } |
324 | set_extent_delalloc(io_tree, start_pos, end_of_last_block, | 324 | set_extent_delalloc(io_tree, start_pos, end_of_last_block, |
325 | GFP_NOFS); | 325 | GFP_NOFS); |
326 | spin_lock(&root->fs_info->delalloc_lock); | ||
327 | root->fs_info->delalloc_bytes += (end_of_last_block + 1 - | ||
328 | start_pos) - existing_delalloc; | ||
329 | spin_unlock(&root->fs_info->delalloc_lock); | ||
330 | btrfs_add_ordered_inode(inode); | 326 | btrfs_add_ordered_inode(inode); |
331 | } else { | 327 | } else { |
332 | u64 aligned_end; | 328 | u64 aligned_end; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 413b1012de53..5a38443a24ee 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -80,8 +80,6 @@ int btrfs_check_free_space(struct btrfs_root *root, u64 num_required, | |||
80 | u64 thresh; | 80 | u64 thresh; |
81 | int ret = 0; | 81 | int ret = 0; |
82 | 82 | ||
83 | return 0; | ||
84 | |||
85 | if (for_del) | 83 | if (for_del) |
86 | thresh = total * 90; | 84 | thresh = total * 90; |
87 | else | 85 | else |
@@ -249,7 +247,6 @@ not_found: | |||
249 | static int run_delalloc_range(struct inode *inode, u64 start, u64 end) | 247 | static int run_delalloc_range(struct inode *inode, u64 start, u64 end) |
250 | { | 248 | { |
251 | struct btrfs_root *root = BTRFS_I(inode)->root; | 249 | struct btrfs_root *root = BTRFS_I(inode)->root; |
252 | u64 num_bytes; | ||
253 | int ret; | 250 | int ret; |
254 | mutex_lock(&root->fs_info->fs_mutex); | 251 | mutex_lock(&root->fs_info->fs_mutex); |
255 | if (btrfs_test_opt(root, NODATACOW) || | 252 | if (btrfs_test_opt(root, NODATACOW) || |
@@ -258,20 +255,34 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end) | |||
258 | else | 255 | else |
259 | ret = cow_file_range(inode, start, end); | 256 | ret = cow_file_range(inode, start, end); |
260 | 257 | ||
261 | spin_lock(&root->fs_info->delalloc_lock); | ||
262 | num_bytes = end + 1 - start; | ||
263 | if (root->fs_info->delalloc_bytes < num_bytes) { | ||
264 | printk("delalloc accounting error total %llu sub %llu\n", | ||
265 | root->fs_info->delalloc_bytes, num_bytes); | ||
266 | } else { | ||
267 | root->fs_info->delalloc_bytes -= num_bytes; | ||
268 | } | ||
269 | spin_unlock(&root->fs_info->delalloc_lock); | ||
270 | |||
271 | mutex_unlock(&root->fs_info->fs_mutex); | 258 | mutex_unlock(&root->fs_info->fs_mutex); |
272 | return ret; | 259 | return ret; |
273 | } | 260 | } |
274 | 261 | ||
262 | int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end, | ||
263 | unsigned long bits) | ||
264 | { | ||
265 | if ((bits & EXTENT_DELALLOC)) { | ||
266 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
267 | spin_lock(&root->fs_info->delalloc_lock); | ||
268 | root->fs_info->delalloc_bytes += end - start + 1; | ||
269 | spin_unlock(&root->fs_info->delalloc_lock); | ||
270 | } | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end, | ||
275 | unsigned long bits) | ||
276 | { | ||
277 | if ((bits & EXTENT_DELALLOC)) { | ||
278 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
279 | spin_lock(&root->fs_info->delalloc_lock); | ||
280 | root->fs_info->delalloc_bytes -= end - start + 1; | ||
281 | spin_unlock(&root->fs_info->delalloc_lock); | ||
282 | } | ||
283 | return 0; | ||
284 | } | ||
285 | |||
275 | int btrfs_writepage_io_hook(struct page *page, u64 start, u64 end) | 286 | int btrfs_writepage_io_hook(struct page *page, u64 start, u64 end) |
276 | { | 287 | { |
277 | struct inode *inode = page->mapping->host; | 288 | struct inode *inode = page->mapping->host; |
@@ -908,28 +919,17 @@ static int btrfs_cow_one_page(struct inode *inode, struct page *page, | |||
908 | { | 919 | { |
909 | char *kaddr; | 920 | char *kaddr; |
910 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 921 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
911 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
912 | u64 page_start = (u64)page->index << PAGE_CACHE_SHIFT; | 922 | u64 page_start = (u64)page->index << PAGE_CACHE_SHIFT; |
913 | u64 page_end = page_start + PAGE_CACHE_SIZE - 1; | 923 | u64 page_end = page_start + PAGE_CACHE_SIZE - 1; |
914 | u64 existing_delalloc; | ||
915 | u64 delalloc_start; | ||
916 | int ret = 0; | 924 | int ret = 0; |
917 | 925 | ||
918 | WARN_ON(!PageLocked(page)); | 926 | WARN_ON(!PageLocked(page)); |
919 | set_page_extent_mapped(page); | 927 | set_page_extent_mapped(page); |
920 | 928 | ||
921 | lock_extent(io_tree, page_start, page_end, GFP_NOFS); | 929 | lock_extent(io_tree, page_start, page_end, GFP_NOFS); |
922 | delalloc_start = page_start; | ||
923 | existing_delalloc = count_range_bits(&BTRFS_I(inode)->io_tree, | ||
924 | &delalloc_start, page_end, | ||
925 | PAGE_CACHE_SIZE, EXTENT_DELALLOC); | ||
926 | set_extent_delalloc(&BTRFS_I(inode)->io_tree, page_start, | 930 | set_extent_delalloc(&BTRFS_I(inode)->io_tree, page_start, |
927 | page_end, GFP_NOFS); | 931 | page_end, GFP_NOFS); |
928 | 932 | ||
929 | spin_lock(&root->fs_info->delalloc_lock); | ||
930 | root->fs_info->delalloc_bytes += PAGE_CACHE_SIZE - existing_delalloc; | ||
931 | spin_unlock(&root->fs_info->delalloc_lock); | ||
932 | |||
933 | if (zero_start != PAGE_CACHE_SIZE) { | 933 | if (zero_start != PAGE_CACHE_SIZE) { |
934 | kaddr = kmap(page); | 934 | kaddr = kmap(page); |
935 | memset(kaddr + zero_start, 0, PAGE_CACHE_SIZE - zero_start); | 935 | memset(kaddr + zero_start, 0, PAGE_CACHE_SIZE - zero_start); |
@@ -2456,8 +2456,6 @@ int btrfs_defrag_file(struct file *file) { | |||
2456 | unsigned long ra_index = 0; | 2456 | unsigned long ra_index = 0; |
2457 | u64 page_start; | 2457 | u64 page_start; |
2458 | u64 page_end; | 2458 | u64 page_end; |
2459 | u64 delalloc_start; | ||
2460 | u64 existing_delalloc; | ||
2461 | unsigned long i; | 2459 | unsigned long i; |
2462 | int ret; | 2460 | int ret; |
2463 | 2461 | ||
@@ -2491,19 +2489,9 @@ int btrfs_defrag_file(struct file *file) { | |||
2491 | page_end = page_start + PAGE_CACHE_SIZE - 1; | 2489 | page_end = page_start + PAGE_CACHE_SIZE - 1; |
2492 | 2490 | ||
2493 | lock_extent(io_tree, page_start, page_end, GFP_NOFS); | 2491 | lock_extent(io_tree, page_start, page_end, GFP_NOFS); |
2494 | delalloc_start = page_start; | ||
2495 | existing_delalloc = | ||
2496 | count_range_bits(&BTRFS_I(inode)->io_tree, | ||
2497 | &delalloc_start, page_end, | ||
2498 | PAGE_CACHE_SIZE, EXTENT_DELALLOC); | ||
2499 | set_extent_delalloc(io_tree, page_start, | 2492 | set_extent_delalloc(io_tree, page_start, |
2500 | page_end, GFP_NOFS); | 2493 | page_end, GFP_NOFS); |
2501 | 2494 | ||
2502 | spin_lock(&root->fs_info->delalloc_lock); | ||
2503 | root->fs_info->delalloc_bytes += PAGE_CACHE_SIZE - | ||
2504 | existing_delalloc; | ||
2505 | spin_unlock(&root->fs_info->delalloc_lock); | ||
2506 | |||
2507 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); | 2495 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); |
2508 | set_page_dirty(page); | 2496 | set_page_dirty(page); |
2509 | unlock_page(page); | 2497 | unlock_page(page); |