mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 01:10:04 +00:00
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>
This commit is contained in:
parent
2fc48021f4
commit
ac8c3f3df6
3 changed files with 58 additions and 0 deletions
|
@ -1696,3 +1696,17 @@ void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd)
|
|||
dm_bm_set_read_only(pmd->bm);
|
||||
up_write(&pmd->root_lock);
|
||||
}
|
||||
|
||||
int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
|
||||
dm_block_t threshold,
|
||||
dm_sm_threshold_fn fn,
|
||||
void *context)
|
||||
{
|
||||
int r;
|
||||
|
||||
down_write(&pmd->root_lock);
|
||||
r = dm_sm_register_threshold_callback(pmd->metadata_sm, threshold, fn, context);
|
||||
up_write(&pmd->root_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define DM_THIN_METADATA_H
|
||||
|
||||
#include "persistent-data/dm-block-manager.h"
|
||||
#include "persistent-data/dm-space-map.h"
|
||||
|
||||
#define THIN_METADATA_BLOCK_SIZE 4096
|
||||
|
||||
|
@ -193,6 +194,11 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_siz
|
|||
*/
|
||||
void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd);
|
||||
|
||||
int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
|
||||
dm_block_t threshold,
|
||||
dm_sm_threshold_fn fn,
|
||||
void *context);
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1281,6 +1281,10 @@ static void process_bio_fail(struct thin_c *tc, struct bio *bio)
|
|||
bio_io_error(bio);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: should we also commit due to size of transaction, measured in
|
||||
* metadata blocks?
|
||||
*/
|
||||
static int need_commit_due_to_time(struct pool *pool)
|
||||
{
|
||||
return jiffies < pool->last_commit_jiffies ||
|
||||
|
@ -1909,6 +1913,16 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
|
|||
return r;
|
||||
}
|
||||
|
||||
static void metadata_low_callback(void *context)
|
||||
{
|
||||
struct pool *pool = context;
|
||||
|
||||
DMWARN("%s: reached low water mark for metadata device: sending event.",
|
||||
dm_device_name(pool->pool_md));
|
||||
|
||||
dm_table_event(pool->ti->table);
|
||||
}
|
||||
|
||||
static sector_t get_metadata_dev_size(struct block_device *bdev)
|
||||
{
|
||||
sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
|
||||
|
@ -1932,6 +1946,23 @@ static dm_block_t get_metadata_dev_size_in_blocks(struct block_device *bdev)
|
|||
return metadata_dev_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* When a metadata threshold is crossed a dm event is triggered, and
|
||||
* userland should respond by growing the metadata device. We could let
|
||||
* userland set the threshold, like we do with the data threshold, but I'm
|
||||
* not sure they know enough to do this well.
|
||||
*/
|
||||
static dm_block_t calc_metadata_threshold(struct pool_c *pt)
|
||||
{
|
||||
/*
|
||||
* 4M is ample for all ops with the possible exception of thin
|
||||
* device deletion which is harmless if it fails (just retry the
|
||||
* delete after you've grown the device).
|
||||
*/
|
||||
dm_block_t quarter = get_metadata_dev_size_in_blocks(pt->metadata_dev->bdev) / 4;
|
||||
return min((dm_block_t)1024ULL /* 4M */, quarter);
|
||||
}
|
||||
|
||||
/*
|
||||
* thin-pool <metadata dev> <data dev>
|
||||
* <data block size (sectors)>
|
||||
|
@ -2065,6 +2096,13 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
|||
}
|
||||
ti->private = pt;
|
||||
|
||||
r = dm_pool_register_metadata_threshold(pt->pool->pmd,
|
||||
calc_metadata_threshold(pt),
|
||||
metadata_low_callback,
|
||||
pool);
|
||||
if (r)
|
||||
goto out_free_pt;
|
||||
|
||||
pt->callbacks.congested_fn = pool_is_congested;
|
||||
dm_table_add_target_callbacks(ti->table, &pt->callbacks);
|
||||
|
||||
|
|
Loading…
Reference in a new issue