162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2012 Red Hat, Inc.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * This file is released under the GPL.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef DM_CACHE_METADATA_H
962306a36Sopenharmony_ci#define DM_CACHE_METADATA_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include "dm-cache-block-types.h"
1262306a36Sopenharmony_ci#include "dm-cache-policy-internal.h"
1362306a36Sopenharmony_ci#include "persistent-data/dm-space-map-metadata.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/*----------------------------------------------------------------*/
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define DM_CACHE_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/* FIXME: remove this restriction */
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * The metadata device is currently limited in size.
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ci#define DM_CACHE_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/*
2662306a36Sopenharmony_ci * A metadata device larger than 16GB triggers a warning.
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_ci#define DM_CACHE_METADATA_MAX_SECTORS_WARNING (16 * (1024 * 1024 * 1024 >> SECTOR_SHIFT))
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/*----------------------------------------------------------------*/
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/*
3362306a36Sopenharmony_ci * Ext[234]-style compat feature flags.
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci * A new feature which old metadata will still be compatible with should
3662306a36Sopenharmony_ci * define a DM_CACHE_FEATURE_COMPAT_* flag (rarely useful).
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci * A new feature that is not compatible with old code should define a
3962306a36Sopenharmony_ci * DM_CACHE_FEATURE_INCOMPAT_* flag and guard the relevant code with
4062306a36Sopenharmony_ci * that flag.
4162306a36Sopenharmony_ci *
4262306a36Sopenharmony_ci * A new feature that is not compatible with old code accessing the
4362306a36Sopenharmony_ci * metadata RDWR should define a DM_CACHE_FEATURE_RO_COMPAT_* flag and
4462306a36Sopenharmony_ci * guard the relevant code with that flag.
4562306a36Sopenharmony_ci *
4662306a36Sopenharmony_ci * As these various flags are defined they should be added to the
4762306a36Sopenharmony_ci * following masks.
4862306a36Sopenharmony_ci */
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#define DM_CACHE_FEATURE_COMPAT_SUPP	  0UL
5162306a36Sopenharmony_ci#define DM_CACHE_FEATURE_COMPAT_RO_SUPP	  0UL
5262306a36Sopenharmony_ci#define DM_CACHE_FEATURE_INCOMPAT_SUPP	  0UL
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistruct dm_cache_metadata;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/*
5762306a36Sopenharmony_ci * Reopens or creates a new, empty metadata volume.  Returns an ERR_PTR on
5862306a36Sopenharmony_ci * failure.  If reopening then features must match.
5962306a36Sopenharmony_ci */
6062306a36Sopenharmony_cistruct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
6162306a36Sopenharmony_ci						 sector_t data_block_size,
6262306a36Sopenharmony_ci						 bool may_format_device,
6362306a36Sopenharmony_ci						 size_t policy_hint_size,
6462306a36Sopenharmony_ci						 unsigned int metadata_version);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_civoid dm_cache_metadata_close(struct dm_cache_metadata *cmd);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/*
6962306a36Sopenharmony_ci * The metadata needs to know how many cache blocks there are.  We don't
7062306a36Sopenharmony_ci * care about the origin, assuming the core target is giving us valid
7162306a36Sopenharmony_ci * origin blocks to map to.
7262306a36Sopenharmony_ci */
7362306a36Sopenharmony_ciint dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size);
7462306a36Sopenharmony_ciint dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ciint dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
7762306a36Sopenharmony_ci				   sector_t discard_block_size,
7862306a36Sopenharmony_ci				   dm_dblock_t new_nr_entries);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_citypedef int (*load_discard_fn)(void *context, sector_t discard_block_size,
8162306a36Sopenharmony_ci			       dm_dblock_t dblock, bool discarded);
8262306a36Sopenharmony_ciint dm_cache_load_discards(struct dm_cache_metadata *cmd,
8362306a36Sopenharmony_ci			   load_discard_fn fn, void *context);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ciint dm_cache_set_discard(struct dm_cache_metadata *cmd, dm_dblock_t dblock, bool discard);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ciint dm_cache_remove_mapping(struct dm_cache_metadata *cmd, dm_cblock_t cblock);
8862306a36Sopenharmony_ciint dm_cache_insert_mapping(struct dm_cache_metadata *cmd, dm_cblock_t cblock, dm_oblock_t oblock);
8962306a36Sopenharmony_ciint dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_citypedef int (*load_mapping_fn)(void *context, dm_oblock_t oblock,
9262306a36Sopenharmony_ci			       dm_cblock_t cblock, bool dirty,
9362306a36Sopenharmony_ci			       uint32_t hint, bool hint_valid);
9462306a36Sopenharmony_ciint dm_cache_load_mappings(struct dm_cache_metadata *cmd,
9562306a36Sopenharmony_ci			   struct dm_cache_policy *policy,
9662306a36Sopenharmony_ci			   load_mapping_fn fn,
9762306a36Sopenharmony_ci			   void *context);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ciint dm_cache_set_dirty_bits(struct dm_cache_metadata *cmd,
10062306a36Sopenharmony_ci			    unsigned int nr_bits, unsigned long *bits);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistruct dm_cache_statistics {
10362306a36Sopenharmony_ci	uint32_t read_hits;
10462306a36Sopenharmony_ci	uint32_t read_misses;
10562306a36Sopenharmony_ci	uint32_t write_hits;
10662306a36Sopenharmony_ci	uint32_t write_misses;
10762306a36Sopenharmony_ci};
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_civoid dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd,
11062306a36Sopenharmony_ci				 struct dm_cache_statistics *stats);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/*
11362306a36Sopenharmony_ci * 'void' because it's no big deal if it fails.
11462306a36Sopenharmony_ci */
11562306a36Sopenharmony_civoid dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd,
11662306a36Sopenharmony_ci				 struct dm_cache_statistics *stats);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ciint dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ciint dm_cache_get_free_metadata_block_count(struct dm_cache_metadata *cmd,
12162306a36Sopenharmony_ci					   dm_block_t *result);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ciint dm_cache_get_metadata_dev_size(struct dm_cache_metadata *cmd,
12462306a36Sopenharmony_ci				   dm_block_t *result);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_civoid dm_cache_dump(struct dm_cache_metadata *cmd);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci/*
12962306a36Sopenharmony_ci * The policy is invited to save a 32bit hint value for every cblock (eg,
13062306a36Sopenharmony_ci * for a hit count).  These are stored against the policy name.  If
13162306a36Sopenharmony_ci * policies are changed, then hints will be lost.  If the machine crashes,
13262306a36Sopenharmony_ci * hints will be lost.
13362306a36Sopenharmony_ci *
13462306a36Sopenharmony_ci * The hints are indexed by the cblock, but many policies will not
13562306a36Sopenharmony_ci * necessarily have a fast way of accessing efficiently via cblock.  So
13662306a36Sopenharmony_ci * rather than querying the policy for each cblock, we let it walk its data
13762306a36Sopenharmony_ci * structures and fill in the hints in whatever order it wishes.
13862306a36Sopenharmony_ci */
13962306a36Sopenharmony_ciint dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *p);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci/*
14262306a36Sopenharmony_ci * Query method.  Are all the blocks in the cache clean?
14362306a36Sopenharmony_ci */
14462306a36Sopenharmony_ciint dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ciint dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result);
14762306a36Sopenharmony_ciint dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd);
14862306a36Sopenharmony_civoid dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd);
14962306a36Sopenharmony_civoid dm_cache_metadata_set_read_write(struct dm_cache_metadata *cmd);
15062306a36Sopenharmony_ciint dm_cache_metadata_abort(struct dm_cache_metadata *cmd);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci/*----------------------------------------------------------------*/
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci#endif /* DM_CACHE_METADATA_H */
155