Commit 0591fb56 authored by Chris Mason's avatar Chris Mason

Btrfs: Fix extent bit range testing

It could return the bit as set when there was actually a hole at the
very end of the range.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 3ab2fb5a
...@@ -96,7 +96,7 @@ void extent_map_tree_empty_lru(struct extent_map_tree *tree) ...@@ -96,7 +96,7 @@ void extent_map_tree_empty_lru(struct extent_map_tree *tree)
while(!list_empty(&tree->buffer_lru)) { while(!list_empty(&tree->buffer_lru)) {
eb = list_entry(tree->buffer_lru.next, struct extent_buffer, eb = list_entry(tree->buffer_lru.next, struct extent_buffer,
lru); lru);
list_del(&eb->lru); list_del_init(&eb->lru);
free_extent_buffer(eb); free_extent_buffer(eb);
} }
} }
...@@ -1212,13 +1212,15 @@ int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end, ...@@ -1212,13 +1212,15 @@ int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end,
node = tree_search(&tree->state, start); node = tree_search(&tree->state, start);
while (node && start <= end) { while (node && start <= end) {
state = rb_entry(node, struct extent_state, rb_node); state = rb_entry(node, struct extent_state, rb_node);
if (state->start > end)
break;
if (filled && state->start > start) { if (filled && state->start > start) {
bitset = 0; bitset = 0;
break; break;
} }
if (state->start > end)
break;
if (state->state & bits) { if (state->state & bits) {
bitset = 1; bitset = 1;
if (!filled) if (!filled)
...@@ -2208,6 +2210,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree, ...@@ -2208,6 +2210,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
page_cache_get(page0); page_cache_get(page0);
mark_page_accessed(page0); mark_page_accessed(page0);
set_page_extent_mapped(page0); set_page_extent_mapped(page0);
WARN_ON(!PageUptodate(page0));
set_page_private(page0, EXTENT_PAGE_PRIVATE_FIRST_PAGE | set_page_private(page0, EXTENT_PAGE_PRIVATE_FIRST_PAGE |
len << 2); len << 2);
} else { } else {
...@@ -2248,9 +2251,11 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree, ...@@ -2248,9 +2251,11 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
spin_unlock(&tree->lru_lock); spin_unlock(&tree->lru_lock);
if (!atomic_dec_and_test(&eb->refs)) if (!atomic_dec_and_test(&eb->refs))
return NULL; return NULL;
for (index = 0; index < i; index++) { for (index = 1; index < i; index++) {
page_cache_release(extent_buffer_page(eb, index)); page_cache_release(extent_buffer_page(eb, index));
} }
if (i > 0)
page_cache_release(extent_buffer_page(eb, 0));
__free_extent_buffer(eb); __free_extent_buffer(eb);
return NULL; return NULL;
} }
...@@ -2310,9 +2315,11 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree, ...@@ -2310,9 +2315,11 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
spin_unlock(&tree->lru_lock); spin_unlock(&tree->lru_lock);
if (!atomic_dec_and_test(&eb->refs)) if (!atomic_dec_and_test(&eb->refs))
return NULL; return NULL;
for (index = 0; index < i; index++) { for (index = 1; index < i; index++) {
page_cache_release(extent_buffer_page(eb, index)); page_cache_release(extent_buffer_page(eb, index));
} }
if (i > 0)
page_cache_release(extent_buffer_page(eb, 0));
__free_extent_buffer(eb); __free_extent_buffer(eb);
return NULL; return NULL;
} }
...@@ -2329,11 +2336,13 @@ void free_extent_buffer(struct extent_buffer *eb) ...@@ -2329,11 +2336,13 @@ void free_extent_buffer(struct extent_buffer *eb)
if (!atomic_dec_and_test(&eb->refs)) if (!atomic_dec_and_test(&eb->refs))
return; return;
WARN_ON(!list_empty(&eb->lru));
num_pages = num_extent_pages(eb->start, eb->len); num_pages = num_extent_pages(eb->start, eb->len);
for (i = 0; i < num_pages; i++) { for (i = 1; i < num_pages; i++) {
page_cache_release(extent_buffer_page(eb, i)); page_cache_release(extent_buffer_page(eb, i));
} }
page_cache_release(extent_buffer_page(eb, 0));
__free_extent_buffer(eb); __free_extent_buffer(eb);
} }
EXPORT_SYMBOL(free_extent_buffer); EXPORT_SYMBOL(free_extent_buffer);
...@@ -2469,6 +2478,7 @@ int read_extent_buffer_pages(struct extent_map_tree *tree, ...@@ -2469,6 +2478,7 @@ int read_extent_buffer_pages(struct extent_map_tree *tree,
EXTENT_UPTODATE, 1)) { EXTENT_UPTODATE, 1)) {
return 0; return 0;
} }
if (start) { if (start) {
WARN_ON(start < eb->start); WARN_ON(start < eb->start);
start_i = (start >> PAGE_CACHE_SHIFT) - start_i = (start >> PAGE_CACHE_SHIFT) -
...@@ -2577,7 +2587,7 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, ...@@ -2577,7 +2587,7 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
*map_start = 0; *map_start = 0;
} else { } else {
offset = 0; offset = 0;
*map_start = (i << PAGE_CACHE_SHIFT) - start_offset; *map_start = ((u64)i << PAGE_CACHE_SHIFT) - start_offset;
} }
if (start + min_len > eb->len) { if (start + min_len > eb->len) {
printk("bad mapping eb start %Lu len %lu, wanted %lu %lu\n", eb->start, eb->len, start, min_len); printk("bad mapping eb start %Lu len %lu, wanted %lu %lu\n", eb->start, eb->len, start, min_len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment