1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * Copyright (C) 2010-2011 Red Hat, Inc. 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * This file is released under the GPL. 5*4882a593Smuzhiyun */ 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun #ifndef DM_THIN_METADATA_H 8*4882a593Smuzhiyun #define DM_THIN_METADATA_H 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun #include "persistent-data/dm-block-manager.h" 11*4882a593Smuzhiyun #include "persistent-data/dm-space-map.h" 12*4882a593Smuzhiyun #include "persistent-data/dm-space-map-metadata.h" 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun #define THIN_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun /* 17*4882a593Smuzhiyun * The metadata device is currently limited in size. 18*4882a593Smuzhiyun */ 19*4882a593Smuzhiyun #define THIN_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun /* 22*4882a593Smuzhiyun * A metadata device larger than 16GB triggers a warning. 23*4882a593Smuzhiyun */ 24*4882a593Smuzhiyun #define THIN_METADATA_MAX_SECTORS_WARNING (16 * (1024 * 1024 * 1024 >> SECTOR_SHIFT)) 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun /*----------------------------------------------------------------*/ 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun /* 29*4882a593Smuzhiyun * Thin metadata superblock flags. 30*4882a593Smuzhiyun */ 31*4882a593Smuzhiyun #define THIN_METADATA_NEEDS_CHECK_FLAG (1 << 0) 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun struct dm_pool_metadata; 34*4882a593Smuzhiyun struct dm_thin_device; 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun /* 37*4882a593Smuzhiyun * Device identifier 38*4882a593Smuzhiyun */ 39*4882a593Smuzhiyun typedef uint64_t dm_thin_id; 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun /* 42*4882a593Smuzhiyun * Reopens or creates a new, empty metadata volume. 43*4882a593Smuzhiyun */ 44*4882a593Smuzhiyun struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev, 45*4882a593Smuzhiyun sector_t data_block_size, 46*4882a593Smuzhiyun bool format_device); 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun int dm_pool_metadata_close(struct dm_pool_metadata *pmd); 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun /* 51*4882a593Smuzhiyun * Compat feature flags. Any incompat flags beyond the ones 52*4882a593Smuzhiyun * specified below will prevent use of the thin metadata. 53*4882a593Smuzhiyun */ 54*4882a593Smuzhiyun #define THIN_FEATURE_COMPAT_SUPP 0UL 55*4882a593Smuzhiyun #define THIN_FEATURE_COMPAT_RO_SUPP 0UL 56*4882a593Smuzhiyun #define THIN_FEATURE_INCOMPAT_SUPP 0UL 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun /* 59*4882a593Smuzhiyun * Device creation/deletion. 60*4882a593Smuzhiyun */ 61*4882a593Smuzhiyun int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev); 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun /* 64*4882a593Smuzhiyun * An internal snapshot. 65*4882a593Smuzhiyun * 66*4882a593Smuzhiyun * You can only snapshot a quiesced origin i.e. one that is either 67*4882a593Smuzhiyun * suspended or not instanced at all. 68*4882a593Smuzhiyun */ 69*4882a593Smuzhiyun int dm_pool_create_snap(struct dm_pool_metadata *pmd, dm_thin_id dev, 70*4882a593Smuzhiyun dm_thin_id origin); 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun /* 73*4882a593Smuzhiyun * Deletes a virtual device from the metadata. It _is_ safe to call this 74*4882a593Smuzhiyun * when that device is open. Operations on that device will just start 75*4882a593Smuzhiyun * failing. You still need to call close() on the device. 76*4882a593Smuzhiyun */ 77*4882a593Smuzhiyun int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd, 78*4882a593Smuzhiyun dm_thin_id dev); 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun /* 81*4882a593Smuzhiyun * Commits _all_ metadata changes: device creation, deletion, mapping 82*4882a593Smuzhiyun * updates. 83*4882a593Smuzhiyun */ 84*4882a593Smuzhiyun int dm_pool_commit_metadata(struct dm_pool_metadata *pmd); 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun /* 87*4882a593Smuzhiyun * Discards all uncommitted changes. Rereads the superblock, rolling back 88*4882a593Smuzhiyun * to the last good transaction. Thin devices remain open. 89*4882a593Smuzhiyun * dm_thin_aborted_changes() tells you if they had uncommitted changes. 90*4882a593Smuzhiyun * 91*4882a593Smuzhiyun * If this call fails it's only useful to call dm_pool_metadata_close(). 92*4882a593Smuzhiyun * All other methods will fail with -EINVAL. 93*4882a593Smuzhiyun */ 94*4882a593Smuzhiyun int dm_pool_abort_metadata(struct dm_pool_metadata *pmd); 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun /* 97*4882a593Smuzhiyun * Set/get userspace transaction id. 98*4882a593Smuzhiyun */ 99*4882a593Smuzhiyun int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd, 100*4882a593Smuzhiyun uint64_t current_id, 101*4882a593Smuzhiyun uint64_t new_id); 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd, 104*4882a593Smuzhiyun uint64_t *result); 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun /* 107*4882a593Smuzhiyun * Hold/get root for userspace transaction. 108*4882a593Smuzhiyun * 109*4882a593Smuzhiyun * The metadata snapshot is a copy of the current superblock (minus the 110*4882a593Smuzhiyun * space maps). Userland can access the data structures for READ 111*4882a593Smuzhiyun * operations only. A small performance hit is incurred by providing this 112*4882a593Smuzhiyun * copy of the metadata to userland due to extra copy-on-write operations 113*4882a593Smuzhiyun * on the metadata nodes. Release this as soon as you finish with it. 114*4882a593Smuzhiyun */ 115*4882a593Smuzhiyun int dm_pool_reserve_metadata_snap(struct dm_pool_metadata *pmd); 116*4882a593Smuzhiyun int dm_pool_release_metadata_snap(struct dm_pool_metadata *pmd); 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd, 119*4882a593Smuzhiyun dm_block_t *result); 120*4882a593Smuzhiyun 121*4882a593Smuzhiyun /* 122*4882a593Smuzhiyun * Actions on a single virtual device. 123*4882a593Smuzhiyun */ 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun /* 126*4882a593Smuzhiyun * Opening the same device more than once will fail with -EBUSY. 127*4882a593Smuzhiyun */ 128*4882a593Smuzhiyun int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev, 129*4882a593Smuzhiyun struct dm_thin_device **td); 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun int dm_pool_close_thin_device(struct dm_thin_device *td); 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun dm_thin_id dm_thin_dev_id(struct dm_thin_device *td); 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun struct dm_thin_lookup_result { 136*4882a593Smuzhiyun dm_block_t block; 137*4882a593Smuzhiyun bool shared:1; 138*4882a593Smuzhiyun }; 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun /* 141*4882a593Smuzhiyun * Returns: 142*4882a593Smuzhiyun * -EWOULDBLOCK iff @can_issue_io is set and would issue IO 143*4882a593Smuzhiyun * -ENODATA iff that mapping is not present. 144*4882a593Smuzhiyun * 0 success 145*4882a593Smuzhiyun */ 146*4882a593Smuzhiyun int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block, 147*4882a593Smuzhiyun int can_issue_io, struct dm_thin_lookup_result *result); 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun /* 150*4882a593Smuzhiyun * Retrieve the next run of contiguously mapped blocks. Useful for working 151*4882a593Smuzhiyun * out where to break up IO. Returns 0 on success, < 0 on error. 152*4882a593Smuzhiyun */ 153*4882a593Smuzhiyun int dm_thin_find_mapped_range(struct dm_thin_device *td, 154*4882a593Smuzhiyun dm_block_t begin, dm_block_t end, 155*4882a593Smuzhiyun dm_block_t *thin_begin, dm_block_t *thin_end, 156*4882a593Smuzhiyun dm_block_t *pool_begin, bool *maybe_shared); 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun /* 159*4882a593Smuzhiyun * Obtain an unused block. 160*4882a593Smuzhiyun */ 161*4882a593Smuzhiyun int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result); 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun /* 164*4882a593Smuzhiyun * Insert or remove block. 165*4882a593Smuzhiyun */ 166*4882a593Smuzhiyun int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block, 167*4882a593Smuzhiyun dm_block_t data_block); 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block); 170*4882a593Smuzhiyun int dm_thin_remove_range(struct dm_thin_device *td, 171*4882a593Smuzhiyun dm_block_t begin, dm_block_t end); 172*4882a593Smuzhiyun 173*4882a593Smuzhiyun /* 174*4882a593Smuzhiyun * Queries. 175*4882a593Smuzhiyun */ 176*4882a593Smuzhiyun bool dm_thin_changed_this_transaction(struct dm_thin_device *td); 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun bool dm_pool_changed_this_transaction(struct dm_pool_metadata *pmd); 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun bool dm_thin_aborted_changes(struct dm_thin_device *td); 181*4882a593Smuzhiyun 182*4882a593Smuzhiyun int dm_thin_get_highest_mapped_block(struct dm_thin_device *td, 183*4882a593Smuzhiyun dm_block_t *highest_mapped); 184*4882a593Smuzhiyun 185*4882a593Smuzhiyun int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result); 186*4882a593Smuzhiyun 187*4882a593Smuzhiyun int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, 188*4882a593Smuzhiyun dm_block_t *result); 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd, 191*4882a593Smuzhiyun dm_block_t *result); 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd, 194*4882a593Smuzhiyun dm_block_t *result); 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result); 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result); 199*4882a593Smuzhiyun 200*4882a593Smuzhiyun int dm_pool_inc_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e); 201*4882a593Smuzhiyun int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e); 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun /* 204*4882a593Smuzhiyun * Returns -ENOSPC if the new size is too small and already allocated 205*4882a593Smuzhiyun * blocks would be lost. 206*4882a593Smuzhiyun */ 207*4882a593Smuzhiyun int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size); 208*4882a593Smuzhiyun int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_size); 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun /* 211*4882a593Smuzhiyun * Flicks the underlying block manager into read only mode, so you know 212*4882a593Smuzhiyun * that nothing is changing. 213*4882a593Smuzhiyun */ 214*4882a593Smuzhiyun void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd); 215*4882a593Smuzhiyun void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd); 216*4882a593Smuzhiyun 217*4882a593Smuzhiyun int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd, 218*4882a593Smuzhiyun dm_block_t threshold, 219*4882a593Smuzhiyun dm_sm_threshold_fn fn, 220*4882a593Smuzhiyun void *context); 221*4882a593Smuzhiyun 222*4882a593Smuzhiyun /* 223*4882a593Smuzhiyun * Updates the superblock immediately. 224*4882a593Smuzhiyun */ 225*4882a593Smuzhiyun int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd); 226*4882a593Smuzhiyun bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd); 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun /* 229*4882a593Smuzhiyun * Issue any prefetches that may be useful. 230*4882a593Smuzhiyun */ 231*4882a593Smuzhiyun void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd); 232*4882a593Smuzhiyun 233*4882a593Smuzhiyun /* Pre-commit callback */ 234*4882a593Smuzhiyun typedef int (*dm_pool_pre_commit_fn)(void *context); 235*4882a593Smuzhiyun 236*4882a593Smuzhiyun void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd, 237*4882a593Smuzhiyun dm_pool_pre_commit_fn fn, 238*4882a593Smuzhiyun void *context); 239*4882a593Smuzhiyun 240*4882a593Smuzhiyun /*----------------------------------------------------------------*/ 241*4882a593Smuzhiyun 242*4882a593Smuzhiyun #endif 243