1c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/* 2c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * Copyright (C) 2012 Red Hat, Inc. 3c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * 4c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * This file is released under the GPL. 5c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 6c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 7c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#include "dm-cache-metadata.h" 8c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 9c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#include "persistent-data/dm-array.h" 10c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#include "persistent-data/dm-bitset.h" 11c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#include "persistent-data/dm-space-map.h" 12c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#include "persistent-data/dm-space-map-disk.h" 13c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#include "persistent-data/dm-transaction-manager.h" 14c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 15c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#include <linux/device-mapper.h> 16c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 17c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/*----------------------------------------------------------------*/ 18c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 19c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#define DM_MSG_PREFIX "cache metadata" 20c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 21c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#define CACHE_SUPERBLOCK_MAGIC 06142003 22c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#define CACHE_SUPERBLOCK_LOCATION 0 2353d498198d3e8bce4287112beafc30befcba98ccJoe Thornber 2453d498198d3e8bce4287112beafc30befcba98ccJoe Thornber/* 2553d498198d3e8bce4287112beafc30befcba98ccJoe Thornber * defines a range of metadata versions that this module can handle. 2653d498198d3e8bce4287112beafc30befcba98ccJoe Thornber */ 2753d498198d3e8bce4287112beafc30befcba98ccJoe Thornber#define MIN_CACHE_VERSION 1 2853d498198d3e8bce4287112beafc30befcba98ccJoe Thornber#define MAX_CACHE_VERSION 1 2953d498198d3e8bce4287112beafc30befcba98ccJoe Thornber 30c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#define CACHE_METADATA_CACHE_SIZE 64 31c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 32c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/* 33c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * 3 for btree insert + 34c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * 2 for btree lookup used within space map 35c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 36c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#define CACHE_MAX_CONCURRENT_LOCKS 5 37c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#define SPACE_MAP_ROOT_SIZE 128 38c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 39c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberenum superblock_flag_bits { 40c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber /* for spotting crashes that would invalidate the dirty bitset */ 41c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber CLEAN_SHUTDOWN, 42c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber}; 43c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 44c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/* 45c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * Each mapping from cache block -> origin block carries a set of flags. 46c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 47c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberenum mapping_bits { 48c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber /* 49c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * A valid mapping. Because we're using an array we clear this 50c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * flag for an non existant mapping. 51c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 52c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber M_VALID = 1, 53c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 54c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber /* 55c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * The data on the cache is different from that on the origin. 56c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 57c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber M_DIRTY = 2 58c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber}; 59c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 60c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstruct cache_disk_superblock { 61c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 csum; 62c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 flags; 63c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 blocknr; 64c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 65c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __u8 uuid[16]; 66c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 magic; 67c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 version; 68c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 69c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __u8 policy_name[CACHE_POLICY_NAME_SIZE]; 70c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 policy_hint_size; 71c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 72c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE]; 73c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 mapping_root; 74c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 hint_root; 75c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 76c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 discard_root; 77c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 discard_block_size; 78c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 discard_nr_blocks; 79c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 80c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 data_block_size; 81c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 metadata_block_size; 82c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 cache_blocks; 83c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 84c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 compat_flags; 85c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 compat_ro_flags; 86c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 incompat_flags; 87c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 88c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 read_hits; 89c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 read_misses; 90c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 write_hits; 91c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 write_misses; 924e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer 934e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer __le32 policy_version[CACHE_POLICY_VERSION_SIZE]; 94c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} __packed; 95c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 96c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstruct dm_cache_metadata { 97c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct block_device *bdev; 98c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block_manager *bm; 99c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_space_map *metadata_sm; 100c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_transaction_manager *tm; 101c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 102c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_array_info info; 103c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_array_info hint_info; 104c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_disk_bitset discard_info; 105c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 106c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct rw_semaphore root_lock; 107c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_block_t root; 108c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_block_t hint_root; 109c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_block_t discard_root; 110c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 111c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber sector_t discard_block_size; 11264ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen dm_oblock_t discard_nr_blocks; 113c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 114c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber sector_t data_block_size; 115c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_cblock_t cache_blocks; 116c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bool changed:1; 117c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bool clean_when_opened:1; 118c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 119c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber char policy_name[CACHE_POLICY_NAME_SIZE]; 1204e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer unsigned policy_version[CACHE_POLICY_VERSION_SIZE]; 121c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber size_t policy_hint_size; 122c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_cache_statistics stats; 1235a32083d03fb543f63489b2946c4948398579ba0Joe Thornber 1245a32083d03fb543f63489b2946c4948398579ba0Joe Thornber /* 1255a32083d03fb543f63489b2946c4948398579ba0Joe Thornber * Reading the space map root can fail, so we read it into this 1265a32083d03fb543f63489b2946c4948398579ba0Joe Thornber * buffer before the superblock is locked and updated. 1275a32083d03fb543f63489b2946c4948398579ba0Joe Thornber */ 1285a32083d03fb543f63489b2946c4948398579ba0Joe Thornber __u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE]; 129c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber}; 130c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 131c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/*------------------------------------------------------------------- 132c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * superblock validator 133c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber *-----------------------------------------------------------------*/ 134c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 135c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#define SUPERBLOCK_CSUM_XOR 9031977 136c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 137c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic void sb_prepare_for_write(struct dm_block_validator *v, 138c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block *b, 139c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber size_t sb_block_size) 140c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 141c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct cache_disk_superblock *disk_super = dm_block_data(b); 142c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 143c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->blocknr = cpu_to_le64(dm_block_location(b)); 144c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->csum = cpu_to_le32(dm_bm_checksum(&disk_super->flags, 145c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber sb_block_size - sizeof(__le32), 146c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber SUPERBLOCK_CSUM_XOR)); 147c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 148c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 14953d498198d3e8bce4287112beafc30befcba98ccJoe Thornberstatic int check_metadata_version(struct cache_disk_superblock *disk_super) 15053d498198d3e8bce4287112beafc30befcba98ccJoe Thornber{ 15153d498198d3e8bce4287112beafc30befcba98ccJoe Thornber uint32_t metadata_version = le32_to_cpu(disk_super->version); 15253d498198d3e8bce4287112beafc30befcba98ccJoe Thornber if (metadata_version < MIN_CACHE_VERSION || metadata_version > MAX_CACHE_VERSION) { 15353d498198d3e8bce4287112beafc30befcba98ccJoe Thornber DMERR("Cache metadata version %u found, but only versions between %u and %u supported.", 15453d498198d3e8bce4287112beafc30befcba98ccJoe Thornber metadata_version, MIN_CACHE_VERSION, MAX_CACHE_VERSION); 15553d498198d3e8bce4287112beafc30befcba98ccJoe Thornber return -EINVAL; 15653d498198d3e8bce4287112beafc30befcba98ccJoe Thornber } 15753d498198d3e8bce4287112beafc30befcba98ccJoe Thornber 15853d498198d3e8bce4287112beafc30befcba98ccJoe Thornber return 0; 15953d498198d3e8bce4287112beafc30befcba98ccJoe Thornber} 16053d498198d3e8bce4287112beafc30befcba98ccJoe Thornber 161c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int sb_check(struct dm_block_validator *v, 162c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block *b, 163c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber size_t sb_block_size) 164c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 165c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct cache_disk_superblock *disk_super = dm_block_data(b); 166c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 csum_le; 167c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 168c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (dm_block_location(b) != le64_to_cpu(disk_super->blocknr)) { 169c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber DMERR("sb_check failed: blocknr %llu: wanted %llu", 170c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber le64_to_cpu(disk_super->blocknr), 171c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber (unsigned long long)dm_block_location(b)); 172c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return -ENOTBLK; 173c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 174c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 175c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (le64_to_cpu(disk_super->magic) != CACHE_SUPERBLOCK_MAGIC) { 176c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber DMERR("sb_check failed: magic %llu: wanted %llu", 177c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber le64_to_cpu(disk_super->magic), 178c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber (unsigned long long)CACHE_SUPERBLOCK_MAGIC); 179c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return -EILSEQ; 180c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 181c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 182c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber csum_le = cpu_to_le32(dm_bm_checksum(&disk_super->flags, 183c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber sb_block_size - sizeof(__le32), 184c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber SUPERBLOCK_CSUM_XOR)); 185c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (csum_le != disk_super->csum) { 186c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber DMERR("sb_check failed: csum %u: wanted %u", 187c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber le32_to_cpu(csum_le), le32_to_cpu(disk_super->csum)); 188c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return -EILSEQ; 189c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 190c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 19153d498198d3e8bce4287112beafc30befcba98ccJoe Thornber return check_metadata_version(disk_super); 192c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 193c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 194c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic struct dm_block_validator sb_validator = { 195c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber .name = "superblock", 196c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber .prepare_for_write = sb_prepare_for_write, 197c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber .check = sb_check 198c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber}; 199c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 200c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/*----------------------------------------------------------------*/ 201c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 202c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int superblock_read_lock(struct dm_cache_metadata *cmd, 203c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block **sblock) 204c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 205c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_bm_read_lock(cmd->bm, CACHE_SUPERBLOCK_LOCATION, 206c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &sb_validator, sblock); 207c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 208c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 209c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int superblock_lock_zero(struct dm_cache_metadata *cmd, 210c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block **sblock) 211c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 212c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_bm_write_lock_zero(cmd->bm, CACHE_SUPERBLOCK_LOCATION, 213c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &sb_validator, sblock); 214c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 215c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 216c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int superblock_lock(struct dm_cache_metadata *cmd, 217c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block **sblock) 218c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 219c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_bm_write_lock(cmd->bm, CACHE_SUPERBLOCK_LOCATION, 220c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &sb_validator, sblock); 221c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 222c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 223c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/*----------------------------------------------------------------*/ 224c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 225dd8b0c2096e53b336324e99455efcc498599ba0fJoe Thornberstatic int __superblock_all_zeroes(struct dm_block_manager *bm, bool *result) 226c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 227c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 228c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber unsigned i; 229c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block *b; 230c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 *data_le, zero = cpu_to_le64(0); 231c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber unsigned sb_block_size = dm_bm_block_size(bm) / sizeof(__le64); 232c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 233c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber /* 234c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * We can't use a validator here - it may be all zeroes. 235c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 236c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_bm_read_lock(bm, CACHE_SUPERBLOCK_LOCATION, NULL, &b); 237c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 238c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 239c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 240c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber data_le = dm_block_data(b); 241dd8b0c2096e53b336324e99455efcc498599ba0fJoe Thornber *result = true; 242c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber for (i = 0; i < sb_block_size; i++) { 243c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (data_le[i] != zero) { 244dd8b0c2096e53b336324e99455efcc498599ba0fJoe Thornber *result = false; 245c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber break; 246c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 247c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 248c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 249c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_bm_unlock(b); 250c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 251c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 252c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic void __setup_mapping_info(struct dm_cache_metadata *cmd) 253c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 254c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_btree_value_type vt; 255c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 256c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber vt.context = NULL; 257c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber vt.size = sizeof(__le64); 258c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber vt.inc = NULL; 259c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber vt.dec = NULL; 260c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber vt.equal = NULL; 261c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_array_info_init(&cmd->info, cmd->tm, &vt); 262c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 263c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (cmd->policy_hint_size) { 264c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber vt.size = sizeof(__le32); 265c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_array_info_init(&cmd->hint_info, cmd->tm, &vt); 266c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 267c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 268c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 2695a32083d03fb543f63489b2946c4948398579ba0Joe Thornberstatic int __save_sm_root(struct dm_cache_metadata *cmd) 2705a32083d03fb543f63489b2946c4948398579ba0Joe Thornber{ 2715a32083d03fb543f63489b2946c4948398579ba0Joe Thornber int r; 2725a32083d03fb543f63489b2946c4948398579ba0Joe Thornber size_t metadata_len; 2735a32083d03fb543f63489b2946c4948398579ba0Joe Thornber 2745a32083d03fb543f63489b2946c4948398579ba0Joe Thornber r = dm_sm_root_size(cmd->metadata_sm, &metadata_len); 2755a32083d03fb543f63489b2946c4948398579ba0Joe Thornber if (r < 0) 2765a32083d03fb543f63489b2946c4948398579ba0Joe Thornber return r; 2775a32083d03fb543f63489b2946c4948398579ba0Joe Thornber 2785a32083d03fb543f63489b2946c4948398579ba0Joe Thornber return dm_sm_copy_root(cmd->metadata_sm, &cmd->metadata_space_map_root, 2795a32083d03fb543f63489b2946c4948398579ba0Joe Thornber metadata_len); 2805a32083d03fb543f63489b2946c4948398579ba0Joe Thornber} 2815a32083d03fb543f63489b2946c4948398579ba0Joe Thornber 2825a32083d03fb543f63489b2946c4948398579ba0Joe Thornberstatic void __copy_sm_root(struct dm_cache_metadata *cmd, 2835a32083d03fb543f63489b2946c4948398579ba0Joe Thornber struct cache_disk_superblock *disk_super) 2845a32083d03fb543f63489b2946c4948398579ba0Joe Thornber{ 2855a32083d03fb543f63489b2946c4948398579ba0Joe Thornber memcpy(&disk_super->metadata_space_map_root, 2865a32083d03fb543f63489b2946c4948398579ba0Joe Thornber &cmd->metadata_space_map_root, 2875a32083d03fb543f63489b2946c4948398579ba0Joe Thornber sizeof(cmd->metadata_space_map_root)); 2885a32083d03fb543f63489b2946c4948398579ba0Joe Thornber} 2895a32083d03fb543f63489b2946c4948398579ba0Joe Thornber 290c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __write_initial_superblock(struct dm_cache_metadata *cmd) 291c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 292c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 293c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block *sblock; 294c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct cache_disk_superblock *disk_super; 295c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber sector_t bdev_size = i_size_read(cmd->bdev->bd_inode) >> SECTOR_SHIFT; 296c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 297c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber /* FIXME: see if we can lose the max sectors limit */ 298c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (bdev_size > DM_CACHE_METADATA_MAX_SECTORS) 299c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bdev_size = DM_CACHE_METADATA_MAX_SECTORS; 300c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 3015a32083d03fb543f63489b2946c4948398579ba0Joe Thornber r = dm_tm_pre_commit(cmd->tm); 302c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r < 0) 303c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 304c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 3055a32083d03fb543f63489b2946c4948398579ba0Joe Thornber /* 3065a32083d03fb543f63489b2946c4948398579ba0Joe Thornber * dm_sm_copy_root() can fail. So we need to do it before we start 3075a32083d03fb543f63489b2946c4948398579ba0Joe Thornber * updating the superblock. 3085a32083d03fb543f63489b2946c4948398579ba0Joe Thornber */ 3095a32083d03fb543f63489b2946c4948398579ba0Joe Thornber r = __save_sm_root(cmd); 3105a32083d03fb543f63489b2946c4948398579ba0Joe Thornber if (r) 311c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 312c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 313c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = superblock_lock_zero(cmd, &sblock); 314c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 315c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 316c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 317c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super = dm_block_data(sblock); 318c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->flags = 0; 319c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber memset(disk_super->uuid, 0, sizeof(disk_super->uuid)); 320c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->magic = cpu_to_le64(CACHE_SUPERBLOCK_MAGIC); 32153d498198d3e8bce4287112beafc30befcba98ccJoe Thornber disk_super->version = cpu_to_le32(MAX_CACHE_VERSION); 3224e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name)); 3234e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer memset(disk_super->policy_version, 0, sizeof(disk_super->policy_version)); 324c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->policy_hint_size = 0; 325c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 3265a32083d03fb543f63489b2946c4948398579ba0Joe Thornber __copy_sm_root(cmd, disk_super); 327c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 328c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->mapping_root = cpu_to_le64(cmd->root); 329c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->hint_root = cpu_to_le64(cmd->hint_root); 330c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->discard_root = cpu_to_le64(cmd->discard_root); 331c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->discard_block_size = cpu_to_le64(cmd->discard_block_size); 33264ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen disk_super->discard_nr_blocks = cpu_to_le64(from_oblock(cmd->discard_nr_blocks)); 333895b47d7989af3aacea16380b190b1bb8f046362Mike Snitzer disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE); 334c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->data_block_size = cpu_to_le32(cmd->data_block_size); 335c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->cache_blocks = cpu_to_le32(0); 336c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 337c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->read_hits = cpu_to_le32(0); 338c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->read_misses = cpu_to_le32(0); 339c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->write_hits = cpu_to_le32(0); 340c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->write_misses = cpu_to_le32(0); 341c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 342c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_tm_commit(cmd->tm, sblock); 343c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 344c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 345c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __format_metadata(struct dm_cache_metadata *cmd) 346c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 347c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 348c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 349c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_tm_create_with_sm(cmd->bm, CACHE_SUPERBLOCK_LOCATION, 350c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &cmd->tm, &cmd->metadata_sm); 351c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r < 0) { 352c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber DMERR("tm_create_with_sm failed"); 353c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 354c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 355c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 356c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __setup_mapping_info(cmd); 357c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 358c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_empty(&cmd->info, &cmd->root); 359c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r < 0) 360c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber goto bad; 361c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 362c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_disk_bitset_init(cmd->tm, &cmd->discard_info); 363c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 364c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_bitset_empty(&cmd->discard_info, &cmd->discard_root); 365c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r < 0) 366c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber goto bad; 367c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 368c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->discard_block_size = 0; 369c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->discard_nr_blocks = 0; 370c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 371c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __write_initial_superblock(cmd); 372c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 373c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber goto bad; 374c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 375c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->clean_when_opened = true; 376c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; 377c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 378c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberbad: 379c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_tm_destroy(cmd->tm); 380c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_sm_destroy(cmd->metadata_sm); 381c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 382c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 383c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 384c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 385c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __check_incompat_features(struct cache_disk_superblock *disk_super, 386c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_cache_metadata *cmd) 387c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 388c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber uint32_t features; 389c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 390c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber features = le32_to_cpu(disk_super->incompat_flags) & ~DM_CACHE_FEATURE_INCOMPAT_SUPP; 391c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (features) { 392c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber DMERR("could not access metadata due to unsupported optional features (%lx).", 393c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber (unsigned long)features); 394c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return -EINVAL; 395c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 396c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 397c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber /* 398c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * Check for read-only metadata to skip the following RDWR checks. 399c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 400c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (get_disk_ro(cmd->bdev->bd_disk)) 401c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; 402c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 403c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber features = le32_to_cpu(disk_super->compat_ro_flags) & ~DM_CACHE_FEATURE_COMPAT_RO_SUPP; 404c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (features) { 405c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber DMERR("could not access metadata RDWR due to unsupported optional features (%lx).", 406c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber (unsigned long)features); 407c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return -EINVAL; 408c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 409c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 410c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; 411c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 412c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 413c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __open_metadata(struct dm_cache_metadata *cmd) 414c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 415c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 416c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block *sblock; 417c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct cache_disk_superblock *disk_super; 418c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber unsigned long sb_flags; 419c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 420c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = superblock_read_lock(cmd, &sblock); 421c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r < 0) { 422c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber DMERR("couldn't read lock superblock"); 423c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 424c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 425c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 426c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super = dm_block_data(sblock); 427c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 428048e5a07f282c57815b3901d4a68a77fa131ce0aMike Snitzer /* Verify the data block size hasn't changed */ 429048e5a07f282c57815b3901d4a68a77fa131ce0aMike Snitzer if (le32_to_cpu(disk_super->data_block_size) != cmd->data_block_size) { 430048e5a07f282c57815b3901d4a68a77fa131ce0aMike Snitzer DMERR("changing the data block size (from %u to %llu) is not supported", 431048e5a07f282c57815b3901d4a68a77fa131ce0aMike Snitzer le32_to_cpu(disk_super->data_block_size), 432048e5a07f282c57815b3901d4a68a77fa131ce0aMike Snitzer (unsigned long long)cmd->data_block_size); 433048e5a07f282c57815b3901d4a68a77fa131ce0aMike Snitzer r = -EINVAL; 434048e5a07f282c57815b3901d4a68a77fa131ce0aMike Snitzer goto bad; 435048e5a07f282c57815b3901d4a68a77fa131ce0aMike Snitzer } 436048e5a07f282c57815b3901d4a68a77fa131ce0aMike Snitzer 437c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __check_incompat_features(disk_super, cmd); 438c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r < 0) 439c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber goto bad; 440c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 441c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_tm_open_with_sm(cmd->bm, CACHE_SUPERBLOCK_LOCATION, 442c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->metadata_space_map_root, 443c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber sizeof(disk_super->metadata_space_map_root), 444c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &cmd->tm, &cmd->metadata_sm); 445c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r < 0) { 446c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber DMERR("tm_open_with_sm failed"); 447c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber goto bad; 448c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 449c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 450c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __setup_mapping_info(cmd); 451c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_disk_bitset_init(cmd->tm, &cmd->discard_info); 452c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber sb_flags = le32_to_cpu(disk_super->flags); 453c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->clean_when_opened = test_bit(CLEAN_SHUTDOWN, &sb_flags); 454c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_bm_unlock(sblock); 455c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 456c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberbad: 457c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_bm_unlock(sblock); 458c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 459c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 460c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 461c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __open_or_format_metadata(struct dm_cache_metadata *cmd, 462c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bool format_device) 463c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 464dd8b0c2096e53b336324e99455efcc498599ba0fJoe Thornber int r; 465dd8b0c2096e53b336324e99455efcc498599ba0fJoe Thornber bool unformatted = false; 466c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 467c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __superblock_all_zeroes(cmd->bm, &unformatted); 468c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 469c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 470c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 471c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (unformatted) 472c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return format_device ? __format_metadata(cmd) : -EPERM; 473c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 474c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return __open_metadata(cmd); 475c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 476c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 477c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __create_persistent_data_objects(struct dm_cache_metadata *cmd, 478c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bool may_format_device) 479c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 480c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 481895b47d7989af3aacea16380b190b1bb8f046362Mike Snitzer cmd->bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE << SECTOR_SHIFT, 482c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber CACHE_METADATA_CACHE_SIZE, 483c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber CACHE_MAX_CONCURRENT_LOCKS); 484c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (IS_ERR(cmd->bm)) { 485c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber DMERR("could not create block manager"); 486c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return PTR_ERR(cmd->bm); 487c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 488c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 489c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __open_or_format_metadata(cmd, may_format_device); 490c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 491c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_block_manager_destroy(cmd->bm); 492c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 493c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 494c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 495c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 496c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic void __destroy_persistent_data_objects(struct dm_cache_metadata *cmd) 497c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 498c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_sm_destroy(cmd->metadata_sm); 499c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_tm_destroy(cmd->tm); 500c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_block_manager_destroy(cmd->bm); 501c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 502c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 503c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornbertypedef unsigned long (*flags_mutator)(unsigned long); 504c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 505c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic void update_flags(struct cache_disk_superblock *disk_super, 506c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber flags_mutator mutator) 507c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 508c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber uint32_t sb_flags = mutator(le32_to_cpu(disk_super->flags)); 509c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->flags = cpu_to_le32(sb_flags); 510c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 511c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 512c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic unsigned long set_clean_shutdown(unsigned long flags) 513c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 514c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber set_bit(CLEAN_SHUTDOWN, &flags); 515c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return flags; 516c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 517c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 518c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic unsigned long clear_clean_shutdown(unsigned long flags) 519c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 520c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber clear_bit(CLEAN_SHUTDOWN, &flags); 521c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return flags; 522c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 523c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 524c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic void read_superblock_fields(struct dm_cache_metadata *cmd, 525c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct cache_disk_superblock *disk_super) 526c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 527c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->root = le64_to_cpu(disk_super->mapping_root); 528c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->hint_root = le64_to_cpu(disk_super->hint_root); 529c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->discard_root = le64_to_cpu(disk_super->discard_root); 530c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->discard_block_size = le64_to_cpu(disk_super->discard_block_size); 53164ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen cmd->discard_nr_blocks = to_oblock(le64_to_cpu(disk_super->discard_nr_blocks)); 532c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->data_block_size = le32_to_cpu(disk_super->data_block_size); 533c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->cache_blocks = to_cblock(le32_to_cpu(disk_super->cache_blocks)); 534c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber strncpy(cmd->policy_name, disk_super->policy_name, sizeof(cmd->policy_name)); 5354e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer cmd->policy_version[0] = le32_to_cpu(disk_super->policy_version[0]); 5364e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer cmd->policy_version[1] = le32_to_cpu(disk_super->policy_version[1]); 5374e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer cmd->policy_version[2] = le32_to_cpu(disk_super->policy_version[2]); 538c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->policy_hint_size = le32_to_cpu(disk_super->policy_hint_size); 539c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 540c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->stats.read_hits = le32_to_cpu(disk_super->read_hits); 541c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->stats.read_misses = le32_to_cpu(disk_super->read_misses); 542c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->stats.write_hits = le32_to_cpu(disk_super->write_hits); 543c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->stats.write_misses = le32_to_cpu(disk_super->write_misses); 544c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 545c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->changed = false; 546c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 547c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 548c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/* 549c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * The mutator updates the superblock flags. 550c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 551c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __begin_transaction_flags(struct dm_cache_metadata *cmd, 552c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber flags_mutator mutator) 553c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 554c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 555c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct cache_disk_superblock *disk_super; 556c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block *sblock; 557c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 558c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = superblock_lock(cmd, &sblock); 559c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 560c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 561c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 562c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super = dm_block_data(sblock); 563c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber update_flags(disk_super, mutator); 564c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber read_superblock_fields(cmd, disk_super); 565a9d45396f5956d0b615c7ae3b936afd888351a47Joe Thornber dm_bm_unlock(sblock); 566c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 567a9d45396f5956d0b615c7ae3b936afd888351a47Joe Thornber return dm_bm_flush(cmd->bm); 568c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 569c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 570c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __begin_transaction(struct dm_cache_metadata *cmd) 571c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 572c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 573c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct cache_disk_superblock *disk_super; 574c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block *sblock; 575c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 576c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber /* 577c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * We re-read the superblock every time. Shouldn't need to do this 578c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * really. 579c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 580c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = superblock_read_lock(cmd, &sblock); 581c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 582c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 583c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 584c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super = dm_block_data(sblock); 585c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber read_superblock_fields(cmd, disk_super); 586c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_bm_unlock(sblock); 587c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 588c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; 589c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 590c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 591c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __commit_transaction(struct dm_cache_metadata *cmd, 592c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber flags_mutator mutator) 593c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 594c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 595c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct cache_disk_superblock *disk_super; 596c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_block *sblock; 597c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 598c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber /* 599c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * We need to know if the cache_disk_superblock exceeds a 512-byte sector. 600c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 601c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber BUILD_BUG_ON(sizeof(struct cache_disk_superblock) > 512); 602c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 603c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_bitset_flush(&cmd->discard_info, cmd->discard_root, 604c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &cmd->discard_root); 605c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 606c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 607c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 608c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_tm_pre_commit(cmd->tm); 609c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r < 0) 610c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 611c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 6125a32083d03fb543f63489b2946c4948398579ba0Joe Thornber r = __save_sm_root(cmd); 6135a32083d03fb543f63489b2946c4948398579ba0Joe Thornber if (r) 614c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 615c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 616c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = superblock_lock(cmd, &sblock); 617c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 618c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 619c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 620c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super = dm_block_data(sblock); 621c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 622c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (mutator) 623c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber update_flags(disk_super, mutator); 624c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 625c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->mapping_root = cpu_to_le64(cmd->root); 626c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->hint_root = cpu_to_le64(cmd->hint_root); 627c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->discard_root = cpu_to_le64(cmd->discard_root); 628c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->discard_block_size = cpu_to_le64(cmd->discard_block_size); 62964ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen disk_super->discard_nr_blocks = cpu_to_le64(from_oblock(cmd->discard_nr_blocks)); 630c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->cache_blocks = cpu_to_le32(from_cblock(cmd->cache_blocks)); 631c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber strncpy(disk_super->policy_name, cmd->policy_name, sizeof(disk_super->policy_name)); 6324e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer disk_super->policy_version[0] = cpu_to_le32(cmd->policy_version[0]); 6334e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer disk_super->policy_version[1] = cpu_to_le32(cmd->policy_version[1]); 6344e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer disk_super->policy_version[2] = cpu_to_le32(cmd->policy_version[2]); 635c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 636c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->read_hits = cpu_to_le32(cmd->stats.read_hits); 637c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->read_misses = cpu_to_le32(cmd->stats.read_misses); 638c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->write_hits = cpu_to_le32(cmd->stats.write_hits); 639c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber disk_super->write_misses = cpu_to_le32(cmd->stats.write_misses); 6405a32083d03fb543f63489b2946c4948398579ba0Joe Thornber __copy_sm_root(cmd, disk_super); 641c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 642c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_tm_commit(cmd->tm, sblock); 643c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 644c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 645c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/*----------------------------------------------------------------*/ 646c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 647c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/* 648c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * The mappings are held in a dm-array that has 64-bit values stored in 649c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * little-endian format. The index is the cblock, the high 48bits of the 650c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber * value are the oblock and the low 16 bit the flags. 651c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber */ 652c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber#define FLAGS_MASK ((1 << 16) - 1) 653c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 654c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic __le64 pack_value(dm_oblock_t block, unsigned flags) 655c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 656c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber uint64_t value = from_oblock(block); 657c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber value <<= 16; 658c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber value = value | (flags & FLAGS_MASK); 659c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return cpu_to_le64(value); 660c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 661c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 662c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic void unpack_value(__le64 value_le, dm_oblock_t *block, unsigned *flags) 663c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 664c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber uint64_t value = le64_to_cpu(value_le); 665c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber uint64_t b = value >> 16; 666c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber *block = to_oblock(b); 667c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber *flags = value & FLAGS_MASK; 668c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 669c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 670c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/*----------------------------------------------------------------*/ 671c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 672c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstruct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, 673c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber sector_t data_block_size, 674c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bool may_format_device, 675c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber size_t policy_hint_size) 676c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 677c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 678c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_cache_metadata *cmd; 679c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 680c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 681c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (!cmd) { 682c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber DMERR("could not allocate metadata struct"); 683c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return NULL; 684c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 685c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 686c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber init_rwsem(&cmd->root_lock); 687c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->bdev = bdev; 688c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->data_block_size = data_block_size; 689c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->cache_blocks = 0; 690c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->policy_hint_size = policy_hint_size; 691c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->changed = true; 692c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 693c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __create_persistent_data_objects(cmd, may_format_device); 694c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) { 695c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber kfree(cmd); 696c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return ERR_PTR(r); 697c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 698c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 699c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __begin_transaction_flags(cmd, clear_clean_shutdown); 700c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r < 0) { 701c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_cache_metadata_close(cmd); 702c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return ERR_PTR(r); 703c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 704c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 705c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return cmd; 706c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 707c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 708c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornbervoid dm_cache_metadata_close(struct dm_cache_metadata *cmd) 709c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 710c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __destroy_persistent_data_objects(cmd); 711c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber kfree(cmd); 712c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 713c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 714f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber/* 715f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber * Checks that the given cache block is either unmapped or clean. 716f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber */ 717f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornberstatic int block_unmapped_or_clean(struct dm_cache_metadata *cmd, dm_cblock_t b, 718f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber bool *result) 719f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber{ 720f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber int r; 721f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber __le64 value; 722f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber dm_oblock_t ob; 723f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber unsigned flags; 724f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 725f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber r = dm_array_get_value(&cmd->info, cmd->root, from_cblock(b), &value); 726f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber if (r) { 727f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber DMERR("block_unmapped_or_clean failed"); 728f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber return r; 729f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber } 730f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 731f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber unpack_value(value, &ob, &flags); 732f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber *result = !((flags & M_VALID) && (flags & M_DIRTY)); 733f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 734f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber return 0; 735f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber} 736f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 737f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornberstatic int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd, 738f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber dm_cblock_t begin, dm_cblock_t end, 739f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber bool *result) 740f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber{ 741f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber int r; 742f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber *result = true; 743f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 744f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber while (begin != end) { 745f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber r = block_unmapped_or_clean(cmd, begin, result); 746f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber if (r) 747f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber return r; 748f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 749f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber if (!*result) { 750f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber DMERR("cache block %llu is dirty", 751f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber (unsigned long long) from_cblock(begin)); 752f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber return 0; 753f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber } 754f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 755f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber begin = to_cblock(from_cblock(begin) + 1); 756f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber } 757f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 758f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber return 0; 759f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber} 760f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 761c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size) 762c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 763c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 764f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber bool clean; 765c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 null_mapping = pack_value(0, 0); 766c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 767c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_write(&cmd->root_lock); 768c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __dm_bless_for_disk(&null_mapping); 769f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 770f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber if (from_cblock(new_cache_size) < from_cblock(cmd->cache_blocks)) { 771f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber r = blocks_are_unmapped_or_clean(cmd, new_cache_size, cmd->cache_blocks, &clean); 772f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber if (r) { 773f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber __dm_unbless_for_disk(&null_mapping); 774f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber goto out; 775f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber } 776f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 777f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber if (!clean) { 778f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber DMERR("unable to shrink cache due to dirty blocks"); 779f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber r = -EINVAL; 780f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber __dm_unbless_for_disk(&null_mapping); 781f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber goto out; 782f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber } 783f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber } 784f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 785c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_resize(&cmd->info, cmd->root, from_cblock(cmd->cache_blocks), 786c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber from_cblock(new_cache_size), 787c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &null_mapping, &cmd->root); 788c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (!r) 789c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->cache_blocks = new_cache_size; 790c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->changed = true; 791f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornber 792f494a9c6b1b6dd9a9f21bbb75d9210d478eeb498Joe Thornberout: 793c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_write(&cmd->root_lock); 794c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 795c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 796c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 797c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 798c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd, 799c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber sector_t discard_block_size, 80064ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen dm_oblock_t new_nr_entries) 801c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 802c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 803c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 804c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_write(&cmd->root_lock); 805c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_bitset_resize(&cmd->discard_info, 806c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->discard_root, 80764ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen from_oblock(cmd->discard_nr_blocks), 80864ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen from_oblock(new_nr_entries), 809c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber false, &cmd->discard_root); 810c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (!r) { 811c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->discard_block_size = discard_block_size; 812c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->discard_nr_blocks = new_nr_entries; 813c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 814c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 815c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->changed = true; 816c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_write(&cmd->root_lock); 817c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 818c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 819c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 820c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 82164ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagenstatic int __set_discard(struct dm_cache_metadata *cmd, dm_oblock_t b) 822c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 823c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_bitset_set_bit(&cmd->discard_info, cmd->discard_root, 82464ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen from_oblock(b), &cmd->discard_root); 825c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 826c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 82764ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagenstatic int __clear_discard(struct dm_cache_metadata *cmd, dm_oblock_t b) 828c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 829c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_bitset_clear_bit(&cmd->discard_info, cmd->discard_root, 83064ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen from_oblock(b), &cmd->discard_root); 831c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 832c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 83364ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagenstatic int __is_discarded(struct dm_cache_metadata *cmd, dm_oblock_t b, 834c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bool *is_discarded) 835c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 836c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_bitset_test_bit(&cmd->discard_info, cmd->discard_root, 83764ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen from_oblock(b), &cmd->discard_root, 838c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber is_discarded); 839c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 840c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 841c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __discard(struct dm_cache_metadata *cmd, 84264ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen dm_oblock_t dblock, bool discard) 843c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 844c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 845c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 846c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = (discard ? __set_discard : __clear_discard)(cmd, dblock); 847c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 848c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 849c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 850c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->changed = true; 851c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; 852c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 853c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 854c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_set_discard(struct dm_cache_metadata *cmd, 85564ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen dm_oblock_t dblock, bool discard) 856c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 857c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 858c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 859c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_write(&cmd->root_lock); 860c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __discard(cmd, dblock, discard); 861c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_write(&cmd->root_lock); 862c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 863c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 864c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 865c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 866c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __load_discards(struct dm_cache_metadata *cmd, 867c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber load_discard_fn fn, void *context) 868c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 869c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r = 0; 870c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_block_t b; 871c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bool discard; 872c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 87364ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen for (b = 0; b < from_oblock(cmd->discard_nr_blocks); b++) { 87464ab346a360a4b15c28fb8531918d4a01f4eabd9Heinz Mauelshagen dm_oblock_t dblock = to_oblock(b); 875c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 876c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (cmd->clean_when_opened) { 877c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __is_discarded(cmd, dblock, &discard); 878c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 879c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 880c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } else 881c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber discard = false; 882c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 883c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = fn(context, cmd->discard_block_size, dblock, discard); 884c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 885c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber break; 886c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 887c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 888c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 889c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 890c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 891c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_load_discards(struct dm_cache_metadata *cmd, 892c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber load_discard_fn fn, void *context) 893c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 894c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 895c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 896c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_read(&cmd->root_lock); 897c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __load_discards(cmd, fn, context); 898c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_read(&cmd->root_lock); 899c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 900c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 901c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 902c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 903c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberdm_cblock_t dm_cache_size(struct dm_cache_metadata *cmd) 904c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 905c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_cblock_t r; 906c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 907c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_read(&cmd->root_lock); 908c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = cmd->cache_blocks; 909c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_read(&cmd->root_lock); 910c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 911c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 912c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 913c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 914c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __remove(struct dm_cache_metadata *cmd, dm_cblock_t cblock) 915c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 916c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 917c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 value = pack_value(0, 0); 918c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 919c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __dm_bless_for_disk(&value); 920c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_set_value(&cmd->info, cmd->root, from_cblock(cblock), 921c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &value, &cmd->root); 922c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 923c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 924c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 925c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->changed = true; 926c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; 927c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 928c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 929c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_remove_mapping(struct dm_cache_metadata *cmd, dm_cblock_t cblock) 930c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 931c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 932c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 933c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_write(&cmd->root_lock); 934c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __remove(cmd, cblock); 935c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_write(&cmd->root_lock); 936c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 937c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 938c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 939c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 940c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __insert(struct dm_cache_metadata *cmd, 941c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_cblock_t cblock, dm_oblock_t oblock) 942c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 943c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 944c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 value = pack_value(oblock, M_VALID); 945c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __dm_bless_for_disk(&value); 946c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 947c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_set_value(&cmd->info, cmd->root, from_cblock(cblock), 948c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &value, &cmd->root); 949c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 950c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 951c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 952c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->changed = true; 953c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; 954c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 955c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 956c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_insert_mapping(struct dm_cache_metadata *cmd, 957c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_cblock_t cblock, dm_oblock_t oblock) 958c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 959c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 960c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 961c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_write(&cmd->root_lock); 962c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __insert(cmd, cblock, oblock); 963c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_write(&cmd->root_lock); 964c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 965c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 966c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 967c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 968c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstruct thunk { 969c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber load_mapping_fn fn; 970c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber void *context; 971c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 972c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_cache_metadata *cmd; 973c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bool respect_dirty_flags; 974c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bool hints_valid; 975c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber}; 976c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 977ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzerstatic bool policy_unchanged(struct dm_cache_metadata *cmd, 978ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer struct dm_cache_policy *policy) 979ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer{ 980ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer const char *policy_name = dm_cache_policy_get_name(policy); 981ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer const unsigned *policy_version = dm_cache_policy_get_version(policy); 982ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer size_t policy_hint_size = dm_cache_policy_get_hint_size(policy); 983ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer 984ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer /* 985ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer * Ensure policy names match. 986ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer */ 987ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer if (strncmp(cmd->policy_name, policy_name, sizeof(cmd->policy_name))) 988ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer return false; 989ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer 990ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer /* 991ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer * Ensure policy major versions match. 992ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer */ 993ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer if (cmd->policy_version[0] != policy_version[0]) 994ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer return false; 995ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer 996ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer /* 997ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer * Ensure policy hint sizes match. 998ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer */ 999ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer if (cmd->policy_hint_size != policy_hint_size) 1000ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer return false; 1001ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer 1002ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer return true; 1003ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer} 1004ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer 1005c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic bool hints_array_initialized(struct dm_cache_metadata *cmd) 1006c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1007c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return cmd->hint_root && cmd->policy_hint_size; 1008c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1009c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1010c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic bool hints_array_available(struct dm_cache_metadata *cmd, 1011ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer struct dm_cache_policy *policy) 1012c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1013ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer return cmd->clean_when_opened && policy_unchanged(cmd, policy) && 1014c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber hints_array_initialized(cmd); 1015c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1016c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1017c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __load_mapping(void *context, uint64_t cblock, void *leaf) 1018c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1019c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r = 0; 1020c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber bool dirty; 1021c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 value; 1022c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 hint_value = 0; 1023c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_oblock_t oblock; 1024c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber unsigned flags; 1025c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct thunk *thunk = context; 1026c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_cache_metadata *cmd = thunk->cmd; 1027c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1028c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber memcpy(&value, leaf, sizeof(value)); 1029c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber unpack_value(value, &oblock, &flags); 1030c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1031c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (flags & M_VALID) { 1032c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (thunk->hints_valid) { 1033c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_get_value(&cmd->hint_info, cmd->hint_root, 1034c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cblock, &hint_value); 1035c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r && r != -ENODATA) 1036c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1037c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 1038c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1039c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dirty = thunk->respect_dirty_flags ? (flags & M_DIRTY) : true; 1040c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = thunk->fn(thunk->context, oblock, to_cblock(cblock), 1041c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dirty, le32_to_cpu(hint_value), thunk->hints_valid); 1042c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 1043c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1044c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1045c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1046c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1047ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzerstatic int __load_mappings(struct dm_cache_metadata *cmd, 1048ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer struct dm_cache_policy *policy, 1049c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber load_mapping_fn fn, void *context) 1050c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1051c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct thunk thunk; 1052c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1053c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber thunk.fn = fn; 1054c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber thunk.context = context; 1055c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1056c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber thunk.cmd = cmd; 1057c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber thunk.respect_dirty_flags = cmd->clean_when_opened; 1058ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer thunk.hints_valid = hints_array_available(cmd, policy); 1059c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1060c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk); 1061c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1062c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1063ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzerint dm_cache_load_mappings(struct dm_cache_metadata *cmd, 1064ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer struct dm_cache_policy *policy, 1065c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber load_mapping_fn fn, void *context) 1066c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1067c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 1068c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1069c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_read(&cmd->root_lock); 1070ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer r = __load_mappings(cmd, policy, fn, context); 1071c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_read(&cmd->root_lock); 1072c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1073c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1074c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1075c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1076c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __dump_mapping(void *context, uint64_t cblock, void *leaf) 1077c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1078c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r = 0; 1079c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 value; 1080c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_oblock_t oblock; 1081c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber unsigned flags; 1082c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1083c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber memcpy(&value, leaf, sizeof(value)); 1084c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber unpack_value(value, &oblock, &flags); 1085c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1086c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1087c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1088c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1089c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __dump_mappings(struct dm_cache_metadata *cmd) 1090c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1091c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return dm_array_walk(&cmd->info, cmd->root, __dump_mapping, NULL); 1092c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1093c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1094c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornbervoid dm_cache_dump(struct dm_cache_metadata *cmd) 1095c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1096c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_read(&cmd->root_lock); 1097c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __dump_mappings(cmd); 1098c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_read(&cmd->root_lock); 1099c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1100c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1101c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd) 1102c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1103c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 1104c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1105c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_read(&cmd->root_lock); 1106c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = cmd->changed; 1107c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_read(&cmd->root_lock); 1108c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1109c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1110c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1111c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1112c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int __dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty) 1113c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1114c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 1115c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber unsigned flags; 1116c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_oblock_t oblock; 1117c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le64 value; 1118c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1119c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_get_value(&cmd->info, cmd->root, from_cblock(cblock), &value); 1120c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 1121c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1122c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1123c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber unpack_value(value, &oblock, &flags); 1124c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1125c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (((flags & M_DIRTY) && dirty) || (!(flags & M_DIRTY) && !dirty)) 1126c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber /* nothing to be done */ 1127c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; 1128c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 112979ed9caffc9fff67aa64fd683e791aa70f1bcb51Joe Thornber value = pack_value(oblock, (flags & ~M_DIRTY) | (dirty ? M_DIRTY : 0)); 1130c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __dm_bless_for_disk(&value); 1131c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1132c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_set_value(&cmd->info, cmd->root, from_cblock(cblock), 1133c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &value, &cmd->root); 1134c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 1135c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1136c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1137c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->changed = true; 1138c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; 1139c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1140c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1141c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1142c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_set_dirty(struct dm_cache_metadata *cmd, 1143c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_cblock_t cblock, bool dirty) 1144c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1145c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 1146c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1147c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_write(&cmd->root_lock); 1148c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __dirty(cmd, cblock, dirty); 1149c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_write(&cmd->root_lock); 1150c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1151c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1152c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1153c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1154c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornbervoid dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd, 1155c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_cache_statistics *stats) 1156c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1157c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_read(&cmd->root_lock); 11588c5008fac4af85c7a597c4e7f2c328ac90652bc2Joe Thornber *stats = cmd->stats; 1159c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_read(&cmd->root_lock); 1160c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1161c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1162c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornbervoid dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd, 1163c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber struct dm_cache_statistics *stats) 1164c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1165c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_write(&cmd->root_lock); 11668c5008fac4af85c7a597c4e7f2c328ac90652bc2Joe Thornber cmd->stats = *stats; 1167c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_write(&cmd->root_lock); 1168c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1169c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1170c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown) 1171c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1172c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 1173c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber flags_mutator mutator = (clean_shutdown ? set_clean_shutdown : 1174c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber clear_clean_shutdown); 1175c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1176c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_write(&cmd->root_lock); 1177c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __commit_transaction(cmd, mutator); 1178c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 1179c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber goto out; 1180c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1181c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = __begin_transaction(cmd); 1182c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1183c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberout: 1184c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_write(&cmd->root_lock); 1185c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1186c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1187c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1188c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_get_free_metadata_block_count(struct dm_cache_metadata *cmd, 1189c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_block_t *result) 1190c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1191c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r = -EINVAL; 1192c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1193c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_read(&cmd->root_lock); 1194c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_sm_get_nr_free(cmd->metadata_sm, result); 1195c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_read(&cmd->root_lock); 1196c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1197c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1198c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1199c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1200c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberint dm_cache_get_metadata_dev_size(struct dm_cache_metadata *cmd, 1201c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber dm_block_t *result) 1202c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1203c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r = -EINVAL; 1204c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1205c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_read(&cmd->root_lock); 1206c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_sm_get_nr_blocks(cmd->metadata_sm, result); 1207c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_read(&cmd->root_lock); 1208c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1209c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1210c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1211c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1212c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber/*----------------------------------------------------------------*/ 1213c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1214c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornberstatic int begin_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *policy) 1215c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1216c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 1217c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __le32 value; 1218c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber size_t hint_size; 1219c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber const char *policy_name = dm_cache_policy_get_name(policy); 12204e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer const unsigned *policy_version = dm_cache_policy_get_version(policy); 1221c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1222c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (!policy_name[0] || 1223c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber (strlen(policy_name) > sizeof(cmd->policy_name) - 1)) 1224c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return -EINVAL; 1225c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1226ea2dd8c1ed0becee9812cf0840a9cd553ed398feMike Snitzer if (!policy_unchanged(cmd, policy)) { 1227c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber strncpy(cmd->policy_name, policy_name, sizeof(cmd->policy_name)); 12284e7f506f6429636115e2f58f9f97089acc62524aMike Snitzer memcpy(cmd->policy_version, policy_version, sizeof(cmd->policy_version)); 1229c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1230c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber hint_size = dm_cache_policy_get_hint_size(policy); 1231c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (!hint_size) 1232c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; /* short-circuit hints initialization */ 1233c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->policy_hint_size = hint_size; 1234c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1235c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (cmd->hint_root) { 1236c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_del(&cmd->hint_info, cmd->hint_root); 1237c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 1238c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1239c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 1240c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1241c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_empty(&cmd->hint_info, &cmd->hint_root); 1242c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 1243c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1244c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1245c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber value = cpu_to_le32(0); 1246c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __dm_bless_for_disk(&value); 1247c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_resize(&cmd->hint_info, cmd->hint_root, 0, 1248c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber from_cblock(cmd->cache_blocks), 1249c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber &value, &cmd->hint_root); 1250c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber if (r) 1251c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1252c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber } 1253c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1254c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return 0; 1255c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1256c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 12570596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornberstatic int save_hint(void *context, dm_cblock_t cblock, dm_oblock_t oblock, uint32_t hint) 1258c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 12590596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber struct dm_cache_metadata *cmd = context; 12600596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber __le32 value = cpu_to_le32(hint); 1261c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 1262c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1263c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber __dm_bless_for_disk(&value); 1264c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1265c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber r = dm_array_set_value(&cmd->hint_info, cmd->hint_root, 1266c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber from_cblock(cblock), &value, &cmd->hint_root); 1267c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber cmd->changed = true; 1268c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1269c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1270c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 1271c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 12720596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornberstatic int write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *policy) 1273c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber{ 1274c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber int r; 1275c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 12760596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber r = begin_hints(cmd, policy); 12770596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber if (r) { 12780596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber DMERR("begin_hints failed"); 12790596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber return r; 12800596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber } 12810596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber 12820596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber return policy_walk_mappings(policy, save_hint, cmd); 12830596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber} 12840596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber 12850596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornberint dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *policy) 12860596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber{ 12870596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber int r; 1288c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1289c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber down_write(&cmd->root_lock); 12900596661f0a16d9d69bf1033320e70b6ff52b5e81Joe Thornber r = write_hints(cmd, policy); 1291c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber up_write(&cmd->root_lock); 1292c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber 1293c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber return r; 1294c6b4fcbad044e6fffcc75bba160e720eb8d67d17Joe Thornber} 12952ee57d587357f0d752af6c2e3e46434a74b1bee3Joe Thornber 12962ee57d587357f0d752af6c2e3e46434a74b1bee3Joe Thornberint dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result) 12972ee57d587357f0d752af6c2e3e46434a74b1bee3Joe Thornber{ 12982ee57d587357f0d752af6c2e3e46434a74b1bee3Joe Thornber return blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result); 12992ee57d587357f0d752af6c2e3e46434a74b1bee3Joe Thornber} 1300