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