Commit ee20a98314e52a6675e94d1a07ca205ffdf09a72

Authored by Josef Bacik
Committed by Chris Mason
1 parent ed8c4913da

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

... ... @@ -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);