diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index b7ddc77fa568..0d50d49d990a 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -2020,6 +2020,17 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev) | |||
2020 | return latest; | 2020 | return latest; |
2021 | } | 2021 | } |
2022 | 2022 | ||
2023 | /* | ||
2024 | * this should be called twice, once with wait == 0 and | ||
2025 | * once with wait == 1. When wait == 0 is done, all the buffer heads | ||
2026 | * we write are pinned. | ||
2027 | * | ||
2028 | * They are released when wait == 1 is done. | ||
2029 | * max_mirrors must be the same for both runs, and it indicates how | ||
2030 | * many supers on this one device should be written. | ||
2031 | * | ||
2032 | * max_mirrors == 0 means to write them all. | ||
2033 | */ | ||
2023 | static int write_dev_supers(struct btrfs_device *device, | 2034 | static int write_dev_supers(struct btrfs_device *device, |
2024 | struct btrfs_super_block *sb, | 2035 | struct btrfs_super_block *sb, |
2025 | int do_barriers, int wait, int max_mirrors) | 2036 | int do_barriers, int wait, int max_mirrors) |
@@ -2055,12 +2066,16 @@ static int write_dev_supers(struct btrfs_device *device, | |||
2055 | bh = __find_get_block(device->bdev, bytenr / 4096, | 2066 | bh = __find_get_block(device->bdev, bytenr / 4096, |
2056 | BTRFS_SUPER_INFO_SIZE); | 2067 | BTRFS_SUPER_INFO_SIZE); |
2057 | BUG_ON(!bh); | 2068 | BUG_ON(!bh); |
2058 | brelse(bh); | ||
2059 | wait_on_buffer(bh); | 2069 | wait_on_buffer(bh); |
2060 | if (buffer_uptodate(bh)) { | 2070 | if (!buffer_uptodate(bh)) |
2061 | brelse(bh); | 2071 | errors++; |
2062 | continue; | 2072 | |
2063 | } | 2073 | /* drop our reference */ |
2074 | brelse(bh); | ||
2075 | |||
2076 | /* drop the reference from the wait == 0 run */ | ||
2077 | brelse(bh); | ||
2078 | continue; | ||
2064 | } else { | 2079 | } else { |
2065 | btrfs_set_super_bytenr(sb, bytenr); | 2080 | btrfs_set_super_bytenr(sb, bytenr); |
2066 | 2081 | ||
@@ -2071,12 +2086,18 @@ static int write_dev_supers(struct btrfs_device *device, | |||
2071 | BTRFS_CSUM_SIZE); | 2086 | BTRFS_CSUM_SIZE); |
2072 | btrfs_csum_final(crc, sb->csum); | 2087 | btrfs_csum_final(crc, sb->csum); |
2073 | 2088 | ||
2089 | /* | ||
2090 | * one reference for us, and we leave it for the | ||
2091 | * caller | ||
2092 | */ | ||
2074 | bh = __getblk(device->bdev, bytenr / 4096, | 2093 | bh = __getblk(device->bdev, bytenr / 4096, |
2075 | BTRFS_SUPER_INFO_SIZE); | 2094 | BTRFS_SUPER_INFO_SIZE); |
2076 | memcpy(bh->b_data, sb, BTRFS_SUPER_INFO_SIZE); | 2095 | memcpy(bh->b_data, sb, BTRFS_SUPER_INFO_SIZE); |
2077 | 2096 | ||
2078 | set_buffer_uptodate(bh); | 2097 | /* one reference for submit_bh */ |
2079 | get_bh(bh); | 2098 | get_bh(bh); |
2099 | |||
2100 | set_buffer_uptodate(bh); | ||
2080 | lock_buffer(bh); | 2101 | lock_buffer(bh); |
2081 | bh->b_end_io = btrfs_end_buffer_write_sync; | 2102 | bh->b_end_io = btrfs_end_buffer_write_sync; |
2082 | } | 2103 | } |
@@ -2088,6 +2109,7 @@ static int write_dev_supers(struct btrfs_device *device, | |||
2088 | device->name); | 2109 | device->name); |
2089 | set_buffer_uptodate(bh); | 2110 | set_buffer_uptodate(bh); |
2090 | device->barriers = 0; | 2111 | device->barriers = 0; |
2112 | /* one reference for submit_bh */ | ||
2091 | get_bh(bh); | 2113 | get_bh(bh); |
2092 | lock_buffer(bh); | 2114 | lock_buffer(bh); |
2093 | ret = submit_bh(WRITE_SYNC, bh); | 2115 | ret = submit_bh(WRITE_SYNC, bh); |
@@ -2096,15 +2118,8 @@ static int write_dev_supers(struct btrfs_device *device, | |||
2096 | ret = submit_bh(WRITE_SYNC, bh); | 2118 | ret = submit_bh(WRITE_SYNC, bh); |
2097 | } | 2119 | } |
2098 | 2120 | ||
2099 | if (!ret && wait) { | 2121 | if (ret) |
2100 | wait_on_buffer(bh); | ||
2101 | if (!buffer_uptodate(bh)) | ||
2102 | errors++; | ||
2103 | } else if (ret) { | ||
2104 | errors++; | 2122 | errors++; |
2105 | } | ||
2106 | if (wait) | ||
2107 | brelse(bh); | ||
2108 | } | 2123 | } |
2109 | return errors < i ? 0 : -1; | 2124 | return errors < i ? 0 : -1; |
2110 | } | 2125 | } |