aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2013-05-10 09:37:21 -0400
committerAlasdair G Kergon <agk@redhat.com>2013-05-10 09:37:21 -0400
commitac8c3f3df65e487bbcabf274eeeb9cd222f5da1e (patch)
treee1ab6d4662834bbbf248b1ad6224c9b7c3faa15e /drivers/md
parent2fc48021f4afdd109b9e52b6eef5db89ca80bac7 (diff)
dm thin: generate event when metadata threshold passed
Generate a dm event when the amount of remaining thin pool metadata space falls below a certain level. The threshold is taken to be a quarter of the size of the metadata device with a minimum threshold of 4MB. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-thin-metadata.c14
-rw-r--r--drivers/md/dm-thin-metadata.h6
-rw-r--r--drivers/md/dm-thin.c38
3 files changed, 58 insertions, 0 deletions
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index f553ed66603c..60bce435f4fa 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1696,3 +1696,17 @@ void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd)
1696 dm_bm_set_read_only(pmd->bm); 1696 dm_bm_set_read_only(pmd->bm);
1697 up_write(&pmd->root_lock); 1697 up_write(&pmd->root_lock);
1698} 1698}
1699
1700int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
1701 dm_block_t threshold,
1702 dm_sm_threshold_fn fn,
1703 void *context)
1704{
1705 int r;
1706
1707 down_write(&pmd->root_lock);
1708 r = dm_sm_register_threshold_callback(pmd->metadata_sm, threshold, fn, context);
1709 up_write(&pmd->root_lock);
1710
1711 return r;
1712}
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
index ef8dd709e34e..845ebbe589a9 100644
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -8,6 +8,7 @@
8#define DM_THIN_METADATA_H 8#define DM_THIN_METADATA_H
9 9
10#include "persistent-data/dm-block-manager.h" 10#include "persistent-data/dm-block-manager.h"
11#include "persistent-data/dm-space-map.h"
11 12
12#define THIN_METADATA_BLOCK_SIZE 4096 13#define THIN_METADATA_BLOCK_SIZE 4096
13 14
@@ -193,6 +194,11 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_siz
193 */ 194 */
194void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd); 195void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd);
195 196
197int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
198 dm_block_t threshold,
199 dm_sm_threshold_fn fn,
200 void *context);
201
196/*----------------------------------------------------------------*/ 202/*----------------------------------------------------------------*/
197 203
198#endif 204#endif
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index f4632f97bd7b..759cffc45cab 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -1281,6 +1281,10 @@ static void process_bio_fail(struct thin_c *tc, struct bio *bio)
1281 bio_io_error(bio); 1281 bio_io_error(bio);
1282} 1282}
1283 1283
1284/*
1285 * FIXME: should we also commit due to size of transaction, measured in
1286 * metadata blocks?
1287 */
1284static int need_commit_due_to_time(struct pool *pool) 1288static int need_commit_due_to_time(struct pool *pool)
1285{ 1289{
1286 return jiffies < pool->last_commit_jiffies || 1290 return jiffies < pool->last_commit_jiffies ||
@@ -1909,6 +1913,16 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
1909 return r; 1913 return r;
1910} 1914}
1911 1915
1916static void metadata_low_callback(void *context)
1917{
1918 struct pool *pool = context;
1919
1920 DMWARN("%s: reached low water mark for metadata device: sending event.",
1921 dm_device_name(pool->pool_md));
1922
1923 dm_table_event(pool->ti->table);
1924}
1925
1912static sector_t get_metadata_dev_size(struct block_device *bdev) 1926static sector_t get_metadata_dev_size(struct block_device *bdev)
1913{ 1927{
1914 sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; 1928 sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
@@ -1933,6 +1947,23 @@ static dm_block_t get_metadata_dev_size_in_blocks(struct block_device *bdev)
1933} 1947}
1934 1948
1935/* 1949/*
1950 * When a metadata threshold is crossed a dm event is triggered, and
1951 * userland should respond by growing the metadata device. We could let
1952 * userland set the threshold, like we do with the data threshold, but I'm
1953 * not sure they know enough to do this well.
1954 */
1955static dm_block_t calc_metadata_threshold(struct pool_c *pt)
1956{
1957 /*
1958 * 4M is ample for all ops with the possible exception of thin
1959 * device deletion which is harmless if it fails (just retry the
1960 * delete after you've grown the device).
1961 */
1962 dm_block_t quarter = get_metadata_dev_size_in_blocks(pt->metadata_dev->bdev) / 4;
1963 return min((dm_block_t)1024ULL /* 4M */, quarter);
1964}
1965
1966/*
1936 * thin-pool <metadata dev> <data dev> 1967 * thin-pool <metadata dev> <data dev>
1937 * <data block size (sectors)> 1968 * <data block size (sectors)>
1938 * <low water mark (blocks)> 1969 * <low water mark (blocks)>
@@ -2065,6 +2096,13 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
2065 } 2096 }
2066 ti->private = pt; 2097 ti->private = pt;
2067 2098
2099 r = dm_pool_register_metadata_threshold(pt->pool->pmd,
2100 calc_metadata_threshold(pt),
2101 metadata_low_callback,
2102 pool);
2103 if (r)
2104 goto out_free_pt;
2105
2068 pt->callbacks.congested_fn = pool_is_congested; 2106 pt->callbacks.congested_fn = pool_is_congested;
2069 dm_table_add_target_callbacks(ti->table, &pt->callbacks); 2107 dm_table_add_target_callbacks(ti->table, &pt->callbacks);
2070 2108