diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 61 |
1 files changed, 35 insertions, 26 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index e785f0a0632b..af2de30dbeac 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1794,7 +1794,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
1794 | *space_info = found; | 1794 | *space_info = found; |
1795 | return 0; | 1795 | return 0; |
1796 | } | 1796 | } |
1797 | found = kmalloc(sizeof(*found), GFP_NOFS); | 1797 | found = kzalloc(sizeof(*found), GFP_NOFS); |
1798 | if (!found) | 1798 | if (!found) |
1799 | return -ENOMEM; | 1799 | return -ENOMEM; |
1800 | 1800 | ||
@@ -1807,6 +1807,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
1807 | found->bytes_used = bytes_used; | 1807 | found->bytes_used = bytes_used; |
1808 | found->bytes_pinned = 0; | 1808 | found->bytes_pinned = 0; |
1809 | found->bytes_reserved = 0; | 1809 | found->bytes_reserved = 0; |
1810 | found->bytes_readonly = 0; | ||
1810 | found->full = 0; | 1811 | found->full = 0; |
1811 | found->force_alloc = 0; | 1812 | found->force_alloc = 0; |
1812 | *space_info = found; | 1813 | *space_info = found; |
@@ -1829,6 +1830,19 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | |||
1829 | } | 1830 | } |
1830 | } | 1831 | } |
1831 | 1832 | ||
1833 | static void set_block_group_readonly(struct btrfs_block_group_cache *cache) | ||
1834 | { | ||
1835 | spin_lock(&cache->space_info->lock); | ||
1836 | spin_lock(&cache->lock); | ||
1837 | if (!cache->ro) { | ||
1838 | cache->space_info->bytes_readonly += cache->key.offset - | ||
1839 | btrfs_block_group_used(&cache->item); | ||
1840 | cache->ro = 1; | ||
1841 | } | ||
1842 | spin_unlock(&cache->lock); | ||
1843 | spin_unlock(&cache->space_info->lock); | ||
1844 | } | ||
1845 | |||
1832 | static u64 reduce_alloc_profile(struct btrfs_root *root, u64 flags) | 1846 | static u64 reduce_alloc_profile(struct btrfs_root *root, u64 flags) |
1833 | { | 1847 | { |
1834 | u64 num_devices = root->fs_info->fs_devices->num_devices; | 1848 | u64 num_devices = root->fs_info->fs_devices->num_devices; |
@@ -1865,7 +1879,9 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1865 | u64 thresh; | 1879 | u64 thresh; |
1866 | u64 start; | 1880 | u64 start; |
1867 | u64 num_bytes; | 1881 | u64 num_bytes; |
1868 | int ret = 0, waited = 0; | 1882 | int ret = 0; |
1883 | |||
1884 | mutex_lock(&extent_root->fs_info->chunk_mutex); | ||
1869 | 1885 | ||
1870 | flags = reduce_alloc_profile(extent_root, flags); | 1886 | flags = reduce_alloc_profile(extent_root, flags); |
1871 | 1887 | ||
@@ -1887,46 +1903,28 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1887 | goto out; | 1903 | goto out; |
1888 | } | 1904 | } |
1889 | 1905 | ||
1890 | thresh = div_factor(space_info->total_bytes, 6); | 1906 | thresh = space_info->total_bytes - space_info->bytes_readonly; |
1907 | thresh = div_factor(thresh, 6); | ||
1891 | if (!force && | 1908 | if (!force && |
1892 | (space_info->bytes_used + space_info->bytes_pinned + | 1909 | (space_info->bytes_used + space_info->bytes_pinned + |
1893 | space_info->bytes_reserved + alloc_bytes) < thresh) { | 1910 | space_info->bytes_reserved + alloc_bytes) < thresh) { |
1894 | spin_unlock(&space_info->lock); | 1911 | spin_unlock(&space_info->lock); |
1895 | goto out; | 1912 | goto out; |
1896 | } | 1913 | } |
1897 | |||
1898 | spin_unlock(&space_info->lock); | 1914 | spin_unlock(&space_info->lock); |
1899 | 1915 | ||
1900 | ret = mutex_trylock(&extent_root->fs_info->chunk_mutex); | ||
1901 | if (!ret && !force) { | ||
1902 | goto out; | ||
1903 | } else if (!ret) { | ||
1904 | mutex_lock(&extent_root->fs_info->chunk_mutex); | ||
1905 | waited = 1; | ||
1906 | } | ||
1907 | |||
1908 | if (waited) { | ||
1909 | spin_lock(&space_info->lock); | ||
1910 | if (space_info->full) { | ||
1911 | spin_unlock(&space_info->lock); | ||
1912 | goto out_unlock; | ||
1913 | } | ||
1914 | spin_unlock(&space_info->lock); | ||
1915 | } | ||
1916 | |||
1917 | ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes, flags); | 1916 | ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes, flags); |
1918 | if (ret) { | 1917 | if (ret) { |
1919 | printk("space info full %Lu\n", flags); | 1918 | printk("space info full %Lu\n", flags); |
1920 | space_info->full = 1; | 1919 | space_info->full = 1; |
1921 | goto out_unlock; | 1920 | goto out; |
1922 | } | 1921 | } |
1923 | 1922 | ||
1924 | ret = btrfs_make_block_group(trans, extent_root, 0, flags, | 1923 | ret = btrfs_make_block_group(trans, extent_root, 0, flags, |
1925 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes); | 1924 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes); |
1926 | BUG_ON(ret); | 1925 | BUG_ON(ret); |
1927 | out_unlock: | ||
1928 | mutex_unlock(&extent_root->fs_info->chunk_mutex); | ||
1929 | out: | 1926 | out: |
1927 | mutex_unlock(&extent_root->fs_info->chunk_mutex); | ||
1930 | return ret; | 1928 | return ret; |
1931 | } | 1929 | } |
1932 | 1930 | ||
@@ -1956,12 +1954,18 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
1956 | if (alloc) { | 1954 | if (alloc) { |
1957 | old_val += num_bytes; | 1955 | old_val += num_bytes; |
1958 | cache->space_info->bytes_used += num_bytes; | 1956 | cache->space_info->bytes_used += num_bytes; |
1957 | if (cache->ro) { | ||
1958 | cache->space_info->bytes_readonly -= num_bytes; | ||
1959 | WARN_ON(1); | ||
1960 | } | ||
1959 | btrfs_set_block_group_used(&cache->item, old_val); | 1961 | btrfs_set_block_group_used(&cache->item, old_val); |
1960 | spin_unlock(&cache->lock); | 1962 | spin_unlock(&cache->lock); |
1961 | spin_unlock(&cache->space_info->lock); | 1963 | spin_unlock(&cache->space_info->lock); |
1962 | } else { | 1964 | } else { |
1963 | old_val -= num_bytes; | 1965 | old_val -= num_bytes; |
1964 | cache->space_info->bytes_used -= num_bytes; | 1966 | cache->space_info->bytes_used -= num_bytes; |
1967 | if (cache->ro) | ||
1968 | cache->space_info->bytes_readonly += num_bytes; | ||
1965 | btrfs_set_block_group_used(&cache->item, old_val); | 1969 | btrfs_set_block_group_used(&cache->item, old_val); |
1966 | spin_unlock(&cache->lock); | 1970 | spin_unlock(&cache->lock); |
1967 | spin_unlock(&cache->space_info->lock); | 1971 | spin_unlock(&cache->space_info->lock); |
@@ -5560,8 +5564,7 @@ int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start) | |||
5560 | BUG_ON(IS_ERR(reloc_inode)); | 5564 | BUG_ON(IS_ERR(reloc_inode)); |
5561 | 5565 | ||
5562 | __alloc_chunk_for_shrink(root, block_group, 1); | 5566 | __alloc_chunk_for_shrink(root, block_group, 1); |
5563 | block_group->ro = 1; | 5567 | set_block_group_readonly(block_group); |
5564 | block_group->space_info->total_bytes -= block_group->key.offset; | ||
5565 | 5568 | ||
5566 | btrfs_start_delalloc_inodes(info->tree_root); | 5569 | btrfs_start_delalloc_inodes(info->tree_root); |
5567 | btrfs_wait_ordered_extents(info->tree_root, 0); | 5570 | btrfs_wait_ordered_extents(info->tree_root, 0); |
@@ -5868,6 +5871,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5868 | 5871 | ||
5869 | block_group = btrfs_lookup_block_group(root->fs_info, group_start); | 5872 | block_group = btrfs_lookup_block_group(root->fs_info, group_start); |
5870 | BUG_ON(!block_group); | 5873 | BUG_ON(!block_group); |
5874 | BUG_ON(!block_group->ro); | ||
5871 | 5875 | ||
5872 | memcpy(&key, &block_group->key, sizeof(key)); | 5876 | memcpy(&key, &block_group->key, sizeof(key)); |
5873 | 5877 | ||
@@ -5881,6 +5885,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5881 | list_del(&block_group->list); | 5885 | list_del(&block_group->list); |
5882 | up_write(&block_group->space_info->groups_sem); | 5886 | up_write(&block_group->space_info->groups_sem); |
5883 | 5887 | ||
5888 | spin_lock(&block_group->space_info->lock); | ||
5889 | block_group->space_info->total_bytes -= block_group->key.offset; | ||
5890 | block_group->space_info->bytes_readonly -= block_group->key.offset; | ||
5891 | spin_unlock(&block_group->space_info->lock); | ||
5892 | |||
5884 | /* | 5893 | /* |
5885 | memset(shrink_block_group, 0, sizeof(*shrink_block_group)); | 5894 | memset(shrink_block_group, 0, sizeof(*shrink_block_group)); |
5886 | kfree(shrink_block_group); | 5895 | kfree(shrink_block_group); |