Commit ee20a98314e52a6675e94d1a07ca205ffdf09a72
Committed by
Chris Mason
1 parent
ed8c4913da
Exists in
master
and in
20 other branches
Btrfs: allow splitting of hole em's when dropping extent cache
I noticed while running multi-threaded fsync tests that sometimes fsck would complain about an improper gap. This happens because we fail to add a hole extent to the file, which was happening when we'd split a hole EM because btrfs_drop_extent_cache was just discarding the whole em instead of splitting it. So this patch fixes this by allowing us to split a hole em properly, which means that added holes actually get logged properly and we no longer see this fsck error. Thankfully we're tolerant of these sort of problems so a user would not see any adverse effects of this bug, other than fsck complaining. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Showing 1 changed file with 40 additions and 22 deletions Side-by-side Diff
fs/btrfs/file.c
... | ... | @@ -596,20 +596,29 @@ |
596 | 596 | if (no_splits) |
597 | 597 | goto next; |
598 | 598 | |
599 | - if (em->block_start < EXTENT_MAP_LAST_BYTE && | |
600 | - em->start < start) { | |
599 | + if (em->start < start) { | |
601 | 600 | split->start = em->start; |
602 | 601 | split->len = start - em->start; |
603 | - split->orig_start = em->orig_start; | |
604 | - split->block_start = em->block_start; | |
605 | 602 | |
606 | - if (compressed) | |
607 | - split->block_len = em->block_len; | |
608 | - else | |
609 | - split->block_len = split->len; | |
610 | - split->ram_bytes = em->ram_bytes; | |
611 | - split->orig_block_len = max(split->block_len, | |
612 | - em->orig_block_len); | |
603 | + if (em->block_start < EXTENT_MAP_LAST_BYTE) { | |
604 | + split->orig_start = em->orig_start; | |
605 | + split->block_start = em->block_start; | |
606 | + | |
607 | + if (compressed) | |
608 | + split->block_len = em->block_len; | |
609 | + else | |
610 | + split->block_len = split->len; | |
611 | + split->orig_block_len = max(split->block_len, | |
612 | + em->orig_block_len); | |
613 | + split->ram_bytes = em->ram_bytes; | |
614 | + } else { | |
615 | + split->orig_start = split->start; | |
616 | + split->block_len = 0; | |
617 | + split->block_start = em->block_start; | |
618 | + split->orig_block_len = 0; | |
619 | + split->ram_bytes = split->len; | |
620 | + } | |
621 | + | |
613 | 622 | split->generation = gen; |
614 | 623 | split->bdev = em->bdev; |
615 | 624 | split->flags = flags; |
... | ... | @@ -620,8 +629,7 @@ |
620 | 629 | split = split2; |
621 | 630 | split2 = NULL; |
622 | 631 | } |
623 | - if (em->block_start < EXTENT_MAP_LAST_BYTE && | |
624 | - testend && em->start + em->len > start + len) { | |
632 | + if (testend && em->start + em->len > start + len) { | |
625 | 633 | u64 diff = start + len - em->start; |
626 | 634 | |
627 | 635 | split->start = start + len; |
628 | 636 | |
629 | 637 | |
630 | 638 | |
... | ... | @@ -630,18 +638,28 @@ |
630 | 638 | split->flags = flags; |
631 | 639 | split->compress_type = em->compress_type; |
632 | 640 | split->generation = gen; |
633 | - split->orig_block_len = max(em->block_len, | |
641 | + | |
642 | + if (em->block_start < EXTENT_MAP_LAST_BYTE) { | |
643 | + split->orig_block_len = max(em->block_len, | |
634 | 644 | em->orig_block_len); |
635 | - split->ram_bytes = em->ram_bytes; | |
636 | 645 | |
637 | - if (compressed) { | |
638 | - split->block_len = em->block_len; | |
639 | - split->block_start = em->block_start; | |
640 | - split->orig_start = em->orig_start; | |
646 | + split->ram_bytes = em->ram_bytes; | |
647 | + if (compressed) { | |
648 | + split->block_len = em->block_len; | |
649 | + split->block_start = em->block_start; | |
650 | + split->orig_start = em->orig_start; | |
651 | + } else { | |
652 | + split->block_len = split->len; | |
653 | + split->block_start = em->block_start | |
654 | + + diff; | |
655 | + split->orig_start = em->orig_start; | |
656 | + } | |
641 | 657 | } else { |
642 | - split->block_len = split->len; | |
643 | - split->block_start = em->block_start + diff; | |
644 | - split->orig_start = em->orig_start; | |
658 | + split->ram_bytes = split->len; | |
659 | + split->orig_start = split->start; | |
660 | + split->block_len = 0; | |
661 | + split->block_start = em->block_start; | |
662 | + split->orig_block_len = 0; | |
645 | 663 | } |
646 | 664 | |
647 | 665 | ret = add_extent_mapping(em_tree, split, modified); |