Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2019 Arrikto, Inc. All Rights Reserved. */ #ifndef DM_CLONE_METADATA_H #define DM_CLONE_METADATA_H #include "persistent-data/dm-block-manager.h" #include "persistent-data/dm-space-map-metadata.h" #define DM_CLONE_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE /* * The metadata device is currently limited in size. */ #define DM_CLONE_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS /* * A metadata device larger than 16GB triggers a warning. */ #define DM_CLONE_METADATA_MAX_SECTORS_WARNING (16 * (1024 * 1024 * 1024 >> SECTOR_SHIFT)) #define SPACE_MAP_ROOT_SIZE 128 /* dm-clone metadata */ struct dm_clone_metadata; /* * Set region status to hydrated. * * @cmd: The dm-clone metadata * @region_nr: The region number * * This function doesn't block, so it's safe to call it from interrupt context. */ int dm_clone_set_region_hydrated(struct dm_clone_metadata *cmd, unsigned long region_nr); /* * Set status of all regions in the provided range to hydrated, if not already * hydrated. * * @cmd: The dm-clone metadata * @start: Starting region number * @nr_regions: Number of regions in the range * * This function doesn't block, but since it uses spin_lock_irq()/spin_unlock_irq() * it's NOT safe to call it from any context where interrupts are disabled, e.g., * from interrupt context. */ int dm_clone_cond_set_range(struct dm_clone_metadata *cmd, unsigned long start, unsigned long nr_regions); /* * Read existing or create fresh metadata. * * @bdev: The device storing the metadata * @target_size: The target size * @region_size: The region size * * @returns: The dm-clone metadata * * This function reads the superblock of @bdev and checks if it's all zeroes. * If it is, it formats @bdev and creates fresh metadata. If it isn't, it * validates the metadata stored in @bdev. */ struct dm_clone_metadata *dm_clone_metadata_open(struct block_device *bdev, sector_t target_size, sector_t region_size); /* * Free the resources related to metadata management. */ void dm_clone_metadata_close(struct dm_clone_metadata *cmd); /* * Commit dm-clone metadata to disk. * * We use a two phase commit: * * 1. dm_clone_metadata_pre_commit(): Prepare the current transaction for * committing. After this is called, all subsequent metadata updates, done * through either dm_clone_set_region_hydrated() or * dm_clone_cond_set_range(), will be part of the **next** transaction. * * 2. dm_clone_metadata_commit(): Actually commit the current transaction to * disk and start a new transaction. * * This allows dm-clone to flush the destination device after step (1) to * ensure that all freshly hydrated regions, for which we are updating the * metadata, are properly written to non-volatile storage and won't be lost in * case of a crash. */ int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd); int dm_clone_metadata_commit(struct dm_clone_metadata *cmd); /* * Reload the in core copy of the on-disk bitmap. * * This should be used after aborting a metadata transaction and setting the * metadata to read-only, to invalidate the in-core cache and make it match the * on-disk metadata. * * WARNING: It must not be called concurrently with either * dm_clone_set_region_hydrated() or dm_clone_cond_set_range(), as it updates * the region bitmap without taking the relevant spinlock. We don't take the * spinlock because dm_clone_reload_in_core_bitset() does I/O, so it may block. * * But, it's safe to use it after calling dm_clone_metadata_set_read_only(), * because the latter sets the metadata to read-only mode. Both * dm_clone_set_region_hydrated() and dm_clone_cond_set_range() refuse to touch * the region bitmap, after calling dm_clone_metadata_set_read_only(). */ int dm_clone_reload_in_core_bitset(struct dm_clone_metadata *cmd); /* * Check whether dm-clone's metadata changed this transaction. */ bool dm_clone_changed_this_transaction(struct dm_clone_metadata *cmd); /* * Abort current metadata transaction and rollback metadata to the last * committed transaction. */ int dm_clone_metadata_abort(struct dm_clone_metadata *cmd); /* * Switches metadata to a read only mode. Once read-only mode has been entered * the following functions will return -EPERM: * * dm_clone_metadata_pre_commit() * dm_clone_metadata_commit() * dm_clone_set_region_hydrated() * dm_clone_cond_set_range() * dm_clone_metadata_abort() */ void dm_clone_metadata_set_read_only(struct dm_clone_metadata *cmd); void dm_clone_metadata_set_read_write(struct dm_clone_metadata *cmd); /* * Returns true if the hydration of the destination device is finished. */ bool dm_clone_is_hydration_done(struct dm_clone_metadata *cmd); /* * Returns true if region @region_nr is hydrated. */ bool dm_clone_is_region_hydrated(struct dm_clone_metadata *cmd, unsigned long region_nr); /* * Returns true if all the regions in the range are hydrated. */ bool dm_clone_is_range_hydrated(struct dm_clone_metadata *cmd, unsigned long start, unsigned long nr_regions); /* * Returns the number of hydrated regions. */ unsigned int dm_clone_nr_of_hydrated_regions(struct dm_clone_metadata *cmd); /* * Returns the first unhydrated region with region_nr >= @start */ unsigned long dm_clone_find_next_unhydrated_region(struct dm_clone_metadata *cmd, unsigned long start); /* * Get the number of free metadata blocks. */ int dm_clone_get_free_metadata_block_count(struct dm_clone_metadata *cmd, dm_block_t *result); /* * Get the total number of metadata blocks. */ int dm_clone_get_metadata_dev_size(struct dm_clone_metadata *cmd, dm_block_t *result); #endif /* DM_CLONE_METADATA_H */ |