|
@@ -743,8 +743,22 @@ static noinline int cow_file_range(struct inode *inode,
|
|
|
em = search_extent_mapping(&BTRFS_I(inode)->extent_tree,
|
|
|
start, num_bytes);
|
|
|
if (em) {
|
|
|
- alloc_hint = em->block_start;
|
|
|
- free_extent_map(em);
|
|
|
+ /*
|
|
|
+ * if block start isn't an actual block number then find the
|
|
|
+ * first block in this inode and use that as a hint. If that
|
|
|
+ * block is also bogus then just don't worry about it.
|
|
|
+ */
|
|
|
+ if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
|
|
|
+ free_extent_map(em);
|
|
|
+ em = search_extent_mapping(em_tree, 0, 0);
|
|
|
+ if (em && em->block_start < EXTENT_MAP_LAST_BYTE)
|
|
|
+ alloc_hint = em->block_start;
|
|
|
+ if (em)
|
|
|
+ free_extent_map(em);
|
|
|
+ } else {
|
|
|
+ alloc_hint = em->block_start;
|
|
|
+ free_extent_map(em);
|
|
|
+ }
|
|
|
}
|
|
|
read_unlock(&BTRFS_I(inode)->extent_tree.lock);
|
|
|
btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0);
|