diff options
| author | Josef Bacik <josef@redhat.com> | 2009-11-10 21:23:47 -0500 |
|---|---|---|
| committer | Chris Mason <chris.mason@oracle.com> | 2009-11-11 14:20:16 -0500 |
| commit | 6346c93988caa3048bf4d81f9ba3608a7a195aa2 (patch) | |
| tree | 78e5fbc5fa6ed8c692db24dfff475e2b95413570 /fs/btrfs/inode.c | |
| parent | 444528b3e614f7f2391488d9bca8e0b872db909b (diff) | |
Btrfs: fix data allocation hint start
Sometimes our start allocation hint when we cow a file can be either
EXTENT_HOLE or some other such place holder, which is not optimal. So if we
find that our em->block_start is one of these special values, check to see
where the first block of the inode is stored, and use that as a hint. If that
block is also a special value, just fallback on a hint of 0 and let the
allocator figure out a good place to put the data.
Signed-off-by: Josef Bacik <josef@redhat.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
| -rw-r--r-- | fs/btrfs/inode.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 78139efe41fc..d8393ddc72a3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -743,8 +743,22 @@ static noinline int cow_file_range(struct inode *inode, | |||
| 743 | em = search_extent_mapping(&BTRFS_I(inode)->extent_tree, | 743 | em = search_extent_mapping(&BTRFS_I(inode)->extent_tree, |
| 744 | start, num_bytes); | 744 | start, num_bytes); |
| 745 | if (em) { | 745 | if (em) { |
| 746 | alloc_hint = em->block_start; | 746 | /* |
| 747 | free_extent_map(em); | 747 | * if block start isn't an actual block number then find the |
| 748 | * first block in this inode and use that as a hint. If that | ||
| 749 | * block is also bogus then just don't worry about it. | ||
| 750 | */ | ||
| 751 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
| 752 | free_extent_map(em); | ||
| 753 | em = search_extent_mapping(em_tree, 0, 0); | ||
| 754 | if (em && em->block_start < EXTENT_MAP_LAST_BYTE) | ||
| 755 | alloc_hint = em->block_start; | ||
| 756 | if (em) | ||
| 757 | free_extent_map(em); | ||
| 758 | } else { | ||
| 759 | alloc_hint = em->block_start; | ||
| 760 | free_extent_map(em); | ||
| 761 | } | ||
| 748 | } | 762 | } |
| 749 | read_unlock(&BTRFS_I(inode)->extent_tree.lock); | 763 | read_unlock(&BTRFS_I(inode)->extent_tree.lock); |
| 750 | btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0); | 764 | btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0); |
