diff options
-rw-r--r-- | fs/btrfs/ctree.h | 40 | ||||
-rw-r--r-- | fs/btrfs/extent_map.c | 15 |
2 files changed, 49 insertions, 6 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 4d05456ec32f..54c754dd9a14 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -436,10 +436,18 @@ static inline u##bits btrfs_##name(struct extent_buffer *eb, \ | |||
436 | unsigned long map_len; \ | 436 | unsigned long map_len; \ |
437 | unsigned long offset = (unsigned long)s + \ | 437 | unsigned long offset = (unsigned long)s + \ |
438 | offsetof(type, member); \ | 438 | offsetof(type, member); \ |
439 | err = map_extent_buffer(eb, offset, \ | 439 | if (eb->map_token && offset >= eb->map_start && \ |
440 | offset + sizeof(((type *)0)->member) <= eb->map_start + \ | ||
441 | eb->map_len) { \ | ||
442 | kaddr = eb->kaddr; \ | ||
443 | map_start = eb->map_start; \ | ||
444 | err = 0; \ | ||
445 | } else { \ | ||
446 | err = map_extent_buffer(eb, offset, \ | ||
440 | sizeof(((type *)0)->member), \ | 447 | sizeof(((type *)0)->member), \ |
441 | &map_token, &kaddr, \ | 448 | &map_token, &kaddr, \ |
442 | &map_start, &map_len, KM_USER1); \ | 449 | &map_start, &map_len, KM_USER1); \ |
450 | } \ | ||
443 | if (!err) { \ | 451 | if (!err) { \ |
444 | __le##bits *tmp = (__le##bits *)(kaddr + offset - \ | 452 | __le##bits *tmp = (__le##bits *)(kaddr + offset - \ |
445 | map_start); \ | 453 | map_start); \ |
@@ -464,10 +472,18 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \ | |||
464 | int unmap_on_exit = (eb->map_token == NULL); \ | 472 | int unmap_on_exit = (eb->map_token == NULL); \ |
465 | unsigned long offset = (unsigned long)s + \ | 473 | unsigned long offset = (unsigned long)s + \ |
466 | offsetof(type, member); \ | 474 | offsetof(type, member); \ |
467 | err = map_extent_buffer(eb, offset, \ | 475 | if (eb->map_token && offset >= eb->map_start && \ |
476 | offset + sizeof(((type *)0)->member) <= eb->map_start + \ | ||
477 | eb->map_len) { \ | ||
478 | kaddr = eb->kaddr; \ | ||
479 | map_start = eb->map_start; \ | ||
480 | err = 0; \ | ||
481 | } else { \ | ||
482 | err = map_extent_buffer(eb, offset, \ | ||
468 | sizeof(((type *)0)->member), \ | 483 | sizeof(((type *)0)->member), \ |
469 | &map_token, &kaddr, \ | 484 | &map_token, &kaddr, \ |
470 | &map_start, &map_len, KM_USER1); \ | 485 | &map_start, &map_len, KM_USER1); \ |
486 | } \ | ||
471 | if (!err) { \ | 487 | if (!err) { \ |
472 | __le##bits *tmp = (__le##bits *)(kaddr + offset - \ | 488 | __le##bits *tmp = (__le##bits *)(kaddr + offset - \ |
473 | map_start); \ | 489 | map_start); \ |
@@ -490,10 +506,18 @@ static inline u##bits btrfs_##name(struct extent_buffer *eb) \ | |||
490 | unsigned long map_len; \ | 506 | unsigned long map_len; \ |
491 | unsigned long offset = offsetof(type, member); \ | 507 | unsigned long offset = offsetof(type, member); \ |
492 | int unmap_on_exit = (eb->map_token == NULL); \ | 508 | int unmap_on_exit = (eb->map_token == NULL); \ |
493 | err = map_extent_buffer(eb, offset, \ | 509 | if (eb->map_token && offset >= eb->map_start && \ |
510 | offset + sizeof(((type *)0)->member) <= eb->map_start + \ | ||
511 | eb->map_len) { \ | ||
512 | kaddr = eb->kaddr; \ | ||
513 | map_start = eb->map_start; \ | ||
514 | err = 0; \ | ||
515 | } else { \ | ||
516 | err = map_extent_buffer(eb, offset, \ | ||
494 | sizeof(((type *)0)->member), \ | 517 | sizeof(((type *)0)->member), \ |
495 | &map_token, &kaddr, \ | 518 | &map_token, &kaddr, \ |
496 | &map_start, &map_len, KM_USER1); \ | 519 | &map_start, &map_len, KM_USER1); \ |
520 | } \ | ||
497 | if (!err) { \ | 521 | if (!err) { \ |
498 | __le##bits *tmp = (__le##bits *)(kaddr + offset - \ | 522 | __le##bits *tmp = (__le##bits *)(kaddr + offset - \ |
499 | map_start); \ | 523 | map_start); \ |
@@ -517,10 +541,18 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \ | |||
517 | unsigned long map_len; \ | 541 | unsigned long map_len; \ |
518 | unsigned long offset = offsetof(type, member); \ | 542 | unsigned long offset = offsetof(type, member); \ |
519 | int unmap_on_exit = (eb->map_token == NULL); \ | 543 | int unmap_on_exit = (eb->map_token == NULL); \ |
520 | err = map_extent_buffer(eb, offset, \ | 544 | if (eb->map_token && offset >= eb->map_start && \ |
545 | offset + sizeof(((type *)0)->member) <= eb->map_start + \ | ||
546 | eb->map_len) { \ | ||
547 | kaddr = eb->kaddr; \ | ||
548 | map_start = eb->map_start; \ | ||
549 | err = 0; \ | ||
550 | } else { \ | ||
551 | err = map_extent_buffer(eb, offset, \ | ||
521 | sizeof(((type *)0)->member), \ | 552 | sizeof(((type *)0)->member), \ |
522 | &map_token, &kaddr, \ | 553 | &map_token, &kaddr, \ |
523 | &map_start, &map_len, KM_USER1); \ | 554 | &map_start, &map_len, KM_USER1); \ |
555 | } \ | ||
524 | if (!err) { \ | 556 | if (!err) { \ |
525 | __le##bits *tmp = (__le##bits *)(kaddr + offset - \ | 557 | __le##bits *tmp = (__le##bits *)(kaddr + offset - \ |
526 | map_start); \ | 558 | map_start); \ |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index f658703c42e6..ea6ee68ef53c 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -2037,6 +2037,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree, | |||
2037 | struct extent_buffer *eb; | 2037 | struct extent_buffer *eb; |
2038 | struct page *p; | 2038 | struct page *p; |
2039 | struct address_space *mapping = tree->mapping; | 2039 | struct address_space *mapping = tree->mapping; |
2040 | int uptodate = 1; | ||
2040 | 2041 | ||
2041 | eb = __alloc_extent_buffer(mask); | 2042 | eb = __alloc_extent_buffer(mask); |
2042 | if (!eb || IS_ERR(eb)) | 2043 | if (!eb || IS_ERR(eb)) |
@@ -2048,7 +2049,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree, | |||
2048 | atomic_set(&eb->refs, 1); | 2049 | atomic_set(&eb->refs, 1); |
2049 | 2050 | ||
2050 | for (i = 0; i < num_pages; i++, index++) { | 2051 | for (i = 0; i < num_pages; i++, index++) { |
2051 | p = find_get_page(mapping, index); | 2052 | p = find_lock_page(mapping, index); |
2052 | if (!p) { | 2053 | if (!p) { |
2053 | /* make sure the free only frees the pages we've | 2054 | /* make sure the free only frees the pages we've |
2054 | * grabbed a reference on | 2055 | * grabbed a reference on |
@@ -2060,7 +2061,12 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree, | |||
2060 | set_page_extent_mapped(p); | 2061 | set_page_extent_mapped(p); |
2061 | if (i == 0) | 2062 | if (i == 0) |
2062 | eb->first_page = p; | 2063 | eb->first_page = p; |
2064 | if (!PageUptodate(p)) | ||
2065 | uptodate = 0; | ||
2066 | unlock_page(p); | ||
2063 | } | 2067 | } |
2068 | if (uptodate) | ||
2069 | eb->flags |= EXTENT_UPTODATE; | ||
2064 | return eb; | 2070 | return eb; |
2065 | fail: | 2071 | fail: |
2066 | free_extent_buffer(eb); | 2072 | free_extent_buffer(eb); |
@@ -2192,7 +2198,7 @@ int read_extent_buffer_pages(struct extent_map_tree *tree, | |||
2192 | if (eb->flags & EXTENT_UPTODATE) | 2198 | if (eb->flags & EXTENT_UPTODATE) |
2193 | return 0; | 2199 | return 0; |
2194 | 2200 | ||
2195 | if (test_range_bit(tree, eb->start, eb->start + eb->len - 1, | 2201 | if (0 && test_range_bit(tree, eb->start, eb->start + eb->len - 1, |
2196 | EXTENT_UPTODATE, 1)) { | 2202 | EXTENT_UPTODATE, 1)) { |
2197 | return 0; | 2203 | return 0; |
2198 | } | 2204 | } |
@@ -2247,6 +2253,7 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv, | |||
2247 | char *dst = (char *)dstv; | 2253 | char *dst = (char *)dstv; |
2248 | size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); | 2254 | size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); |
2249 | unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; | 2255 | unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; |
2256 | unsigned long num_pages = num_extent_pages(eb->start, eb->len); | ||
2250 | 2257 | ||
2251 | WARN_ON(start > eb->len); | 2258 | WARN_ON(start > eb->len); |
2252 | WARN_ON(start + len > eb->start + eb->len); | 2259 | WARN_ON(start + len > eb->start + eb->len); |
@@ -2257,6 +2264,10 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv, | |||
2257 | 2264 | ||
2258 | while(len > 0) { | 2265 | while(len > 0) { |
2259 | page = extent_buffer_page(eb, i); | 2266 | page = extent_buffer_page(eb, i); |
2267 | if (!PageUptodate(page)) { | ||
2268 | printk("page %lu not up to date i %lu, total %lu, len %lu\n", page->index, i, num_pages, eb->len); | ||
2269 | WARN_ON(1); | ||
2270 | } | ||
2260 | WARN_ON(!PageUptodate(page)); | 2271 | WARN_ON(!PageUptodate(page)); |
2261 | 2272 | ||
2262 | cur = min(len, (PAGE_CACHE_SIZE - offset)); | 2273 | cur = min(len, (PAGE_CACHE_SIZE - offset)); |