diff options
| -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 | } |
