diff options
| author | Chris Mason <chris.mason@oracle.com> | 2012-01-31 20:27:41 -0500 |
|---|---|---|
| committer | Chris Mason <chris.mason@oracle.com> | 2012-01-31 20:27:41 -0500 |
| commit | d98456fcafa6f3fd1985f9b7429aaa3531c6bfa0 (patch) | |
| tree | 7cf01b839f68a612b8d612e7eb6315955f792d73 | |
| parent | 9998eb703490589c3e8f1bf09b15203156776edb (diff) | |
Btrfs: don't reserve data with extents locked in btrfs_fallocate
btrfs_fallocate tries to allocate space only if ranges in the file don't
already exist. But the enospc checks it does are not allowed with
extents locked.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
| -rw-r--r-- | fs/btrfs/file.c | 25 |
1 files changed, 10 insertions, 15 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 0f61e11a2998..0621a3a7d5d1 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -1604,6 +1604,14 @@ static long btrfs_fallocate(struct file *file, int mode, | |||
| 1604 | return -EOPNOTSUPP; | 1604 | return -EOPNOTSUPP; |
| 1605 | 1605 | ||
| 1606 | /* | 1606 | /* |
| 1607 | * Make sure we have enough space before we do the | ||
| 1608 | * allocation. | ||
| 1609 | */ | ||
| 1610 | ret = btrfs_check_data_free_space(inode, len); | ||
| 1611 | if (ret) | ||
| 1612 | return ret; | ||
| 1613 | |||
| 1614 | /* | ||
| 1607 | * wait for ordered IO before we have any locks. We'll loop again | 1615 | * wait for ordered IO before we have any locks. We'll loop again |
| 1608 | * below with the locks held. | 1616 | * below with the locks held. |
| 1609 | */ | 1617 | */ |
| @@ -1666,27 +1674,12 @@ static long btrfs_fallocate(struct file *file, int mode, | |||
| 1666 | if (em->block_start == EXTENT_MAP_HOLE || | 1674 | if (em->block_start == EXTENT_MAP_HOLE || |
| 1667 | (cur_offset >= inode->i_size && | 1675 | (cur_offset >= inode->i_size && |
| 1668 | !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { | 1676 | !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { |
| 1669 | |||
| 1670 | /* | ||
| 1671 | * Make sure we have enough space before we do the | ||
| 1672 | * allocation. | ||
| 1673 | */ | ||
| 1674 | ret = btrfs_check_data_free_space(inode, last_byte - | ||
| 1675 | cur_offset); | ||
| 1676 | if (ret) { | ||
| 1677 | free_extent_map(em); | ||
| 1678 | break; | ||
| 1679 | } | ||
| 1680 | |||
| 1681 | ret = btrfs_prealloc_file_range(inode, mode, cur_offset, | 1677 | ret = btrfs_prealloc_file_range(inode, mode, cur_offset, |
| 1682 | last_byte - cur_offset, | 1678 | last_byte - cur_offset, |
| 1683 | 1 << inode->i_blkbits, | 1679 | 1 << inode->i_blkbits, |
| 1684 | offset + len, | 1680 | offset + len, |
| 1685 | &alloc_hint); | 1681 | &alloc_hint); |
| 1686 | 1682 | ||
| 1687 | /* Let go of our reservation. */ | ||
| 1688 | btrfs_free_reserved_data_space(inode, last_byte - | ||
| 1689 | cur_offset); | ||
| 1690 | if (ret < 0) { | 1683 | if (ret < 0) { |
| 1691 | free_extent_map(em); | 1684 | free_extent_map(em); |
| 1692 | break; | 1685 | break; |
| @@ -1714,6 +1707,8 @@ static long btrfs_fallocate(struct file *file, int mode, | |||
| 1714 | &cached_state, GFP_NOFS); | 1707 | &cached_state, GFP_NOFS); |
| 1715 | out: | 1708 | out: |
| 1716 | mutex_unlock(&inode->i_mutex); | 1709 | mutex_unlock(&inode->i_mutex); |
| 1710 | /* Let go of our reservation. */ | ||
| 1711 | btrfs_free_reserved_data_space(inode, len); | ||
| 1717 | return ret; | 1712 | return ret; |
| 1718 | } | 1713 | } |
| 1719 | 1714 | ||
