aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-thin-metadata.c12
-rw-r--r--drivers/md/dm-thin-metadata.h1
-rw-r--r--drivers/md/dm-thin.c54
3 files changed, 64 insertions, 3 deletions
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 9452a489ed99..f553ed66603c 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1677,6 +1677,18 @@ int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
1677 return r; 1677 return r;
1678} 1678}
1679 1679
1680int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
1681{
1682 int r = -EINVAL;
1683
1684 down_write(&pmd->root_lock);
1685 if (!pmd->fail_io)
1686 r = __resize_space_map(pmd->metadata_sm, new_count);
1687 up_write(&pmd->root_lock);
1688
1689 return r;
1690}
1691
1680void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd) 1692void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd)
1681{ 1693{
1682 down_write(&pmd->root_lock); 1694 down_write(&pmd->root_lock);
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
index 0cecc3702885..ef8dd709e34e 100644
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -185,6 +185,7 @@ int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
185 * blocks would be lost. 185 * blocks would be lost.
186 */ 186 */
187int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size); 187int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);
188int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);
188 189
189/* 190/*
190 * Flicks the underlying block manager into read only mode, so you know 191 * Flicks the underlying block manager into read only mode, so you know
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index ef021b0c8106..f4632f97bd7b 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -1923,6 +1923,15 @@ static sector_t get_metadata_dev_size(struct block_device *bdev)
1923 return metadata_dev_size; 1923 return metadata_dev_size;
1924} 1924}
1925 1925
1926static dm_block_t get_metadata_dev_size_in_blocks(struct block_device *bdev)
1927{
1928 sector_t metadata_dev_size = get_metadata_dev_size(bdev);
1929
1930 sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
1931
1932 return metadata_dev_size;
1933}
1934
1926/* 1935/*
1927 * thin-pool <metadata dev> <data dev> 1936 * thin-pool <metadata dev> <data dev>
1928 * <data block size (sectors)> 1937 * <data block size (sectors)>
@@ -2132,6 +2141,41 @@ static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
2132 return 0; 2141 return 0;
2133} 2142}
2134 2143
2144static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit)
2145{
2146 int r;
2147 struct pool_c *pt = ti->private;
2148 struct pool *pool = pt->pool;
2149 dm_block_t metadata_dev_size, sb_metadata_dev_size;
2150
2151 *need_commit = false;
2152
2153 metadata_dev_size = get_metadata_dev_size(pool->md_dev);
2154
2155 r = dm_pool_get_metadata_dev_size(pool->pmd, &sb_metadata_dev_size);
2156 if (r) {
2157 DMERR("failed to retrieve data device size");
2158 return r;
2159 }
2160
2161 if (metadata_dev_size < sb_metadata_dev_size) {
2162 DMERR("metadata device (%llu sectors) too small: expected %llu",
2163 metadata_dev_size, sb_metadata_dev_size);
2164 return -EINVAL;
2165
2166 } else if (metadata_dev_size > sb_metadata_dev_size) {
2167 r = dm_pool_resize_metadata_dev(pool->pmd, metadata_dev_size);
2168 if (r) {
2169 DMERR("failed to resize metadata device");
2170 return r;
2171 }
2172
2173 *need_commit = true;
2174 }
2175
2176 return 0;
2177}
2178
2135/* 2179/*
2136 * Retrieves the number of blocks of the data device from 2180 * Retrieves the number of blocks of the data device from
2137 * the superblock and compares it to the actual device size, 2181 * the superblock and compares it to the actual device size,
@@ -2146,7 +2190,7 @@ static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
2146static int pool_preresume(struct dm_target *ti) 2190static int pool_preresume(struct dm_target *ti)
2147{ 2191{
2148 int r; 2192 int r;
2149 bool need_commit1; 2193 bool need_commit1, need_commit2;
2150 struct pool_c *pt = ti->private; 2194 struct pool_c *pt = ti->private;
2151 struct pool *pool = pt->pool; 2195 struct pool *pool = pt->pool;
2152 2196
@@ -2161,7 +2205,11 @@ static int pool_preresume(struct dm_target *ti)
2161 if (r) 2205 if (r)
2162 return r; 2206 return r;
2163 2207
2164 if (need_commit1) 2208 r = maybe_resize_metadata_dev(ti, &need_commit2);
2209 if (r)
2210 return r;
2211
2212 if (need_commit1 || need_commit2)
2165 (void) commit_or_fallback(pool); 2213 (void) commit_or_fallback(pool);
2166 2214
2167 return 0; 2215 return 0;
@@ -2583,7 +2631,7 @@ static struct target_type pool_target = {
2583 .name = "thin-pool", 2631 .name = "thin-pool",
2584 .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | 2632 .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
2585 DM_TARGET_IMMUTABLE, 2633 DM_TARGET_IMMUTABLE,
2586 .version = {1, 7, 0}, 2634 .version = {1, 8, 0},
2587 .module = THIS_MODULE, 2635 .module = THIS_MODULE,
2588 .ctr = pool_ctr, 2636 .ctr = pool_ctr,
2589 .dtr = pool_dtr, 2637 .dtr = pool_dtr,