diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2008-12-08 16:46:26 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-12-08 16:46:26 -0500 |
commit | a512bbf855ff0af474257475f2e6da7acd854f52 (patch) | |
tree | 1b2cfcf4152e09f32a6cb0bcbd798d5dab2f5490 /fs | |
parent | d20f7043fa65659136c1a7c3c456eeeb5c6f431f (diff) |
Btrfs: superblock duplication
This patch implements superblock duplication. Superblocks
are stored at offset 16K, 64M and 256G on every devices.
Spaces used by superblocks are preserved by the allocator,
which uses a reverse mapping function to find the logical
addresses that correspond to superblocks. Thank you,
Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/disk-io.c | 208 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 17 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 54 | ||||
-rw-r--r-- | fs/btrfs/free-space-cache.c | 1 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 3 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 107 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 6 |
8 files changed, 279 insertions, 119 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 61dc3b2c834b..c72f4f3b912c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1595,8 +1595,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1595 | fs_info, BTRFS_ROOT_TREE_OBJECTID); | 1595 | fs_info, BTRFS_ROOT_TREE_OBJECTID); |
1596 | 1596 | ||
1597 | 1597 | ||
1598 | bh = __bread(fs_devices->latest_bdev, | 1598 | bh = btrfs_read_dev_super(fs_devices->latest_bdev); |
1599 | BTRFS_SUPER_INFO_OFFSET / 4096, 4096); | ||
1600 | if (!bh) | 1599 | if (!bh) |
1601 | goto fail_iput; | 1600 | goto fail_iput; |
1602 | 1601 | ||
@@ -1710,7 +1709,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1710 | } | 1709 | } |
1711 | 1710 | ||
1712 | mutex_lock(&fs_info->chunk_mutex); | 1711 | mutex_lock(&fs_info->chunk_mutex); |
1713 | ret = btrfs_read_sys_array(tree_root); | 1712 | ret = btrfs_read_sys_array(tree_root, btrfs_super_bytenr(disk_super)); |
1714 | mutex_unlock(&fs_info->chunk_mutex); | 1713 | mutex_unlock(&fs_info->chunk_mutex); |
1715 | if (ret) { | 1714 | if (ret) { |
1716 | printk("btrfs: failed to read the system array on %s\n", | 1715 | printk("btrfs: failed to read the system array on %s\n", |
@@ -1905,19 +1904,147 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate) | |||
1905 | put_bh(bh); | 1904 | put_bh(bh); |
1906 | } | 1905 | } |
1907 | 1906 | ||
1908 | static int write_all_supers(struct btrfs_root *root) | 1907 | struct buffer_head *btrfs_read_dev_super(struct block_device *bdev) |
1908 | { | ||
1909 | struct buffer_head *bh; | ||
1910 | struct buffer_head *latest = NULL; | ||
1911 | struct btrfs_super_block *super; | ||
1912 | int i; | ||
1913 | u64 transid = 0; | ||
1914 | u64 bytenr; | ||
1915 | |||
1916 | /* we would like to check all the supers, but that would make | ||
1917 | * a btrfs mount succeed after a mkfs from a different FS. | ||
1918 | * So, we need to add a special mount option to scan for | ||
1919 | * later supers, using BTRFS_SUPER_MIRROR_MAX instead | ||
1920 | */ | ||
1921 | for (i = 0; i < 1; i++) { | ||
1922 | bytenr = btrfs_sb_offset(i); | ||
1923 | if (bytenr + 4096 >= i_size_read(bdev->bd_inode)) | ||
1924 | break; | ||
1925 | bh = __bread(bdev, bytenr / 4096, 4096); | ||
1926 | if (!bh) | ||
1927 | continue; | ||
1928 | |||
1929 | super = (struct btrfs_super_block *)bh->b_data; | ||
1930 | if (btrfs_super_bytenr(super) != bytenr || | ||
1931 | strncmp((char *)(&super->magic), BTRFS_MAGIC, | ||
1932 | sizeof(super->magic))) { | ||
1933 | brelse(bh); | ||
1934 | continue; | ||
1935 | } | ||
1936 | |||
1937 | if (!latest || btrfs_super_generation(super) > transid) { | ||
1938 | brelse(latest); | ||
1939 | latest = bh; | ||
1940 | transid = btrfs_super_generation(super); | ||
1941 | } else { | ||
1942 | brelse(bh); | ||
1943 | } | ||
1944 | } | ||
1945 | return latest; | ||
1946 | } | ||
1947 | |||
1948 | static int write_dev_supers(struct btrfs_device *device, | ||
1949 | struct btrfs_super_block *sb, | ||
1950 | int do_barriers, int wait, int max_mirrors) | ||
1951 | { | ||
1952 | struct buffer_head *bh; | ||
1953 | int i; | ||
1954 | int ret; | ||
1955 | int errors = 0; | ||
1956 | u32 crc; | ||
1957 | u64 bytenr; | ||
1958 | int last_barrier = 0; | ||
1959 | |||
1960 | if (max_mirrors == 0) | ||
1961 | max_mirrors = BTRFS_SUPER_MIRROR_MAX; | ||
1962 | |||
1963 | /* make sure only the last submit_bh does a barrier */ | ||
1964 | if (do_barriers) { | ||
1965 | for (i = 0; i < max_mirrors; i++) { | ||
1966 | bytenr = btrfs_sb_offset(i); | ||
1967 | if (bytenr + BTRFS_SUPER_INFO_SIZE >= | ||
1968 | device->total_bytes) | ||
1969 | break; | ||
1970 | last_barrier = i; | ||
1971 | } | ||
1972 | } | ||
1973 | |||
1974 | for (i = 0; i < max_mirrors; i++) { | ||
1975 | bytenr = btrfs_sb_offset(i); | ||
1976 | if (bytenr + BTRFS_SUPER_INFO_SIZE >= device->total_bytes) | ||
1977 | break; | ||
1978 | |||
1979 | if (wait) { | ||
1980 | bh = __find_get_block(device->bdev, bytenr / 4096, | ||
1981 | BTRFS_SUPER_INFO_SIZE); | ||
1982 | BUG_ON(!bh); | ||
1983 | brelse(bh); | ||
1984 | wait_on_buffer(bh); | ||
1985 | if (buffer_uptodate(bh)) { | ||
1986 | brelse(bh); | ||
1987 | continue; | ||
1988 | } | ||
1989 | } else { | ||
1990 | btrfs_set_super_bytenr(sb, bytenr); | ||
1991 | |||
1992 | crc = ~(u32)0; | ||
1993 | crc = btrfs_csum_data(NULL, (char *)sb + | ||
1994 | BTRFS_CSUM_SIZE, crc, | ||
1995 | BTRFS_SUPER_INFO_SIZE - | ||
1996 | BTRFS_CSUM_SIZE); | ||
1997 | btrfs_csum_final(crc, sb->csum); | ||
1998 | |||
1999 | bh = __getblk(device->bdev, bytenr / 4096, | ||
2000 | BTRFS_SUPER_INFO_SIZE); | ||
2001 | memcpy(bh->b_data, sb, BTRFS_SUPER_INFO_SIZE); | ||
2002 | |||
2003 | set_buffer_uptodate(bh); | ||
2004 | get_bh(bh); | ||
2005 | lock_buffer(bh); | ||
2006 | bh->b_end_io = btrfs_end_buffer_write_sync; | ||
2007 | } | ||
2008 | |||
2009 | if (i == last_barrier && do_barriers && device->barriers) { | ||
2010 | ret = submit_bh(WRITE_BARRIER, bh); | ||
2011 | if (ret == -EOPNOTSUPP) { | ||
2012 | printk("btrfs: disabling barriers on dev %s\n", | ||
2013 | device->name); | ||
2014 | set_buffer_uptodate(bh); | ||
2015 | device->barriers = 0; | ||
2016 | get_bh(bh); | ||
2017 | lock_buffer(bh); | ||
2018 | ret = submit_bh(WRITE, bh); | ||
2019 | } | ||
2020 | } else { | ||
2021 | ret = submit_bh(WRITE, bh); | ||
2022 | } | ||
2023 | |||
2024 | if (!ret && wait) { | ||
2025 | wait_on_buffer(bh); | ||
2026 | if (!buffer_uptodate(bh)) | ||
2027 | errors++; | ||
2028 | } else if (ret) { | ||
2029 | errors++; | ||
2030 | } | ||
2031 | if (wait) | ||
2032 | brelse(bh); | ||
2033 | } | ||
2034 | return errors < i ? 0 : -1; | ||
2035 | } | ||
2036 | |||
2037 | int write_all_supers(struct btrfs_root *root, int max_mirrors) | ||
1909 | { | 2038 | { |
1910 | struct list_head *cur; | 2039 | struct list_head *cur; |
1911 | struct list_head *head = &root->fs_info->fs_devices->devices; | 2040 | struct list_head *head = &root->fs_info->fs_devices->devices; |
1912 | struct btrfs_device *dev; | 2041 | struct btrfs_device *dev; |
1913 | struct btrfs_super_block *sb; | 2042 | struct btrfs_super_block *sb; |
1914 | struct btrfs_dev_item *dev_item; | 2043 | struct btrfs_dev_item *dev_item; |
1915 | struct buffer_head *bh; | ||
1916 | int ret; | 2044 | int ret; |
1917 | int do_barriers; | 2045 | int do_barriers; |
1918 | int max_errors; | 2046 | int max_errors; |
1919 | int total_errors = 0; | 2047 | int total_errors = 0; |
1920 | u32 crc; | ||
1921 | u64 flags; | 2048 | u64 flags; |
1922 | 2049 | ||
1923 | max_errors = btrfs_super_num_devices(&root->fs_info->super_copy) - 1; | 2050 | max_errors = btrfs_super_num_devices(&root->fs_info->super_copy) - 1; |
@@ -1944,40 +2071,11 @@ static int write_all_supers(struct btrfs_root *root) | |||
1944 | btrfs_set_stack_device_sector_size(dev_item, dev->sector_size); | 2071 | btrfs_set_stack_device_sector_size(dev_item, dev->sector_size); |
1945 | memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE); | 2072 | memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE); |
1946 | memcpy(dev_item->fsid, dev->fs_devices->fsid, BTRFS_UUID_SIZE); | 2073 | memcpy(dev_item->fsid, dev->fs_devices->fsid, BTRFS_UUID_SIZE); |
2074 | |||
1947 | flags = btrfs_super_flags(sb); | 2075 | flags = btrfs_super_flags(sb); |
1948 | btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN); | 2076 | btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN); |
1949 | 2077 | ||
1950 | 2078 | ret = write_dev_supers(dev, sb, do_barriers, 0, max_mirrors); | |
1951 | crc = ~(u32)0; | ||
1952 | crc = btrfs_csum_data(root, (char *)sb + BTRFS_CSUM_SIZE, crc, | ||
1953 | BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE); | ||
1954 | btrfs_csum_final(crc, sb->csum); | ||
1955 | |||
1956 | bh = __getblk(dev->bdev, BTRFS_SUPER_INFO_OFFSET / 4096, | ||
1957 | BTRFS_SUPER_INFO_SIZE); | ||
1958 | |||
1959 | memcpy(bh->b_data, sb, BTRFS_SUPER_INFO_SIZE); | ||
1960 | dev->pending_io = bh; | ||
1961 | |||
1962 | get_bh(bh); | ||
1963 | set_buffer_uptodate(bh); | ||
1964 | lock_buffer(bh); | ||
1965 | bh->b_end_io = btrfs_end_buffer_write_sync; | ||
1966 | |||
1967 | if (do_barriers && dev->barriers) { | ||
1968 | ret = submit_bh(WRITE_BARRIER, bh); | ||
1969 | if (ret == -EOPNOTSUPP) { | ||
1970 | printk("btrfs: disabling barriers on dev %s\n", | ||
1971 | dev->name); | ||
1972 | set_buffer_uptodate(bh); | ||
1973 | dev->barriers = 0; | ||
1974 | get_bh(bh); | ||
1975 | lock_buffer(bh); | ||
1976 | ret = submit_bh(WRITE, bh); | ||
1977 | } | ||
1978 | } else { | ||
1979 | ret = submit_bh(WRITE, bh); | ||
1980 | } | ||
1981 | if (ret) | 2079 | if (ret) |
1982 | total_errors++; | 2080 | total_errors++; |
1983 | } | 2081 | } |
@@ -1985,8 +2083,8 @@ static int write_all_supers(struct btrfs_root *root) | |||
1985 | printk("btrfs: %d errors while writing supers\n", total_errors); | 2083 | printk("btrfs: %d errors while writing supers\n", total_errors); |
1986 | BUG(); | 2084 | BUG(); |
1987 | } | 2085 | } |
1988 | total_errors = 0; | ||
1989 | 2086 | ||
2087 | total_errors = 0; | ||
1990 | list_for_each(cur, head) { | 2088 | list_for_each(cur, head) { |
1991 | dev = list_entry(cur, struct btrfs_device, dev_list); | 2089 | dev = list_entry(cur, struct btrfs_device, dev_list); |
1992 | if (!dev->bdev) | 2090 | if (!dev->bdev) |
@@ -1994,29 +2092,9 @@ static int write_all_supers(struct btrfs_root *root) | |||
1994 | if (!dev->in_fs_metadata || !dev->writeable) | 2092 | if (!dev->in_fs_metadata || !dev->writeable) |
1995 | continue; | 2093 | continue; |
1996 | 2094 | ||
1997 | BUG_ON(!dev->pending_io); | 2095 | ret = write_dev_supers(dev, sb, do_barriers, 1, max_mirrors); |
1998 | bh = dev->pending_io; | 2096 | if (ret) |
1999 | wait_on_buffer(bh); | 2097 | total_errors++; |
2000 | if (!buffer_uptodate(dev->pending_io)) { | ||
2001 | if (do_barriers && dev->barriers) { | ||
2002 | printk("btrfs: disabling barriers on dev %s\n", | ||
2003 | dev->name); | ||
2004 | set_buffer_uptodate(bh); | ||
2005 | get_bh(bh); | ||
2006 | lock_buffer(bh); | ||
2007 | dev->barriers = 0; | ||
2008 | ret = submit_bh(WRITE, bh); | ||
2009 | BUG_ON(ret); | ||
2010 | wait_on_buffer(bh); | ||
2011 | if (!buffer_uptodate(bh)) | ||
2012 | total_errors++; | ||
2013 | } else { | ||
2014 | total_errors++; | ||
2015 | } | ||
2016 | |||
2017 | } | ||
2018 | dev->pending_io = NULL; | ||
2019 | brelse(bh); | ||
2020 | } | 2098 | } |
2021 | if (total_errors > max_errors) { | 2099 | if (total_errors > max_errors) { |
2022 | printk("btrfs: %d errors while writing supers\n", total_errors); | 2100 | printk("btrfs: %d errors while writing supers\n", total_errors); |
@@ -2025,12 +2103,12 @@ static int write_all_supers(struct btrfs_root *root) | |||
2025 | return 0; | 2103 | return 0; |
2026 | } | 2104 | } |
2027 | 2105 | ||
2028 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | 2106 | int write_ctree_super(struct btrfs_trans_handle *trans, |
2029 | *root) | 2107 | struct btrfs_root *root, int max_mirrors) |
2030 | { | 2108 | { |
2031 | int ret; | 2109 | int ret; |
2032 | 2110 | ||
2033 | ret = write_all_supers(root); | 2111 | ret = write_all_supers(root, max_mirrors); |
2034 | return ret; | 2112 | return ret; |
2035 | } | 2113 | } |
2036 | 2114 | ||
@@ -2116,7 +2194,7 @@ int btrfs_commit_super(struct btrfs_root *root) | |||
2116 | ret = btrfs_write_and_wait_transaction(NULL, root); | 2194 | ret = btrfs_write_and_wait_transaction(NULL, root); |
2117 | BUG_ON(ret); | 2195 | BUG_ON(ret); |
2118 | 2196 | ||
2119 | ret = write_ctree_super(NULL, root); | 2197 | ret = write_ctree_super(NULL, root, 0); |
2120 | return ret; | 2198 | return ret; |
2121 | } | 2199 | } |
2122 | 2200 | ||
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 717e94811e4e..c0ff404c31b7 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -19,8 +19,20 @@ | |||
19 | #ifndef __DISKIO__ | 19 | #ifndef __DISKIO__ |
20 | #define __DISKIO__ | 20 | #define __DISKIO__ |
21 | 21 | ||
22 | #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) | 22 | #define BTRFS_SUPER_INFO_OFFSET (64 * 1024) |
23 | #define BTRFS_SUPER_INFO_SIZE 4096 | 23 | #define BTRFS_SUPER_INFO_SIZE 4096 |
24 | |||
25 | #define BTRFS_SUPER_MIRROR_MAX 3 | ||
26 | #define BTRFS_SUPER_MIRROR_SHIFT 12 | ||
27 | |||
28 | static inline u64 btrfs_sb_offset(int mirror) | ||
29 | { | ||
30 | u64 start = 16 * 1024; | ||
31 | if (mirror) | ||
32 | return start << (BTRFS_SUPER_MIRROR_SHIFT * mirror); | ||
33 | return BTRFS_SUPER_INFO_OFFSET; | ||
34 | } | ||
35 | |||
24 | struct btrfs_device; | 36 | struct btrfs_device; |
25 | struct btrfs_fs_devices; | 37 | struct btrfs_fs_devices; |
26 | 38 | ||
@@ -37,7 +49,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
37 | char *options); | 49 | char *options); |
38 | int close_ctree(struct btrfs_root *root); | 50 | int close_ctree(struct btrfs_root *root); |
39 | int write_ctree_super(struct btrfs_trans_handle *trans, | 51 | int write_ctree_super(struct btrfs_trans_handle *trans, |
40 | struct btrfs_root *root); | 52 | struct btrfs_root *root, int max_mirrors); |
53 | struct buffer_head *btrfs_read_dev_super(struct block_device *bdev); | ||
41 | int btrfs_commit_super(struct btrfs_root *root); | 54 | int btrfs_commit_super(struct btrfs_root *root); |
42 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, | 55 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, |
43 | u64 bytenr, u32 blocksize); | 56 | u64 bytenr, u32 blocksize); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index d15638529389..803647bc8400 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -189,6 +189,29 @@ static int add_new_free_space(struct btrfs_block_group_cache *block_group, | |||
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
191 | 191 | ||
192 | static int remove_sb_from_cache(struct btrfs_root *root, | ||
193 | struct btrfs_block_group_cache *cache) | ||
194 | { | ||
195 | u64 bytenr; | ||
196 | u64 *logical; | ||
197 | int stripe_len; | ||
198 | int i, nr, ret; | ||
199 | |||
200 | for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { | ||
201 | bytenr = btrfs_sb_offset(i); | ||
202 | ret = btrfs_rmap_block(&root->fs_info->mapping_tree, | ||
203 | cache->key.objectid, bytenr, 0, | ||
204 | &logical, &nr, &stripe_len); | ||
205 | BUG_ON(ret); | ||
206 | while (nr--) { | ||
207 | btrfs_remove_free_space(cache, logical[nr], | ||
208 | stripe_len); | ||
209 | } | ||
210 | kfree(logical); | ||
211 | } | ||
212 | return 0; | ||
213 | } | ||
214 | |||
192 | static int cache_block_group(struct btrfs_root *root, | 215 | static int cache_block_group(struct btrfs_root *root, |
193 | struct btrfs_block_group_cache *block_group) | 216 | struct btrfs_block_group_cache *block_group) |
194 | { | 217 | { |
@@ -197,9 +220,7 @@ static int cache_block_group(struct btrfs_root *root, | |||
197 | struct btrfs_key key; | 220 | struct btrfs_key key; |
198 | struct extent_buffer *leaf; | 221 | struct extent_buffer *leaf; |
199 | int slot; | 222 | int slot; |
200 | u64 last = 0; | 223 | u64 last = block_group->key.objectid; |
201 | u64 first_free; | ||
202 | int found = 0; | ||
203 | 224 | ||
204 | if (!block_group) | 225 | if (!block_group) |
205 | return 0; | 226 | return 0; |
@@ -220,23 +241,13 @@ static int cache_block_group(struct btrfs_root *root, | |||
220 | * skip the locking here | 241 | * skip the locking here |
221 | */ | 242 | */ |
222 | path->skip_locking = 1; | 243 | path->skip_locking = 1; |
223 | first_free = max_t(u64, block_group->key.objectid, | 244 | key.objectid = last; |
224 | BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE); | ||
225 | key.objectid = block_group->key.objectid; | ||
226 | key.offset = 0; | 245 | key.offset = 0; |
227 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 246 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
228 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 247 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
229 | if (ret < 0) | 248 | if (ret < 0) |
230 | goto err; | 249 | goto err; |
231 | ret = btrfs_previous_item(root, path, 0, BTRFS_EXTENT_ITEM_KEY); | 250 | |
232 | if (ret < 0) | ||
233 | goto err; | ||
234 | if (ret == 0) { | ||
235 | leaf = path->nodes[0]; | ||
236 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
237 | if (key.objectid + key.offset > first_free) | ||
238 | first_free = key.objectid + key.offset; | ||
239 | } | ||
240 | while(1) { | 251 | while(1) { |
241 | leaf = path->nodes[0]; | 252 | leaf = path->nodes[0]; |
242 | slot = path->slots[0]; | 253 | slot = path->slots[0]; |
@@ -258,11 +269,6 @@ static int cache_block_group(struct btrfs_root *root, | |||
258 | break; | 269 | break; |
259 | 270 | ||
260 | if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) { | 271 | if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) { |
261 | if (!found) { | ||
262 | last = first_free; | ||
263 | found = 1; | ||
264 | } | ||
265 | |||
266 | add_new_free_space(block_group, root->fs_info, last, | 272 | add_new_free_space(block_group, root->fs_info, last, |
267 | key.objectid); | 273 | key.objectid); |
268 | 274 | ||
@@ -272,13 +278,11 @@ next: | |||
272 | path->slots[0]++; | 278 | path->slots[0]++; |
273 | } | 279 | } |
274 | 280 | ||
275 | if (!found) | ||
276 | last = first_free; | ||
277 | |||
278 | add_new_free_space(block_group, root->fs_info, last, | 281 | add_new_free_space(block_group, root->fs_info, last, |
279 | block_group->key.objectid + | 282 | block_group->key.objectid + |
280 | block_group->key.offset); | 283 | block_group->key.offset); |
281 | 284 | ||
285 | remove_sb_from_cache(root, block_group); | ||
282 | block_group->cached = 1; | 286 | block_group->cached = 1; |
283 | ret = 0; | 287 | ret = 0; |
284 | err: | 288 | err: |
@@ -1974,10 +1978,8 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
1974 | if (alloc) { | 1978 | if (alloc) { |
1975 | old_val += num_bytes; | 1979 | old_val += num_bytes; |
1976 | cache->space_info->bytes_used += num_bytes; | 1980 | cache->space_info->bytes_used += num_bytes; |
1977 | if (cache->ro) { | 1981 | if (cache->ro) |
1978 | cache->space_info->bytes_readonly -= num_bytes; | 1982 | cache->space_info->bytes_readonly -= num_bytes; |
1979 | WARN_ON(1); | ||
1980 | } | ||
1981 | btrfs_set_block_group_used(&cache->item, old_val); | 1983 | btrfs_set_block_group_used(&cache->item, old_val); |
1982 | spin_unlock(&cache->lock); | 1984 | spin_unlock(&cache->lock); |
1983 | spin_unlock(&cache->space_info->lock); | 1985 | spin_unlock(&cache->space_info->lock); |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 09462adfbe33..2e69b9c30437 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -290,7 +290,6 @@ __btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, | |||
290 | ret = -EINVAL; | 290 | ret = -EINVAL; |
291 | goto out; | 291 | goto out; |
292 | } | 292 | } |
293 | |||
294 | unlink_free_space(block_group, info); | 293 | unlink_free_space(block_group, info); |
295 | 294 | ||
296 | if (info->bytes == bytes) { | 295 | if (info->bytes == bytes) { |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index c38f6a0e30b1..47cd5fcad2c8 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -1038,7 +1038,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1038 | mutex_unlock(&root->fs_info->trans_mutex); | 1038 | mutex_unlock(&root->fs_info->trans_mutex); |
1039 | ret = btrfs_write_and_wait_transaction(trans, root); | 1039 | ret = btrfs_write_and_wait_transaction(trans, root); |
1040 | BUG_ON(ret); | 1040 | BUG_ON(ret); |
1041 | write_ctree_super(trans, root); | 1041 | write_ctree_super(trans, root, 0); |
1042 | 1042 | ||
1043 | /* | 1043 | /* |
1044 | * the super is written, we can safely allow the tree-loggers | 1044 | * the super is written, we can safely allow the tree-loggers |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 08469ec05850..d3f9c2c663c4 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -1996,7 +1996,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
1996 | btrfs_set_super_log_root_level(&root->fs_info->super_for_commit, | 1996 | btrfs_set_super_log_root_level(&root->fs_info->super_for_commit, |
1997 | btrfs_header_level(log->fs_info->log_root_tree->node)); | 1997 | btrfs_header_level(log->fs_info->log_root_tree->node)); |
1998 | 1998 | ||
1999 | write_ctree_super(trans, log->fs_info->tree_root); | 1999 | write_ctree_super(trans, log->fs_info->tree_root, 2); |
2000 | log->fs_info->tree_log_transid++; | 2000 | log->fs_info->tree_log_transid++; |
2001 | log->fs_info->tree_log_batch = 0; | 2001 | log->fs_info->tree_log_batch = 0; |
2002 | atomic_set(&log->fs_info->tree_log_commit, 0); | 2002 | atomic_set(&log->fs_info->tree_log_commit, 0); |
@@ -2006,7 +2006,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2006 | out: | 2006 | out: |
2007 | mutex_unlock(&log->fs_info->tree_log_mutex); | 2007 | mutex_unlock(&log->fs_info->tree_log_mutex); |
2008 | return 0; | 2008 | return 0; |
2009 | |||
2010 | } | 2009 | } |
2011 | 2010 | ||
2012 | /* * free all the extents used by the tree log. This should be called | 2011 | /* * free all the extents used by the tree log. This should be called |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 2049d179ccd5..a79b3cc09e94 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -423,15 +423,11 @@ int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, | |||
423 | } | 423 | } |
424 | set_blocksize(bdev, 4096); | 424 | set_blocksize(bdev, 4096); |
425 | 425 | ||
426 | bh = __bread(bdev, BTRFS_SUPER_INFO_OFFSET / 4096, 4096); | 426 | bh = btrfs_read_dev_super(bdev); |
427 | if (!bh) | 427 | if (!bh) |
428 | goto error_close; | 428 | goto error_close; |
429 | 429 | ||
430 | disk_super = (struct btrfs_super_block *)bh->b_data; | 430 | disk_super = (struct btrfs_super_block *)bh->b_data; |
431 | if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, | ||
432 | sizeof(disk_super->magic))) | ||
433 | goto error_brelse; | ||
434 | |||
435 | devid = le64_to_cpu(disk_super->dev_item.devid); | 431 | devid = le64_to_cpu(disk_super->dev_item.devid); |
436 | if (devid != device->devid) | 432 | if (devid != device->devid) |
437 | goto error_brelse; | 433 | goto error_brelse; |
@@ -529,17 +525,12 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
529 | ret = set_blocksize(bdev, 4096); | 525 | ret = set_blocksize(bdev, 4096); |
530 | if (ret) | 526 | if (ret) |
531 | goto error_close; | 527 | goto error_close; |
532 | bh = __bread(bdev, BTRFS_SUPER_INFO_OFFSET / 4096, 4096); | 528 | bh = btrfs_read_dev_super(bdev); |
533 | if (!bh) { | 529 | if (!bh) { |
534 | ret = -EIO; | 530 | ret = -EIO; |
535 | goto error_close; | 531 | goto error_close; |
536 | } | 532 | } |
537 | disk_super = (struct btrfs_super_block *)bh->b_data; | 533 | disk_super = (struct btrfs_super_block *)bh->b_data; |
538 | if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, | ||
539 | sizeof(disk_super->magic))) { | ||
540 | ret = -EINVAL; | ||
541 | goto error_brelse; | ||
542 | } | ||
543 | devid = le64_to_cpu(disk_super->dev_item.devid); | 534 | devid = le64_to_cpu(disk_super->dev_item.devid); |
544 | transid = btrfs_super_generation(disk_super); | 535 | transid = btrfs_super_generation(disk_super); |
545 | if (disk_super->label[0]) | 536 | if (disk_super->label[0]) |
@@ -553,7 +544,6 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
553 | printk("devid %Lu transid %Lu %s\n", devid, transid, path); | 544 | printk("devid %Lu transid %Lu %s\n", devid, transid, path); |
554 | ret = device_list_add(path, disk_super, devid, fs_devices_ret); | 545 | ret = device_list_add(path, disk_super, devid, fs_devices_ret); |
555 | 546 | ||
556 | error_brelse: | ||
557 | brelse(bh); | 547 | brelse(bh); |
558 | error_close: | 548 | error_close: |
559 | close_bdev_exclusive(bdev, flags); | 549 | close_bdev_exclusive(bdev, flags); |
@@ -1016,17 +1006,12 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1016 | } | 1006 | } |
1017 | 1007 | ||
1018 | set_blocksize(bdev, 4096); | 1008 | set_blocksize(bdev, 4096); |
1019 | bh = __bread(bdev, BTRFS_SUPER_INFO_OFFSET / 4096, 4096); | 1009 | bh = btrfs_read_dev_super(bdev); |
1020 | if (!bh) { | 1010 | if (!bh) { |
1021 | ret = -EIO; | 1011 | ret = -EIO; |
1022 | goto error_close; | 1012 | goto error_close; |
1023 | } | 1013 | } |
1024 | disk_super = (struct btrfs_super_block *)bh->b_data; | 1014 | disk_super = (struct btrfs_super_block *)bh->b_data; |
1025 | if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, | ||
1026 | sizeof(disk_super->magic))) { | ||
1027 | ret = -ENOENT; | ||
1028 | goto error_brelse; | ||
1029 | } | ||
1030 | devid = le64_to_cpu(disk_super->dev_item.devid); | 1015 | devid = le64_to_cpu(disk_super->dev_item.devid); |
1031 | dev_uuid = disk_super->dev_item.uuid; | 1016 | dev_uuid = disk_super->dev_item.uuid; |
1032 | device = btrfs_find_device(root, devid, dev_uuid, | 1017 | device = btrfs_find_device(root, devid, dev_uuid, |
@@ -2563,6 +2548,88 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
2563 | mirror_num, NULL); | 2548 | mirror_num, NULL); |
2564 | } | 2549 | } |
2565 | 2550 | ||
2551 | int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, | ||
2552 | u64 chunk_start, u64 physical, u64 devid, | ||
2553 | u64 **logical, int *naddrs, int *stripe_len) | ||
2554 | { | ||
2555 | struct extent_map_tree *em_tree = &map_tree->map_tree; | ||
2556 | struct extent_map *em; | ||
2557 | struct map_lookup *map; | ||
2558 | u64 *buf; | ||
2559 | u64 bytenr; | ||
2560 | u64 length; | ||
2561 | u64 stripe_nr; | ||
2562 | int i, j, nr = 0; | ||
2563 | |||
2564 | spin_lock(&em_tree->lock); | ||
2565 | em = lookup_extent_mapping(em_tree, chunk_start, 1); | ||
2566 | spin_unlock(&em_tree->lock); | ||
2567 | |||
2568 | BUG_ON(!em || em->start != chunk_start); | ||
2569 | map = (struct map_lookup *)em->bdev; | ||
2570 | |||
2571 | length = em->len; | ||
2572 | if (map->type & BTRFS_BLOCK_GROUP_RAID10) | ||
2573 | do_div(length, map->num_stripes / map->sub_stripes); | ||
2574 | else if (map->type & BTRFS_BLOCK_GROUP_RAID0) | ||
2575 | do_div(length, map->num_stripes); | ||
2576 | |||
2577 | buf = kzalloc(sizeof(u64) * map->num_stripes, GFP_NOFS); | ||
2578 | BUG_ON(!buf); | ||
2579 | |||
2580 | for (i = 0; i < map->num_stripes; i++) { | ||
2581 | if (devid && map->stripes[i].dev->devid != devid) | ||
2582 | continue; | ||
2583 | if (map->stripes[i].physical > physical || | ||
2584 | map->stripes[i].physical + length <= physical) | ||
2585 | continue; | ||
2586 | |||
2587 | stripe_nr = physical - map->stripes[i].physical; | ||
2588 | do_div(stripe_nr, map->stripe_len); | ||
2589 | |||
2590 | if (map->type & BTRFS_BLOCK_GROUP_RAID10) { | ||
2591 | stripe_nr = stripe_nr * map->num_stripes + i; | ||
2592 | do_div(stripe_nr, map->sub_stripes); | ||
2593 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID0) { | ||
2594 | stripe_nr = stripe_nr * map->num_stripes + i; | ||
2595 | } | ||
2596 | bytenr = chunk_start + stripe_nr * map->stripe_len; | ||
2597 | for (j = 0; j < nr; j++) { | ||
2598 | if (buf[j] == bytenr) | ||
2599 | break; | ||
2600 | } | ||
2601 | if (j == nr) | ||
2602 | buf[nr++] = bytenr; | ||
2603 | } | ||
2604 | |||
2605 | for (i = 0; i > nr; i++) { | ||
2606 | struct btrfs_multi_bio *multi; | ||
2607 | struct btrfs_bio_stripe *stripe; | ||
2608 | int ret; | ||
2609 | |||
2610 | length = 1; | ||
2611 | ret = btrfs_map_block(map_tree, WRITE, buf[i], | ||
2612 | &length, &multi, 0); | ||
2613 | BUG_ON(ret); | ||
2614 | |||
2615 | stripe = multi->stripes; | ||
2616 | for (j = 0; j < multi->num_stripes; j++) { | ||
2617 | if (stripe->physical >= physical && | ||
2618 | physical < stripe->physical + length) | ||
2619 | break; | ||
2620 | } | ||
2621 | BUG_ON(j >= multi->num_stripes); | ||
2622 | kfree(multi); | ||
2623 | } | ||
2624 | |||
2625 | *logical = buf; | ||
2626 | *naddrs = nr; | ||
2627 | *stripe_len = map->stripe_len; | ||
2628 | |||
2629 | free_extent_map(em); | ||
2630 | return 0; | ||
2631 | } | ||
2632 | |||
2566 | int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, | 2633 | int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, |
2567 | u64 logical, struct page *page) | 2634 | u64 logical, struct page *page) |
2568 | { | 2635 | { |
@@ -3003,7 +3070,7 @@ int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf) | |||
3003 | return read_one_dev(root, buf, dev_item); | 3070 | return read_one_dev(root, buf, dev_item); |
3004 | } | 3071 | } |
3005 | 3072 | ||
3006 | int btrfs_read_sys_array(struct btrfs_root *root) | 3073 | int btrfs_read_sys_array(struct btrfs_root *root, u64 sb_bytenr) |
3007 | { | 3074 | { |
3008 | struct btrfs_super_block *super_copy = &root->fs_info->super_copy; | 3075 | struct btrfs_super_block *super_copy = &root->fs_info->super_copy; |
3009 | struct extent_buffer *sb; | 3076 | struct extent_buffer *sb; |
@@ -3018,7 +3085,7 @@ int btrfs_read_sys_array(struct btrfs_root *root) | |||
3018 | u32 cur; | 3085 | u32 cur; |
3019 | struct btrfs_key key; | 3086 | struct btrfs_key key; |
3020 | 3087 | ||
3021 | sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET, | 3088 | sb = btrfs_find_create_tree_block(root, sb_bytenr, |
3022 | BTRFS_SUPER_INFO_SIZE); | 3089 | BTRFS_SUPER_INFO_SIZE); |
3023 | if (!sb) | 3090 | if (!sb) |
3024 | return -ENOMEM; | 3091 | return -ENOMEM; |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index fcbdcb3ae13e..bdebe83c3195 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -28,7 +28,6 @@ struct btrfs_device { | |||
28 | struct list_head dev_alloc_list; | 28 | struct list_head dev_alloc_list; |
29 | struct btrfs_fs_devices *fs_devices; | 29 | struct btrfs_fs_devices *fs_devices; |
30 | struct btrfs_root *dev_root; | 30 | struct btrfs_root *dev_root; |
31 | struct buffer_head *pending_io; | ||
32 | struct bio *pending_bios; | 31 | struct bio *pending_bios; |
33 | struct bio *pending_bio_tail; | 32 | struct bio *pending_bio_tail; |
34 | int running_pending; | 33 | int running_pending; |
@@ -125,7 +124,10 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, | |||
125 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | 124 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, |
126 | u64 logical, u64 *length, | 125 | u64 logical, u64 *length, |
127 | struct btrfs_multi_bio **multi_ret, int mirror_num); | 126 | struct btrfs_multi_bio **multi_ret, int mirror_num); |
128 | int btrfs_read_sys_array(struct btrfs_root *root); | 127 | int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, |
128 | u64 chunk_start, u64 physical, u64 devid, | ||
129 | u64 **logical, int *naddrs, int *stripe_len); | ||
130 | int btrfs_read_sys_array(struct btrfs_root *root, u64 sb_bytenr); | ||
129 | int btrfs_read_chunk_tree(struct btrfs_root *root); | 131 | int btrfs_read_chunk_tree(struct btrfs_root *root); |
130 | int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | 132 | int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, |
131 | struct btrfs_root *extent_root, u64 type); | 133 | struct btrfs_root *extent_root, u64 type); |