diff options
author | Chris Mason <chris.mason@oracle.com> | 2009-09-24 10:00:58 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-09-24 10:00:58 -0400 |
commit | 54bcf382daf08c1396edb8b81e650b58930ccaef (patch) | |
tree | 64b941f09489b5c9ee63e4ad43d736bfce911b21 /fs/btrfs/volumes.c | |
parent | 94a8d5caba74211ec76dac80fc6e2d5c391530df (diff) | |
parent | c65ddb52dc412c9b67681b1aa16cd1bac8434e24 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable into for-linus
Conflicts:
fs/btrfs/super.c
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 117 |
1 files changed, 78 insertions, 39 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 5cf405b0828d..23e7d36ff325 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -276,7 +276,7 @@ loop_lock: | |||
276 | * is now congested. Back off and let other work structs | 276 | * is now congested. Back off and let other work structs |
277 | * run instead | 277 | * run instead |
278 | */ | 278 | */ |
279 | if (pending && bdi_write_congested(bdi) && batch_run > 32 && | 279 | if (pending && bdi_write_congested(bdi) && batch_run > 8 && |
280 | fs_info->fs_devices->open_devices > 1) { | 280 | fs_info->fs_devices->open_devices > 1) { |
281 | struct io_context *ioc; | 281 | struct io_context *ioc; |
282 | 282 | ||
@@ -719,10 +719,9 @@ error: | |||
719 | * called very infrequently and that a given device has a small number | 719 | * called very infrequently and that a given device has a small number |
720 | * of extents | 720 | * of extents |
721 | */ | 721 | */ |
722 | static noinline int find_free_dev_extent(struct btrfs_trans_handle *trans, | 722 | int find_free_dev_extent(struct btrfs_trans_handle *trans, |
723 | struct btrfs_device *device, | 723 | struct btrfs_device *device, u64 num_bytes, |
724 | u64 num_bytes, u64 *start, | 724 | u64 *start, u64 *max_avail) |
725 | u64 *max_avail) | ||
726 | { | 725 | { |
727 | struct btrfs_key key; | 726 | struct btrfs_key key; |
728 | struct btrfs_root *root = device->dev_root; | 727 | struct btrfs_root *root = device->dev_root; |
@@ -1736,6 +1735,10 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, | |||
1736 | extent_root = root->fs_info->extent_root; | 1735 | extent_root = root->fs_info->extent_root; |
1737 | em_tree = &root->fs_info->mapping_tree.map_tree; | 1736 | em_tree = &root->fs_info->mapping_tree.map_tree; |
1738 | 1737 | ||
1738 | ret = btrfs_can_relocate(extent_root, chunk_offset); | ||
1739 | if (ret) | ||
1740 | return -ENOSPC; | ||
1741 | |||
1739 | /* step one, relocate all the extents inside this chunk */ | 1742 | /* step one, relocate all the extents inside this chunk */ |
1740 | ret = btrfs_relocate_block_group(extent_root, chunk_offset); | 1743 | ret = btrfs_relocate_block_group(extent_root, chunk_offset); |
1741 | BUG_ON(ret); | 1744 | BUG_ON(ret); |
@@ -1749,9 +1752,9 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, | |||
1749 | * step two, delete the device extents and the | 1752 | * step two, delete the device extents and the |
1750 | * chunk tree entries | 1753 | * chunk tree entries |
1751 | */ | 1754 | */ |
1752 | spin_lock(&em_tree->lock); | 1755 | read_lock(&em_tree->lock); |
1753 | em = lookup_extent_mapping(em_tree, chunk_offset, 1); | 1756 | em = lookup_extent_mapping(em_tree, chunk_offset, 1); |
1754 | spin_unlock(&em_tree->lock); | 1757 | read_unlock(&em_tree->lock); |
1755 | 1758 | ||
1756 | BUG_ON(em->start > chunk_offset || | 1759 | BUG_ON(em->start > chunk_offset || |
1757 | em->start + em->len < chunk_offset); | 1760 | em->start + em->len < chunk_offset); |
@@ -1780,9 +1783,9 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, | |||
1780 | ret = btrfs_remove_block_group(trans, extent_root, chunk_offset); | 1783 | ret = btrfs_remove_block_group(trans, extent_root, chunk_offset); |
1781 | BUG_ON(ret); | 1784 | BUG_ON(ret); |
1782 | 1785 | ||
1783 | spin_lock(&em_tree->lock); | 1786 | write_lock(&em_tree->lock); |
1784 | remove_extent_mapping(em_tree, em); | 1787 | remove_extent_mapping(em_tree, em); |
1785 | spin_unlock(&em_tree->lock); | 1788 | write_unlock(&em_tree->lock); |
1786 | 1789 | ||
1787 | kfree(map); | 1790 | kfree(map); |
1788 | em->bdev = NULL; | 1791 | em->bdev = NULL; |
@@ -1807,12 +1810,15 @@ static int btrfs_relocate_sys_chunks(struct btrfs_root *root) | |||
1807 | struct btrfs_key found_key; | 1810 | struct btrfs_key found_key; |
1808 | u64 chunk_tree = chunk_root->root_key.objectid; | 1811 | u64 chunk_tree = chunk_root->root_key.objectid; |
1809 | u64 chunk_type; | 1812 | u64 chunk_type; |
1813 | bool retried = false; | ||
1814 | int failed = 0; | ||
1810 | int ret; | 1815 | int ret; |
1811 | 1816 | ||
1812 | path = btrfs_alloc_path(); | 1817 | path = btrfs_alloc_path(); |
1813 | if (!path) | 1818 | if (!path) |
1814 | return -ENOMEM; | 1819 | return -ENOMEM; |
1815 | 1820 | ||
1821 | again: | ||
1816 | key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; | 1822 | key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; |
1817 | key.offset = (u64)-1; | 1823 | key.offset = (u64)-1; |
1818 | key.type = BTRFS_CHUNK_ITEM_KEY; | 1824 | key.type = BTRFS_CHUNK_ITEM_KEY; |
@@ -1842,7 +1848,10 @@ static int btrfs_relocate_sys_chunks(struct btrfs_root *root) | |||
1842 | ret = btrfs_relocate_chunk(chunk_root, chunk_tree, | 1848 | ret = btrfs_relocate_chunk(chunk_root, chunk_tree, |
1843 | found_key.objectid, | 1849 | found_key.objectid, |
1844 | found_key.offset); | 1850 | found_key.offset); |
1845 | BUG_ON(ret); | 1851 | if (ret == -ENOSPC) |
1852 | failed++; | ||
1853 | else if (ret) | ||
1854 | BUG(); | ||
1846 | } | 1855 | } |
1847 | 1856 | ||
1848 | if (found_key.offset == 0) | 1857 | if (found_key.offset == 0) |
@@ -1850,6 +1859,14 @@ static int btrfs_relocate_sys_chunks(struct btrfs_root *root) | |||
1850 | key.offset = found_key.offset - 1; | 1859 | key.offset = found_key.offset - 1; |
1851 | } | 1860 | } |
1852 | ret = 0; | 1861 | ret = 0; |
1862 | if (failed && !retried) { | ||
1863 | failed = 0; | ||
1864 | retried = true; | ||
1865 | goto again; | ||
1866 | } else if (failed && retried) { | ||
1867 | WARN_ON(1); | ||
1868 | ret = -ENOSPC; | ||
1869 | } | ||
1853 | error: | 1870 | error: |
1854 | btrfs_free_path(path); | 1871 | btrfs_free_path(path); |
1855 | return ret; | 1872 | return ret; |
@@ -1894,6 +1911,8 @@ int btrfs_balance(struct btrfs_root *dev_root) | |||
1894 | continue; | 1911 | continue; |
1895 | 1912 | ||
1896 | ret = btrfs_shrink_device(device, old_size - size_to_free); | 1913 | ret = btrfs_shrink_device(device, old_size - size_to_free); |
1914 | if (ret == -ENOSPC) | ||
1915 | break; | ||
1897 | BUG_ON(ret); | 1916 | BUG_ON(ret); |
1898 | 1917 | ||
1899 | trans = btrfs_start_transaction(dev_root, 1); | 1918 | trans = btrfs_start_transaction(dev_root, 1); |
@@ -1938,9 +1957,8 @@ int btrfs_balance(struct btrfs_root *dev_root) | |||
1938 | chunk = btrfs_item_ptr(path->nodes[0], | 1957 | chunk = btrfs_item_ptr(path->nodes[0], |
1939 | path->slots[0], | 1958 | path->slots[0], |
1940 | struct btrfs_chunk); | 1959 | struct btrfs_chunk); |
1941 | key.offset = found_key.offset; | ||
1942 | /* chunk zero is special */ | 1960 | /* chunk zero is special */ |
1943 | if (key.offset == 0) | 1961 | if (found_key.offset == 0) |
1944 | break; | 1962 | break; |
1945 | 1963 | ||
1946 | btrfs_release_path(chunk_root, path); | 1964 | btrfs_release_path(chunk_root, path); |
@@ -1948,7 +1966,8 @@ int btrfs_balance(struct btrfs_root *dev_root) | |||
1948 | chunk_root->root_key.objectid, | 1966 | chunk_root->root_key.objectid, |
1949 | found_key.objectid, | 1967 | found_key.objectid, |
1950 | found_key.offset); | 1968 | found_key.offset); |
1951 | BUG_ON(ret); | 1969 | BUG_ON(ret && ret != -ENOSPC); |
1970 | key.offset = found_key.offset - 1; | ||
1952 | } | 1971 | } |
1953 | ret = 0; | 1972 | ret = 0; |
1954 | error: | 1973 | error: |
@@ -1974,10 +1993,13 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
1974 | u64 chunk_offset; | 1993 | u64 chunk_offset; |
1975 | int ret; | 1994 | int ret; |
1976 | int slot; | 1995 | int slot; |
1996 | int failed = 0; | ||
1997 | bool retried = false; | ||
1977 | struct extent_buffer *l; | 1998 | struct extent_buffer *l; |
1978 | struct btrfs_key key; | 1999 | struct btrfs_key key; |
1979 | struct btrfs_super_block *super_copy = &root->fs_info->super_copy; | 2000 | struct btrfs_super_block *super_copy = &root->fs_info->super_copy; |
1980 | u64 old_total = btrfs_super_total_bytes(super_copy); | 2001 | u64 old_total = btrfs_super_total_bytes(super_copy); |
2002 | u64 old_size = device->total_bytes; | ||
1981 | u64 diff = device->total_bytes - new_size; | 2003 | u64 diff = device->total_bytes - new_size; |
1982 | 2004 | ||
1983 | if (new_size >= device->total_bytes) | 2005 | if (new_size >= device->total_bytes) |
@@ -1987,12 +2009,6 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
1987 | if (!path) | 2009 | if (!path) |
1988 | return -ENOMEM; | 2010 | return -ENOMEM; |
1989 | 2011 | ||
1990 | trans = btrfs_start_transaction(root, 1); | ||
1991 | if (!trans) { | ||
1992 | ret = -ENOMEM; | ||
1993 | goto done; | ||
1994 | } | ||
1995 | |||
1996 | path->reada = 2; | 2012 | path->reada = 2; |
1997 | 2013 | ||
1998 | lock_chunks(root); | 2014 | lock_chunks(root); |
@@ -2001,8 +2017,8 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
2001 | if (device->writeable) | 2017 | if (device->writeable) |
2002 | device->fs_devices->total_rw_bytes -= diff; | 2018 | device->fs_devices->total_rw_bytes -= diff; |
2003 | unlock_chunks(root); | 2019 | unlock_chunks(root); |
2004 | btrfs_end_transaction(trans, root); | ||
2005 | 2020 | ||
2021 | again: | ||
2006 | key.objectid = device->devid; | 2022 | key.objectid = device->devid; |
2007 | key.offset = (u64)-1; | 2023 | key.offset = (u64)-1; |
2008 | key.type = BTRFS_DEV_EXTENT_KEY; | 2024 | key.type = BTRFS_DEV_EXTENT_KEY; |
@@ -2017,6 +2033,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
2017 | goto done; | 2033 | goto done; |
2018 | if (ret) { | 2034 | if (ret) { |
2019 | ret = 0; | 2035 | ret = 0; |
2036 | btrfs_release_path(root, path); | ||
2020 | break; | 2037 | break; |
2021 | } | 2038 | } |
2022 | 2039 | ||
@@ -2024,14 +2041,18 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
2024 | slot = path->slots[0]; | 2041 | slot = path->slots[0]; |
2025 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | 2042 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); |
2026 | 2043 | ||
2027 | if (key.objectid != device->devid) | 2044 | if (key.objectid != device->devid) { |
2045 | btrfs_release_path(root, path); | ||
2028 | break; | 2046 | break; |
2047 | } | ||
2029 | 2048 | ||
2030 | dev_extent = btrfs_item_ptr(l, slot, struct btrfs_dev_extent); | 2049 | dev_extent = btrfs_item_ptr(l, slot, struct btrfs_dev_extent); |
2031 | length = btrfs_dev_extent_length(l, dev_extent); | 2050 | length = btrfs_dev_extent_length(l, dev_extent); |
2032 | 2051 | ||
2033 | if (key.offset + length <= new_size) | 2052 | if (key.offset + length <= new_size) { |
2053 | btrfs_release_path(root, path); | ||
2034 | break; | 2054 | break; |
2055 | } | ||
2035 | 2056 | ||
2036 | chunk_tree = btrfs_dev_extent_chunk_tree(l, dev_extent); | 2057 | chunk_tree = btrfs_dev_extent_chunk_tree(l, dev_extent); |
2037 | chunk_objectid = btrfs_dev_extent_chunk_objectid(l, dev_extent); | 2058 | chunk_objectid = btrfs_dev_extent_chunk_objectid(l, dev_extent); |
@@ -2040,8 +2061,26 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
2040 | 2061 | ||
2041 | ret = btrfs_relocate_chunk(root, chunk_tree, chunk_objectid, | 2062 | ret = btrfs_relocate_chunk(root, chunk_tree, chunk_objectid, |
2042 | chunk_offset); | 2063 | chunk_offset); |
2043 | if (ret) | 2064 | if (ret && ret != -ENOSPC) |
2044 | goto done; | 2065 | goto done; |
2066 | if (ret == -ENOSPC) | ||
2067 | failed++; | ||
2068 | key.offset -= 1; | ||
2069 | } | ||
2070 | |||
2071 | if (failed && !retried) { | ||
2072 | failed = 0; | ||
2073 | retried = true; | ||
2074 | goto again; | ||
2075 | } else if (failed && retried) { | ||
2076 | ret = -ENOSPC; | ||
2077 | lock_chunks(root); | ||
2078 | |||
2079 | device->total_bytes = old_size; | ||
2080 | if (device->writeable) | ||
2081 | device->fs_devices->total_rw_bytes += diff; | ||
2082 | unlock_chunks(root); | ||
2083 | goto done; | ||
2045 | } | 2084 | } |
2046 | 2085 | ||
2047 | /* Shrinking succeeded, else we would be at "done". */ | 2086 | /* Shrinking succeeded, else we would be at "done". */ |
@@ -2294,9 +2333,9 @@ again: | |||
2294 | em->block_len = em->len; | 2333 | em->block_len = em->len; |
2295 | 2334 | ||
2296 | em_tree = &extent_root->fs_info->mapping_tree.map_tree; | 2335 | em_tree = &extent_root->fs_info->mapping_tree.map_tree; |
2297 | spin_lock(&em_tree->lock); | 2336 | write_lock(&em_tree->lock); |
2298 | ret = add_extent_mapping(em_tree, em); | 2337 | ret = add_extent_mapping(em_tree, em); |
2299 | spin_unlock(&em_tree->lock); | 2338 | write_unlock(&em_tree->lock); |
2300 | BUG_ON(ret); | 2339 | BUG_ON(ret); |
2301 | free_extent_map(em); | 2340 | free_extent_map(em); |
2302 | 2341 | ||
@@ -2491,9 +2530,9 @@ int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset) | |||
2491 | int readonly = 0; | 2530 | int readonly = 0; |
2492 | int i; | 2531 | int i; |
2493 | 2532 | ||
2494 | spin_lock(&map_tree->map_tree.lock); | 2533 | read_lock(&map_tree->map_tree.lock); |
2495 | em = lookup_extent_mapping(&map_tree->map_tree, chunk_offset, 1); | 2534 | em = lookup_extent_mapping(&map_tree->map_tree, chunk_offset, 1); |
2496 | spin_unlock(&map_tree->map_tree.lock); | 2535 | read_unlock(&map_tree->map_tree.lock); |
2497 | if (!em) | 2536 | if (!em) |
2498 | return 1; | 2537 | return 1; |
2499 | 2538 | ||
@@ -2518,11 +2557,11 @@ void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree) | |||
2518 | struct extent_map *em; | 2557 | struct extent_map *em; |
2519 | 2558 | ||
2520 | while (1) { | 2559 | while (1) { |
2521 | spin_lock(&tree->map_tree.lock); | 2560 | write_lock(&tree->map_tree.lock); |
2522 | em = lookup_extent_mapping(&tree->map_tree, 0, (u64)-1); | 2561 | em = lookup_extent_mapping(&tree->map_tree, 0, (u64)-1); |
2523 | if (em) | 2562 | if (em) |
2524 | remove_extent_mapping(&tree->map_tree, em); | 2563 | remove_extent_mapping(&tree->map_tree, em); |
2525 | spin_unlock(&tree->map_tree.lock); | 2564 | write_unlock(&tree->map_tree.lock); |
2526 | if (!em) | 2565 | if (!em) |
2527 | break; | 2566 | break; |
2528 | kfree(em->bdev); | 2567 | kfree(em->bdev); |
@@ -2540,9 +2579,9 @@ int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len) | |||
2540 | struct extent_map_tree *em_tree = &map_tree->map_tree; | 2579 | struct extent_map_tree *em_tree = &map_tree->map_tree; |
2541 | int ret; | 2580 | int ret; |
2542 | 2581 | ||
2543 | spin_lock(&em_tree->lock); | 2582 | read_lock(&em_tree->lock); |
2544 | em = lookup_extent_mapping(em_tree, logical, len); | 2583 | em = lookup_extent_mapping(em_tree, logical, len); |
2545 | spin_unlock(&em_tree->lock); | 2584 | read_unlock(&em_tree->lock); |
2546 | BUG_ON(!em); | 2585 | BUG_ON(!em); |
2547 | 2586 | ||
2548 | BUG_ON(em->start > logical || em->start + em->len < logical); | 2587 | BUG_ON(em->start > logical || em->start + em->len < logical); |
@@ -2604,9 +2643,9 @@ again: | |||
2604 | atomic_set(&multi->error, 0); | 2643 | atomic_set(&multi->error, 0); |
2605 | } | 2644 | } |
2606 | 2645 | ||
2607 | spin_lock(&em_tree->lock); | 2646 | read_lock(&em_tree->lock); |
2608 | em = lookup_extent_mapping(em_tree, logical, *length); | 2647 | em = lookup_extent_mapping(em_tree, logical, *length); |
2609 | spin_unlock(&em_tree->lock); | 2648 | read_unlock(&em_tree->lock); |
2610 | 2649 | ||
2611 | if (!em && unplug_page) | 2650 | if (!em && unplug_page) |
2612 | return 0; | 2651 | return 0; |
@@ -2763,9 +2802,9 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, | |||
2763 | u64 stripe_nr; | 2802 | u64 stripe_nr; |
2764 | int i, j, nr = 0; | 2803 | int i, j, nr = 0; |
2765 | 2804 | ||
2766 | spin_lock(&em_tree->lock); | 2805 | read_lock(&em_tree->lock); |
2767 | em = lookup_extent_mapping(em_tree, chunk_start, 1); | 2806 | em = lookup_extent_mapping(em_tree, chunk_start, 1); |
2768 | spin_unlock(&em_tree->lock); | 2807 | read_unlock(&em_tree->lock); |
2769 | 2808 | ||
2770 | BUG_ON(!em || em->start != chunk_start); | 2809 | BUG_ON(!em || em->start != chunk_start); |
2771 | map = (struct map_lookup *)em->bdev; | 2810 | map = (struct map_lookup *)em->bdev; |
@@ -3053,9 +3092,9 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | |||
3053 | logical = key->offset; | 3092 | logical = key->offset; |
3054 | length = btrfs_chunk_length(leaf, chunk); | 3093 | length = btrfs_chunk_length(leaf, chunk); |
3055 | 3094 | ||
3056 | spin_lock(&map_tree->map_tree.lock); | 3095 | read_lock(&map_tree->map_tree.lock); |
3057 | em = lookup_extent_mapping(&map_tree->map_tree, logical, 1); | 3096 | em = lookup_extent_mapping(&map_tree->map_tree, logical, 1); |
3058 | spin_unlock(&map_tree->map_tree.lock); | 3097 | read_unlock(&map_tree->map_tree.lock); |
3059 | 3098 | ||
3060 | /* already mapped? */ | 3099 | /* already mapped? */ |
3061 | if (em && em->start <= logical && em->start + em->len > logical) { | 3100 | if (em && em->start <= logical && em->start + em->len > logical) { |
@@ -3114,9 +3153,9 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | |||
3114 | map->stripes[i].dev->in_fs_metadata = 1; | 3153 | map->stripes[i].dev->in_fs_metadata = 1; |
3115 | } | 3154 | } |
3116 | 3155 | ||
3117 | spin_lock(&map_tree->map_tree.lock); | 3156 | write_lock(&map_tree->map_tree.lock); |
3118 | ret = add_extent_mapping(&map_tree->map_tree, em); | 3157 | ret = add_extent_mapping(&map_tree->map_tree, em); |
3119 | spin_unlock(&map_tree->map_tree.lock); | 3158 | write_unlock(&map_tree->map_tree.lock); |
3120 | BUG_ON(ret); | 3159 | BUG_ON(ret); |
3121 | free_extent_map(em); | 3160 | free_extent_map(em); |
3122 | 3161 | ||