aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-09 16:28:12 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commit728131d8e40c2a47c59ca91a806299c4708029f9 (patch)
tree4b6023689d6f77fdf785d815a2ca986e73aeff1a /fs
parentcea9e4452ebaf18dd0951e90dc84d82a5dee40b2 (diff)
Btrfs: Add additional debugging for metadata checksum failures
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/disk-io.c3
-rw-r--r--fs/btrfs/extent_io.c54
-rw-r--r--fs/btrfs/extent_io.h2
3 files changed, 55 insertions, 4 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index bc5bd5abb28a..e444b99e02da 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -283,6 +283,7 @@ static int btree_releasepage(struct page *page, gfp_t gfp_flags)
283 map = &BTRFS_I(page->mapping->host)->extent_tree; 283 map = &BTRFS_I(page->mapping->host)->extent_tree;
284 ret = try_release_extent_mapping(map, tree, page, gfp_flags); 284 ret = try_release_extent_mapping(map, tree, page, gfp_flags);
285 if (ret == 1) { 285 if (ret == 1) {
286 invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE);
286 ClearPagePrivate(page); 287 ClearPagePrivate(page);
287 set_page_private(page, 0); 288 set_page_private(page, 0);
288 page_cache_release(page); 289 page_cache_release(page);
@@ -376,7 +377,6 @@ int btrfs_verify_block_csum(struct btrfs_root *root,
376 buf->flags |= EXTENT_CSUM; 377 buf->flags |= EXTENT_CSUM;
377 return 0; 378 return 0;
378 } 379 }
379
380 lock_extent(io_tree, buf->start, end, GFP_NOFS); 380 lock_extent(io_tree, buf->start, end, GFP_NOFS);
381 381
382 if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) { 382 if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) {
@@ -384,6 +384,7 @@ int btrfs_verify_block_csum(struct btrfs_root *root,
384 ret = 0; 384 ret = 0;
385 goto out_unlock; 385 goto out_unlock;
386 } 386 }
387WARN_ON(buf->flags & EXTENT_CSUM);
387 388
388 ret = csum_tree_block(root, buf, 1); 389 ret = csum_tree_block(root, buf, 1);
389 set_extent_bits(io_tree, buf->start, end, EXTENT_CSUM, GFP_NOFS); 390 set_extent_bits(io_tree, buf->start, end, EXTENT_CSUM, GFP_NOFS);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 776c33f1e6fe..13cc2360e375 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2592,6 +2592,33 @@ static inline struct page *extent_buffer_page(struct extent_buffer *eb,
2592 return p; 2592 return p;
2593} 2593}
2594 2594
2595int invalidate_extent_lru(struct extent_io_tree *tree, u64 start,
2596 unsigned long len)
2597{
2598 struct list_head *lru = &tree->buffer_lru;
2599 struct list_head *cur = lru->next;
2600 struct extent_buffer *eb;
2601 int found = 0;
2602
2603 spin_lock(&tree->lru_lock);
2604 if (list_empty(lru))
2605 goto out;
2606
2607 do {
2608 eb = list_entry(cur, struct extent_buffer, lru);
2609 if (eb->start <= start && eb->start + eb->len > start) {
2610 eb->flags &= ~EXTENT_UPTODATE;
2611 }
2612 if (eb->start == start) {
2613 eb->flags &= ~EXTENT_CSUM;
2614 }
2615 cur = cur->next;
2616 } while (cur != lru);
2617out:
2618 spin_unlock(&tree->lru_lock);
2619 return found;
2620}
2621
2595static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, 2622static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
2596 u64 start, 2623 u64 start,
2597 unsigned long len, 2624 unsigned long len,
@@ -2909,10 +2936,32 @@ EXPORT_SYMBOL(set_extent_buffer_uptodate);
2909int extent_buffer_uptodate(struct extent_io_tree *tree, 2936int extent_buffer_uptodate(struct extent_io_tree *tree,
2910 struct extent_buffer *eb) 2937 struct extent_buffer *eb)
2911{ 2938{
2939 int ret = 0;
2940 int ret2;
2941 int num_pages;
2942 int i;
2943 struct page *page;
2944 int pg_uptodate = 1;
2945
2912 if (eb->flags & EXTENT_UPTODATE) 2946 if (eb->flags & EXTENT_UPTODATE)
2913 return 1; 2947 ret = 1;
2914 return test_range_bit(tree, eb->start, eb->start + eb->len - 1, 2948
2949 ret2 = test_range_bit(tree, eb->start, eb->start + eb->len - 1,
2915 EXTENT_UPTODATE, 1); 2950 EXTENT_UPTODATE, 1);
2951
2952 num_pages = num_extent_pages(eb->start, eb->len);
2953 for (i = 0; i < num_pages; i++) {
2954 page = extent_buffer_page(eb, i);
2955 if (!PageUptodate(page)) {
2956 pg_uptodate = 0;
2957 break;
2958 }
2959 }
2960 if ((ret || ret2) && !pg_uptodate) {
2961printk("uptodate error2 eb %Lu ret %d ret2 %d pg_uptodate %d\n", eb->start, ret, ret2, pg_uptodate);
2962 WARN_ON(1);
2963 }
2964 return (ret || ret2);
2916} 2965}
2917EXPORT_SYMBOL(extent_buffer_uptodate); 2966EXPORT_SYMBOL(extent_buffer_uptodate);
2918 2967
@@ -2929,7 +2978,6 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
2929 unsigned long num_pages; 2978 unsigned long num_pages;
2930 struct bio *bio = NULL; 2979 struct bio *bio = NULL;
2931 2980
2932
2933 if (eb->flags & EXTENT_UPTODATE) 2981 if (eb->flags & EXTENT_UPTODATE)
2934 return 0; 2982 return 0;
2935 2983
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 16d67a61a25c..d9f5bc4dbd7f 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -216,4 +216,6 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
216 unsigned long *map_start, 216 unsigned long *map_start,
217 unsigned long *map_len, int km); 217 unsigned long *map_len, int km);
218void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km); 218void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km);
219int invalidate_extent_lru(struct extent_io_tree *tree, u64 start,
220 unsigned long len);
219#endif 221#endif