Commit ee20a983 authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

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: default avatarJosef Bacik <jbacik@fusionio.com>
Signed-off-by: default avatarChris Mason <chris.mason@fusionio.com>
parent ed8c4913
...@@ -596,10 +596,11 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, ...@@ -596,10 +596,11 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
if (no_splits) if (no_splits)
goto next; goto next;
if (em->block_start < EXTENT_MAP_LAST_BYTE && if (em->start < start) {
em->start < start) {
split->start = em->start; split->start = em->start;
split->len = start - em->start; split->len = start - em->start;
if (em->block_start < EXTENT_MAP_LAST_BYTE) {
split->orig_start = em->orig_start; split->orig_start = em->orig_start;
split->block_start = em->block_start; split->block_start = em->block_start;
...@@ -607,9 +608,17 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, ...@@ -607,9 +608,17 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
split->block_len = em->block_len; split->block_len = em->block_len;
else else
split->block_len = split->len; split->block_len = split->len;
split->ram_bytes = em->ram_bytes;
split->orig_block_len = max(split->block_len, split->orig_block_len = max(split->block_len,
em->orig_block_len); em->orig_block_len);
split->ram_bytes = em->ram_bytes;
} else {
split->orig_start = split->start;
split->block_len = 0;
split->block_start = em->block_start;
split->orig_block_len = 0;
split->ram_bytes = split->len;
}
split->generation = gen; split->generation = gen;
split->bdev = em->bdev; split->bdev = em->bdev;
split->flags = flags; split->flags = flags;
...@@ -620,8 +629,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, ...@@ -620,8 +629,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
split = split2; split = split2;
split2 = NULL; split2 = NULL;
} }
if (em->block_start < EXTENT_MAP_LAST_BYTE && if (testend && em->start + em->len > start + len) {
testend && em->start + em->len > start + len) {
u64 diff = start + len - em->start; u64 diff = start + len - em->start;
split->start = start + len; split->start = start + len;
...@@ -630,19 +638,29 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, ...@@ -630,19 +638,29 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
split->flags = flags; split->flags = flags;
split->compress_type = em->compress_type; split->compress_type = em->compress_type;
split->generation = gen; split->generation = gen;
if (em->block_start < EXTENT_MAP_LAST_BYTE) {
split->orig_block_len = max(em->block_len, split->orig_block_len = max(em->block_len,
em->orig_block_len); em->orig_block_len);
split->ram_bytes = em->ram_bytes;
split->ram_bytes = em->ram_bytes;
if (compressed) { if (compressed) {
split->block_len = em->block_len; split->block_len = em->block_len;
split->block_start = em->block_start; split->block_start = em->block_start;
split->orig_start = em->orig_start; split->orig_start = em->orig_start;
} else { } else {
split->block_len = split->len; split->block_len = split->len;
split->block_start = em->block_start + diff; split->block_start = em->block_start
+ diff;
split->orig_start = em->orig_start; split->orig_start = em->orig_start;
} }
} else {
split->ram_bytes = split->len;
split->orig_start = split->start;
split->block_len = 0;
split->block_start = em->block_start;
split->orig_block_len = 0;
}
ret = add_extent_mapping(em_tree, split, modified); ret = add_extent_mapping(em_tree, split, modified);
BUG_ON(ret); /* Logic error */ BUG_ON(ret); /* Logic error */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment