dm-exception-store.h (5377B)
1/* 2 * Copyright (C) 2001-2002 Sistina Software (UK) Limited. 3 * Copyright (C) 2008 Red Hat, Inc. All rights reserved. 4 * 5 * Device-mapper snapshot exception store. 6 * 7 * This file is released under the GPL. 8 */ 9 10#ifndef _LINUX_DM_EXCEPTION_STORE 11#define _LINUX_DM_EXCEPTION_STORE 12 13#include <linux/blkdev.h> 14#include <linux/list_bl.h> 15#include <linux/device-mapper.h> 16 17/* 18 * The snapshot code deals with largish chunks of the disk at a 19 * time. Typically 32k - 512k. 20 */ 21typedef sector_t chunk_t; 22 23/* 24 * An exception is used where an old chunk of data has been 25 * replaced by a new one. 26 * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number 27 * of chunks that follow contiguously. Remaining bits hold the number of the 28 * chunk within the device. 29 */ 30struct dm_exception { 31 struct hlist_bl_node hash_list; 32 33 chunk_t old_chunk; 34 chunk_t new_chunk; 35}; 36 37/* 38 * Abstraction to handle the meta/layout of exception stores (the 39 * COW device). 40 */ 41struct dm_exception_store; 42struct dm_exception_store_type { 43 const char *name; 44 struct module *module; 45 46 int (*ctr) (struct dm_exception_store *store, char *options); 47 48 /* 49 * Destroys this object when you've finished with it. 50 */ 51 void (*dtr) (struct dm_exception_store *store); 52 53 /* 54 * The target shouldn't read the COW device until this is 55 * called. As exceptions are read from the COW, they are 56 * reported back via the callback. 57 */ 58 int (*read_metadata) (struct dm_exception_store *store, 59 int (*callback)(void *callback_context, 60 chunk_t old, chunk_t new), 61 void *callback_context); 62 63 /* 64 * Find somewhere to store the next exception. 65 */ 66 int (*prepare_exception) (struct dm_exception_store *store, 67 struct dm_exception *e); 68 69 /* 70 * Update the metadata with this exception. 71 */ 72 void (*commit_exception) (struct dm_exception_store *store, 73 struct dm_exception *e, int valid, 74 void (*callback) (void *, int success), 75 void *callback_context); 76 77 /* 78 * Returns 0 if the exception store is empty. 79 * 80 * If there are exceptions still to be merged, sets 81 * *last_old_chunk and *last_new_chunk to the most recent 82 * still-to-be-merged chunk and returns the number of 83 * consecutive previous ones. 84 */ 85 int (*prepare_merge) (struct dm_exception_store *store, 86 chunk_t *last_old_chunk, chunk_t *last_new_chunk); 87 88 /* 89 * Clear the last n exceptions. 90 * nr_merged must be <= the value returned by prepare_merge. 91 */ 92 int (*commit_merge) (struct dm_exception_store *store, int nr_merged); 93 94 /* 95 * The snapshot is invalid, note this in the metadata. 96 */ 97 void (*drop_snapshot) (struct dm_exception_store *store); 98 99 unsigned (*status) (struct dm_exception_store *store, 100 status_type_t status, char *result, 101 unsigned maxlen); 102 103 /* 104 * Return how full the snapshot is. 105 */ 106 void (*usage) (struct dm_exception_store *store, 107 sector_t *total_sectors, sector_t *sectors_allocated, 108 sector_t *metadata_sectors); 109 110 /* For internal device-mapper use only. */ 111 struct list_head list; 112}; 113 114struct dm_snapshot; 115 116struct dm_exception_store { 117 struct dm_exception_store_type *type; 118 struct dm_snapshot *snap; 119 120 /* Size of data blocks saved - must be a power of 2 */ 121 unsigned chunk_size; 122 unsigned chunk_mask; 123 unsigned chunk_shift; 124 125 void *context; 126 127 bool userspace_supports_overflow; 128}; 129 130/* 131 * Obtain the origin or cow device used by a given snapshot. 132 */ 133struct dm_dev *dm_snap_origin(struct dm_snapshot *snap); 134struct dm_dev *dm_snap_cow(struct dm_snapshot *snap); 135 136/* 137 * Funtions to manipulate consecutive chunks 138 */ 139#define DM_CHUNK_CONSECUTIVE_BITS 8 140#define DM_CHUNK_NUMBER_BITS 56 141 142static inline chunk_t dm_chunk_number(chunk_t chunk) 143{ 144 return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL); 145} 146 147static inline unsigned dm_consecutive_chunk_count(struct dm_exception *e) 148{ 149 return e->new_chunk >> DM_CHUNK_NUMBER_BITS; 150} 151 152static inline void dm_consecutive_chunk_count_inc(struct dm_exception *e) 153{ 154 e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS); 155 156 BUG_ON(!dm_consecutive_chunk_count(e)); 157} 158 159static inline void dm_consecutive_chunk_count_dec(struct dm_exception *e) 160{ 161 BUG_ON(!dm_consecutive_chunk_count(e)); 162 163 e->new_chunk -= (1ULL << DM_CHUNK_NUMBER_BITS); 164} 165 166/* 167 * Return the number of sectors in the device. 168 */ 169static inline sector_t get_dev_size(struct block_device *bdev) 170{ 171 return bdev_nr_sectors(bdev); 172} 173 174static inline chunk_t sector_to_chunk(struct dm_exception_store *store, 175 sector_t sector) 176{ 177 return sector >> store->chunk_shift; 178} 179 180int dm_exception_store_type_register(struct dm_exception_store_type *type); 181int dm_exception_store_type_unregister(struct dm_exception_store_type *type); 182 183int dm_exception_store_set_chunk_size(struct dm_exception_store *store, 184 unsigned chunk_size, 185 char **error); 186 187int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, 188 struct dm_snapshot *snap, 189 unsigned *args_used, 190 struct dm_exception_store **store); 191void dm_exception_store_destroy(struct dm_exception_store *store); 192 193int dm_exception_store_init(void); 194void dm_exception_store_exit(void); 195 196/* 197 * Two exception store implementations. 198 */ 199int dm_persistent_snapshot_init(void); 200void dm_persistent_snapshot_exit(void); 201 202int dm_transient_snapshot_init(void); 203void dm_transient_snapshot_exit(void); 204 205#endif /* _LINUX_DM_EXCEPTION_STORE */