aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c43
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 */
2023static int write_dev_supers(struct btrfs_device *device, 2034static 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}