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/btrfs/disk-io.c | |
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/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 208 |
1 files changed, 143 insertions, 65 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 | ||