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/device-mapper.h> 15 16 /* 17 * The snapshot code deals with largish chunks of the disk at a 18 * time. Typically 32k - 512k. 19 */ 20 typedef sector_t chunk_t; 21 22 /* 23 * An exception is used where an old chunk of data has been 24 * replaced by a new one. 25 * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number 26 * of chunks that follow contiguously. Remaining bits hold the number of the 27 * chunk within the device. 28 */ 29 struct dm_snap_exception { 30 struct list_head hash_list; 31 32 chunk_t old_chunk; 33 chunk_t new_chunk; 34 }; 35 36 /* 37 * Abstraction to handle the meta/layout of exception stores (the 38 * COW device). 39 */ 40 struct dm_exception_store; 41 struct dm_exception_store_type { 42 const char *name; 43 struct module *module; 44 45 int (*ctr) (struct dm_exception_store *store, 46 unsigned argc, char **argv); 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_snap_exception *e); 68 69 /* 70 * Update the metadata with this exception. 71 */ 72 void (*commit_exception) (struct dm_exception_store *store, 73 struct dm_snap_exception *e, 74 void (*callback) (void *, int success), 75 void *callback_context); 76 77 /* 78 * The snapshot is invalid, note this in the metadata. 79 */ 80 void (*drop_snapshot) (struct dm_exception_store *store); 81 82 unsigned (*status) (struct dm_exception_store *store, 83 status_type_t status, char *result, 84 unsigned maxlen); 85 86 /* 87 * Return how full the snapshot is. 88 */ 89 void (*fraction_full) (struct dm_exception_store *store, 90 sector_t *numerator, 91 sector_t *denominator); 92 93 /* For internal device-mapper use only. */ 94 struct list_head list; 95 }; 96 97 struct dm_exception_store { 98 struct dm_exception_store_type *type; 99 struct dm_target *ti; 100 101 struct dm_dev *cow; 102 103 /* Size of data blocks saved - must be a power of 2 */ 104 chunk_t chunk_size; 105 chunk_t chunk_mask; 106 chunk_t chunk_shift; 107 108 void *context; 109 }; 110 111 /* 112 * Funtions to manipulate consecutive chunks 113 */ 114 # if defined(CONFIG_LBDAF) || (BITS_PER_LONG == 64) 115 # define DM_CHUNK_CONSECUTIVE_BITS 8 116 # define DM_CHUNK_NUMBER_BITS 56 117 118 static inline chunk_t dm_chunk_number(chunk_t chunk) 119 { 120 return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL); 121 } 122 123 static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e) 124 { 125 return e->new_chunk >> DM_CHUNK_NUMBER_BITS; 126 } 127 128 static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e) 129 { 130 e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS); 131 132 BUG_ON(!dm_consecutive_chunk_count(e)); 133 } 134 135 # else 136 # define DM_CHUNK_CONSECUTIVE_BITS 0 137 138 static inline chunk_t dm_chunk_number(chunk_t chunk) 139 { 140 return chunk; 141 } 142 143 static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e) 144 { 145 return 0; 146 } 147 148 static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e) 149 { 150 } 151 152 # endif 153 154 /* 155 * Return the number of sectors in the device. 156 */ 157 static inline sector_t get_dev_size(struct block_device *bdev) 158 { 159 return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; 160 } 161 162 static inline chunk_t sector_to_chunk(struct dm_exception_store *store, 163 sector_t sector) 164 { 165 return (sector & ~store->chunk_mask) >> store->chunk_shift; 166 } 167 168 int dm_exception_store_type_register(struct dm_exception_store_type *type); 169 int dm_exception_store_type_unregister(struct dm_exception_store_type *type); 170 171 int dm_exception_store_set_chunk_size(struct dm_exception_store *store, 172 unsigned long chunk_size_ulong, 173 char **error); 174 175 int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, 176 unsigned *args_used, 177 struct dm_exception_store **store); 178 void dm_exception_store_destroy(struct dm_exception_store *store); 179 180 int dm_exception_store_init(void); 181 void dm_exception_store_exit(void); 182 183 /* 184 * Two exception store implementations. 185 */ 186 int dm_persistent_snapshot_init(void); 187 void dm_persistent_snapshot_exit(void); 188 189 int dm_transient_snapshot_init(void); 190 void dm_transient_snapshot_exit(void); 191 192 #endif /* _LINUX_DM_EXCEPTION_STORE */ 193