diff options
| author | Joe Thornber <ejt@redhat.com> | 2013-05-10 09:37:21 -0400 |
|---|---|---|
| committer | Alasdair G Kergon <agk@redhat.com> | 2013-05-10 09:37:21 -0400 |
| commit | ac8c3f3df65e487bbcabf274eeeb9cd222f5da1e (patch) | |
| tree | e1ab6d4662834bbbf248b1ad6224c9b7c3faa15e /drivers | |
| parent | 2fc48021f4afdd109b9e52b6eef5db89ca80bac7 (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')
| -rw-r--r-- | drivers/md/dm-thin-metadata.c | 14 | ||||
| -rw-r--r-- | drivers/md/dm-thin-metadata.h | 6 | ||||
| -rw-r--r-- | drivers/md/dm-thin.c | 38 |
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 | |||
| 1700 | int 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 | */ |
| 194 | void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd); | 195 | void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd); |
| 195 | 196 | ||
| 197 | int 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 | */ | ||
| 1284 | static int need_commit_due_to_time(struct pool *pool) | 1288 | static 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 | ||
| 1916 | static 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 | |||
| 1912 | static sector_t get_metadata_dev_size(struct block_device *bdev) | 1926 | static 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 | */ | ||
| 1955 | static 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 | ||
