diff options
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r-- | fs/btrfs/free-space-cache.c | 145 |
1 files changed, 52 insertions, 93 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 81296c57405a..6c4e2baa9290 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -1543,29 +1543,26 @@ again: | |||
1543 | end = bitmap_info->offset + (u64)(BITS_PER_BITMAP * ctl->unit) - 1; | 1543 | end = bitmap_info->offset + (u64)(BITS_PER_BITMAP * ctl->unit) - 1; |
1544 | 1544 | ||
1545 | /* | 1545 | /* |
1546 | * XXX - this can go away after a few releases. | 1546 | * We need to search for bits in this bitmap. We could only cover some |
1547 | * | 1547 | * of the extent in this bitmap thanks to how we add space, so we need |
1548 | * since the only user of btrfs_remove_free_space is the tree logging | 1548 | * to search for as much as it as we can and clear that amount, and then |
1549 | * stuff, and the only way to test that is under crash conditions, we | 1549 | * go searching for the next bit. |
1550 | * want to have this debug stuff here just in case somethings not | ||
1551 | * working. Search the bitmap for the space we are trying to use to | ||
1552 | * make sure its actually there. If its not there then we need to stop | ||
1553 | * because something has gone wrong. | ||
1554 | */ | 1550 | */ |
1555 | search_start = *offset; | 1551 | search_start = *offset; |
1556 | search_bytes = *bytes; | 1552 | search_bytes = ctl->unit; |
1557 | search_bytes = min(search_bytes, end - search_start + 1); | 1553 | search_bytes = min(search_bytes, end - search_start + 1); |
1558 | ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes); | 1554 | ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes); |
1559 | BUG_ON(ret < 0 || search_start != *offset); | 1555 | BUG_ON(ret < 0 || search_start != *offset); |
1560 | 1556 | ||
1561 | if (*offset > bitmap_info->offset && *offset + *bytes > end) { | 1557 | /* We may have found more bits than what we need */ |
1562 | bitmap_clear_bits(ctl, bitmap_info, *offset, end - *offset + 1); | 1558 | search_bytes = min(search_bytes, *bytes); |
1563 | *bytes -= end - *offset + 1; | 1559 | |
1564 | *offset = end + 1; | 1560 | /* Cannot clear past the end of the bitmap */ |
1565 | } else if (*offset >= bitmap_info->offset && *offset + *bytes <= end) { | 1561 | search_bytes = min(search_bytes, end - search_start + 1); |
1566 | bitmap_clear_bits(ctl, bitmap_info, *offset, *bytes); | 1562 | |
1567 | *bytes = 0; | 1563 | bitmap_clear_bits(ctl, bitmap_info, search_start, search_bytes); |
1568 | } | 1564 | *offset += search_bytes; |
1565 | *bytes -= search_bytes; | ||
1569 | 1566 | ||
1570 | if (*bytes) { | 1567 | if (*bytes) { |
1571 | struct rb_node *next = rb_next(&bitmap_info->offset_index); | 1568 | struct rb_node *next = rb_next(&bitmap_info->offset_index); |
@@ -1596,7 +1593,7 @@ again: | |||
1596 | * everything over again. | 1593 | * everything over again. |
1597 | */ | 1594 | */ |
1598 | search_start = *offset; | 1595 | search_start = *offset; |
1599 | search_bytes = *bytes; | 1596 | search_bytes = ctl->unit; |
1600 | ret = search_bitmap(ctl, bitmap_info, &search_start, | 1597 | ret = search_bitmap(ctl, bitmap_info, &search_start, |
1601 | &search_bytes); | 1598 | &search_bytes); |
1602 | if (ret < 0 || search_start != *offset) | 1599 | if (ret < 0 || search_start != *offset) |
@@ -1879,12 +1876,14 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, | |||
1879 | { | 1876 | { |
1880 | struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; | 1877 | struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
1881 | struct btrfs_free_space *info; | 1878 | struct btrfs_free_space *info; |
1882 | struct btrfs_free_space *next_info = NULL; | ||
1883 | int ret = 0; | 1879 | int ret = 0; |
1884 | 1880 | ||
1885 | spin_lock(&ctl->tree_lock); | 1881 | spin_lock(&ctl->tree_lock); |
1886 | 1882 | ||
1887 | again: | 1883 | again: |
1884 | if (!bytes) | ||
1885 | goto out_lock; | ||
1886 | |||
1888 | info = tree_search_offset(ctl, offset, 0, 0); | 1887 | info = tree_search_offset(ctl, offset, 0, 0); |
1889 | if (!info) { | 1888 | if (!info) { |
1890 | /* | 1889 | /* |
@@ -1905,88 +1904,48 @@ again: | |||
1905 | } | 1904 | } |
1906 | } | 1905 | } |
1907 | 1906 | ||
1908 | if (info->bytes < bytes && rb_next(&info->offset_index)) { | 1907 | if (!info->bitmap) { |
1909 | u64 end; | ||
1910 | next_info = rb_entry(rb_next(&info->offset_index), | ||
1911 | struct btrfs_free_space, | ||
1912 | offset_index); | ||
1913 | |||
1914 | if (next_info->bitmap) | ||
1915 | end = next_info->offset + | ||
1916 | BITS_PER_BITMAP * ctl->unit - 1; | ||
1917 | else | ||
1918 | end = next_info->offset + next_info->bytes; | ||
1919 | |||
1920 | if (next_info->bytes < bytes || | ||
1921 | next_info->offset > offset || offset > end) { | ||
1922 | printk(KERN_CRIT "Found free space at %llu, size %llu," | ||
1923 | " trying to use %llu\n", | ||
1924 | (unsigned long long)info->offset, | ||
1925 | (unsigned long long)info->bytes, | ||
1926 | (unsigned long long)bytes); | ||
1927 | WARN_ON(1); | ||
1928 | ret = -EINVAL; | ||
1929 | goto out_lock; | ||
1930 | } | ||
1931 | |||
1932 | info = next_info; | ||
1933 | } | ||
1934 | |||
1935 | if (info->bytes == bytes) { | ||
1936 | unlink_free_space(ctl, info); | 1908 | unlink_free_space(ctl, info); |
1937 | if (info->bitmap) { | 1909 | if (offset == info->offset) { |
1938 | kfree(info->bitmap); | 1910 | u64 to_free = min(bytes, info->bytes); |
1939 | ctl->total_bitmaps--; | 1911 | |
1940 | } | 1912 | info->bytes -= to_free; |
1941 | kmem_cache_free(btrfs_free_space_cachep, info); | 1913 | info->offset += to_free; |
1942 | ret = 0; | 1914 | if (info->bytes) { |
1943 | goto out_lock; | 1915 | ret = link_free_space(ctl, info); |
1944 | } | 1916 | WARN_ON(ret); |
1945 | 1917 | } else { | |
1946 | if (!info->bitmap && info->offset == offset) { | 1918 | kmem_cache_free(btrfs_free_space_cachep, info); |
1947 | unlink_free_space(ctl, info); | 1919 | } |
1948 | info->offset += bytes; | ||
1949 | info->bytes -= bytes; | ||
1950 | ret = link_free_space(ctl, info); | ||
1951 | WARN_ON(ret); | ||
1952 | goto out_lock; | ||
1953 | } | ||
1954 | 1920 | ||
1955 | if (!info->bitmap && info->offset <= offset && | 1921 | offset += to_free; |
1956 | info->offset + info->bytes >= offset + bytes) { | 1922 | bytes -= to_free; |
1957 | u64 old_start = info->offset; | 1923 | goto again; |
1958 | /* | 1924 | } else { |
1959 | * we're freeing space in the middle of the info, | 1925 | u64 old_end = info->bytes + info->offset; |
1960 | * this can happen during tree log replay | ||
1961 | * | ||
1962 | * first unlink the old info and then | ||
1963 | * insert it again after the hole we're creating | ||
1964 | */ | ||
1965 | unlink_free_space(ctl, info); | ||
1966 | if (offset + bytes < info->offset + info->bytes) { | ||
1967 | u64 old_end = info->offset + info->bytes; | ||
1968 | 1926 | ||
1969 | info->offset = offset + bytes; | 1927 | info->bytes = offset - info->offset; |
1970 | info->bytes = old_end - info->offset; | ||
1971 | ret = link_free_space(ctl, info); | 1928 | ret = link_free_space(ctl, info); |
1972 | WARN_ON(ret); | 1929 | WARN_ON(ret); |
1973 | if (ret) | 1930 | if (ret) |
1974 | goto out_lock; | 1931 | goto out_lock; |
1975 | } else { | ||
1976 | /* the hole we're creating ends at the end | ||
1977 | * of the info struct, just free the info | ||
1978 | */ | ||
1979 | kmem_cache_free(btrfs_free_space_cachep, info); | ||
1980 | } | ||
1981 | spin_unlock(&ctl->tree_lock); | ||
1982 | 1932 | ||
1983 | /* step two, insert a new info struct to cover | 1933 | /* Not enough bytes in this entry to satisfy us */ |
1984 | * anything before the hole | 1934 | if (old_end < offset + bytes) { |
1985 | */ | 1935 | bytes -= old_end - offset; |
1986 | ret = btrfs_add_free_space(block_group, old_start, | 1936 | offset = old_end; |
1987 | offset - old_start); | 1937 | goto again; |
1988 | WARN_ON(ret); /* -ENOMEM */ | 1938 | } else if (old_end == offset + bytes) { |
1989 | goto out; | 1939 | /* all done */ |
1940 | goto out_lock; | ||
1941 | } | ||
1942 | spin_unlock(&ctl->tree_lock); | ||
1943 | |||
1944 | ret = btrfs_add_free_space(block_group, offset + bytes, | ||
1945 | old_end - (offset + bytes)); | ||
1946 | WARN_ON(ret); | ||
1947 | goto out; | ||
1948 | } | ||
1990 | } | 1949 | } |
1991 | 1950 | ||
1992 | ret = remove_from_bitmap(ctl, info, &offset, &bytes); | 1951 | ret = remove_from_bitmap(ctl, info, &offset, &bytes); |