13bd94003SHeinz Mauelshagen /* SPDX-License-Identifier: GPL-2.0-only */ 2c6b4fcbaSJoe Thornber /* 3c6b4fcbaSJoe Thornber * Copyright (C) 2012 Red Hat, Inc. 4c6b4fcbaSJoe Thornber * 5c6b4fcbaSJoe Thornber * This file is released under the GPL. 6c6b4fcbaSJoe Thornber */ 7c6b4fcbaSJoe Thornber 8c6b4fcbaSJoe Thornber #ifndef DM_CACHE_METADATA_H 9c6b4fcbaSJoe Thornber #define DM_CACHE_METADATA_H 10c6b4fcbaSJoe Thornber 11c6b4fcbaSJoe Thornber #include "dm-cache-block-types.h" 12c6b4fcbaSJoe Thornber #include "dm-cache-policy-internal.h" 13895b47d7SMike Snitzer #include "persistent-data/dm-space-map-metadata.h" 14c6b4fcbaSJoe Thornber 15c6b4fcbaSJoe Thornber /*----------------------------------------------------------------*/ 16c6b4fcbaSJoe Thornber 17895b47d7SMike Snitzer #define DM_CACHE_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE 18c6b4fcbaSJoe Thornber 19c6b4fcbaSJoe Thornber /* FIXME: remove this restriction */ 20c6b4fcbaSJoe Thornber /* 21c6b4fcbaSJoe Thornber * The metadata device is currently limited in size. 22c6b4fcbaSJoe Thornber */ 23895b47d7SMike Snitzer #define DM_CACHE_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS 24c6b4fcbaSJoe Thornber 25c6b4fcbaSJoe Thornber /* 26c6b4fcbaSJoe Thornber * A metadata device larger than 16GB triggers a warning. 27c6b4fcbaSJoe Thornber */ 28c6b4fcbaSJoe Thornber #define DM_CACHE_METADATA_MAX_SECTORS_WARNING (16 * (1024 * 1024 * 1024 >> SECTOR_SHIFT)) 29c6b4fcbaSJoe Thornber 30c6b4fcbaSJoe Thornber /*----------------------------------------------------------------*/ 31c6b4fcbaSJoe Thornber 32c6b4fcbaSJoe Thornber /* 33c6b4fcbaSJoe Thornber * Ext[234]-style compat feature flags. 34c6b4fcbaSJoe Thornber * 35c6b4fcbaSJoe Thornber * A new feature which old metadata will still be compatible with should 36c6b4fcbaSJoe Thornber * define a DM_CACHE_FEATURE_COMPAT_* flag (rarely useful). 37c6b4fcbaSJoe Thornber * 38c6b4fcbaSJoe Thornber * A new feature that is not compatible with old code should define a 39c6b4fcbaSJoe Thornber * DM_CACHE_FEATURE_INCOMPAT_* flag and guard the relevant code with 40c6b4fcbaSJoe Thornber * that flag. 41c6b4fcbaSJoe Thornber * 42c6b4fcbaSJoe Thornber * A new feature that is not compatible with old code accessing the 43c6b4fcbaSJoe Thornber * metadata RDWR should define a DM_CACHE_FEATURE_RO_COMPAT_* flag and 44c6b4fcbaSJoe Thornber * guard the relevant code with that flag. 45c6b4fcbaSJoe Thornber * 46c6b4fcbaSJoe Thornber * As these various flags are defined they should be added to the 47c6b4fcbaSJoe Thornber * following masks. 48c6b4fcbaSJoe Thornber */ 49629d0a8aSJoe Thornber 50c6b4fcbaSJoe Thornber #define DM_CACHE_FEATURE_COMPAT_SUPP 0UL 51c6b4fcbaSJoe Thornber #define DM_CACHE_FEATURE_COMPAT_RO_SUPP 0UL 52c6b4fcbaSJoe Thornber #define DM_CACHE_FEATURE_INCOMPAT_SUPP 0UL 53c6b4fcbaSJoe Thornber 54b29d4986SJoe Thornber struct dm_cache_metadata; 55b29d4986SJoe Thornber 56c6b4fcbaSJoe Thornber /* 57629d0a8aSJoe Thornber * Reopens or creates a new, empty metadata volume. Returns an ERR_PTR on 58629d0a8aSJoe Thornber * failure. If reopening then features must match. 59c6b4fcbaSJoe Thornber */ 60c6b4fcbaSJoe Thornber struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, 61c6b4fcbaSJoe Thornber sector_t data_block_size, 62c6b4fcbaSJoe Thornber bool may_format_device, 63629d0a8aSJoe Thornber size_t policy_hint_size, 64*86a3238cSHeinz Mauelshagen unsigned int metadata_version); 65c6b4fcbaSJoe Thornber 66c6b4fcbaSJoe Thornber void dm_cache_metadata_close(struct dm_cache_metadata *cmd); 67c6b4fcbaSJoe Thornber 68c6b4fcbaSJoe Thornber /* 69c6b4fcbaSJoe Thornber * The metadata needs to know how many cache blocks there are. We don't 70c6b4fcbaSJoe Thornber * care about the origin, assuming the core target is giving us valid 71c6b4fcbaSJoe Thornber * origin blocks to map to. 72c6b4fcbaSJoe Thornber */ 73c6b4fcbaSJoe Thornber int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size); 74d14fcf3dSJoe Thornber int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result); 75c6b4fcbaSJoe Thornber 76c6b4fcbaSJoe Thornber int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd, 77c6b4fcbaSJoe Thornber sector_t discard_block_size, 781bad9bc4SJoe Thornber dm_dblock_t new_nr_entries); 79c6b4fcbaSJoe Thornber 80c6b4fcbaSJoe Thornber typedef int (*load_discard_fn)(void *context, sector_t discard_block_size, 811bad9bc4SJoe Thornber dm_dblock_t dblock, bool discarded); 82c6b4fcbaSJoe Thornber int dm_cache_load_discards(struct dm_cache_metadata *cmd, 83c6b4fcbaSJoe Thornber load_discard_fn fn, void *context); 84c6b4fcbaSJoe Thornber 851bad9bc4SJoe Thornber int dm_cache_set_discard(struct dm_cache_metadata *cmd, dm_dblock_t dblock, bool discard); 86c6b4fcbaSJoe Thornber 87c6b4fcbaSJoe Thornber int dm_cache_remove_mapping(struct dm_cache_metadata *cmd, dm_cblock_t cblock); 88c6b4fcbaSJoe Thornber int dm_cache_insert_mapping(struct dm_cache_metadata *cmd, dm_cblock_t cblock, dm_oblock_t oblock); 89c6b4fcbaSJoe Thornber int dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd); 90c6b4fcbaSJoe Thornber 91c6b4fcbaSJoe Thornber typedef int (*load_mapping_fn)(void *context, dm_oblock_t oblock, 92c6b4fcbaSJoe Thornber dm_cblock_t cblock, bool dirty, 93c6b4fcbaSJoe Thornber uint32_t hint, bool hint_valid); 94c6b4fcbaSJoe Thornber int dm_cache_load_mappings(struct dm_cache_metadata *cmd, 95ea2dd8c1SMike Snitzer struct dm_cache_policy *policy, 96c6b4fcbaSJoe Thornber load_mapping_fn fn, 97c6b4fcbaSJoe Thornber void *context); 98c6b4fcbaSJoe Thornber 99629d0a8aSJoe Thornber int dm_cache_set_dirty_bits(struct dm_cache_metadata *cmd, 100*86a3238cSHeinz Mauelshagen unsigned int nr_bits, unsigned long *bits); 101c6b4fcbaSJoe Thornber 102c6b4fcbaSJoe Thornber struct dm_cache_statistics { 103c6b4fcbaSJoe Thornber uint32_t read_hits; 104c6b4fcbaSJoe Thornber uint32_t read_misses; 105c6b4fcbaSJoe Thornber uint32_t write_hits; 106c6b4fcbaSJoe Thornber uint32_t write_misses; 107c6b4fcbaSJoe Thornber }; 108c6b4fcbaSJoe Thornber 109c6b4fcbaSJoe Thornber void dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd, 110c6b4fcbaSJoe Thornber struct dm_cache_statistics *stats); 111028ae9f7SJoe Thornber 112028ae9f7SJoe Thornber /* 113028ae9f7SJoe Thornber * 'void' because it's no big deal if it fails. 114028ae9f7SJoe Thornber */ 115c6b4fcbaSJoe Thornber void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd, 116c6b4fcbaSJoe Thornber struct dm_cache_statistics *stats); 117c6b4fcbaSJoe Thornber 118c6b4fcbaSJoe Thornber int dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown); 119c6b4fcbaSJoe Thornber 120c6b4fcbaSJoe Thornber int dm_cache_get_free_metadata_block_count(struct dm_cache_metadata *cmd, 121c6b4fcbaSJoe Thornber dm_block_t *result); 122c6b4fcbaSJoe Thornber 123c6b4fcbaSJoe Thornber int dm_cache_get_metadata_dev_size(struct dm_cache_metadata *cmd, 124c6b4fcbaSJoe Thornber dm_block_t *result); 125c6b4fcbaSJoe Thornber 126c6b4fcbaSJoe Thornber void dm_cache_dump(struct dm_cache_metadata *cmd); 127c6b4fcbaSJoe Thornber 128c6b4fcbaSJoe Thornber /* 129c6b4fcbaSJoe Thornber * The policy is invited to save a 32bit hint value for every cblock (eg, 130c6b4fcbaSJoe Thornber * for a hit count). These are stored against the policy name. If 131c6b4fcbaSJoe Thornber * policies are changed, then hints will be lost. If the machine crashes, 132c6b4fcbaSJoe Thornber * hints will be lost. 133c6b4fcbaSJoe Thornber * 134c6b4fcbaSJoe Thornber * The hints are indexed by the cblock, but many policies will not 1355c29e784SSteven Lung * necessarily have a fast way of accessing efficiently via cblock. So 136c6b4fcbaSJoe Thornber * rather than querying the policy for each cblock, we let it walk its data 137c6b4fcbaSJoe Thornber * structures and fill in the hints in whatever order it wishes. 138c6b4fcbaSJoe Thornber */ 1390596661fSJoe Thornber int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *p); 140c6b4fcbaSJoe Thornber 1412ee57d58SJoe Thornber /* 1422ee57d58SJoe Thornber * Query method. Are all the blocks in the cache clean? 1432ee57d58SJoe Thornber */ 1442ee57d58SJoe Thornber int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result); 1452ee57d58SJoe Thornber 146d14fcf3dSJoe Thornber int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result); 147028ae9f7SJoe Thornber int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd); 148028ae9f7SJoe Thornber void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd); 149028ae9f7SJoe Thornber void dm_cache_metadata_set_read_write(struct dm_cache_metadata *cmd); 150028ae9f7SJoe Thornber int dm_cache_metadata_abort(struct dm_cache_metadata *cmd); 151028ae9f7SJoe Thornber 152c6b4fcbaSJoe Thornber /*----------------------------------------------------------------*/ 153c6b4fcbaSJoe Thornber 154c6b4fcbaSJoe Thornber #endif /* DM_CACHE_METADATA_H */ 155