diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-04-09 16:28:12 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:01 -0400 |
commit | 728131d8e40c2a47c59ca91a806299c4708029f9 (patch) | |
tree | 4b6023689d6f77fdf785d815a2ca986e73aeff1a /fs | |
parent | cea9e4452ebaf18dd0951e90dc84d82a5dee40b2 (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.c | 3 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 54 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 2 |
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 | } |
387 | WARN_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 | ||
2595 | int 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); | ||
2617 | out: | ||
2618 | spin_unlock(&tree->lru_lock); | ||
2619 | return found; | ||
2620 | } | ||
2621 | |||
2595 | static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, | 2622 | static 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); | |||
2909 | int extent_buffer_uptodate(struct extent_io_tree *tree, | 2936 | int 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) { | ||
2961 | printk("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 | } |
2917 | EXPORT_SYMBOL(extent_buffer_uptodate); | 2966 | EXPORT_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); |
218 | void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km); | 218 | void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km); |
219 | int invalidate_extent_lru(struct extent_io_tree *tree, u64 start, | ||
220 | unsigned long len); | ||
219 | #endif | 221 | #endif |