1aea53d92SJonathan Brassow /* 2aea53d92SJonathan Brassow * Copyright (C) 2001-2002 Sistina Software (UK) Limited. 3aea53d92SJonathan Brassow * Copyright (C) 2008 Red Hat, Inc. All rights reserved. 4aea53d92SJonathan Brassow * 5aea53d92SJonathan Brassow * Device-mapper snapshot exception store. 6aea53d92SJonathan Brassow * 7aea53d92SJonathan Brassow * This file is released under the GPL. 8aea53d92SJonathan Brassow */ 9aea53d92SJonathan Brassow 10aea53d92SJonathan Brassow #ifndef _LINUX_DM_EXCEPTION_STORE 11aea53d92SJonathan Brassow #define _LINUX_DM_EXCEPTION_STORE 12aea53d92SJonathan Brassow 13aea53d92SJonathan Brassow #include <linux/blkdev.h> 14a159c1acSJonathan Brassow #include <linux/device-mapper.h> 15aea53d92SJonathan Brassow 16aea53d92SJonathan Brassow /* 17aea53d92SJonathan Brassow * The snapshot code deals with largish chunks of the disk at a 18aea53d92SJonathan Brassow * time. Typically 32k - 512k. 19aea53d92SJonathan Brassow */ 20aea53d92SJonathan Brassow typedef sector_t chunk_t; 21aea53d92SJonathan Brassow 22aea53d92SJonathan Brassow /* 23aea53d92SJonathan Brassow * An exception is used where an old chunk of data has been 24aea53d92SJonathan Brassow * replaced by a new one. 25aea53d92SJonathan Brassow * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number 26aea53d92SJonathan Brassow * of chunks that follow contiguously. Remaining bits hold the number of the 27aea53d92SJonathan Brassow * chunk within the device. 28aea53d92SJonathan Brassow */ 29aea53d92SJonathan Brassow struct dm_snap_exception { 30aea53d92SJonathan Brassow struct list_head hash_list; 31aea53d92SJonathan Brassow 32aea53d92SJonathan Brassow chunk_t old_chunk; 33aea53d92SJonathan Brassow chunk_t new_chunk; 34aea53d92SJonathan Brassow }; 35aea53d92SJonathan Brassow 36aea53d92SJonathan Brassow /* 37aea53d92SJonathan Brassow * Abstraction to handle the meta/layout of exception stores (the 38aea53d92SJonathan Brassow * COW device). 39aea53d92SJonathan Brassow */ 40b2a11465SJonathan Brassow struct dm_exception_store; 41b2a11465SJonathan Brassow struct dm_exception_store_type { 42*493df71cSJonathan Brassow const char *name; 43*493df71cSJonathan Brassow struct module *module; 44*493df71cSJonathan Brassow 45b2a11465SJonathan Brassow int (*ctr) (struct dm_exception_store *store, 46b2a11465SJonathan Brassow unsigned argc, char **argv); 47b2a11465SJonathan Brassow 48aea53d92SJonathan Brassow /* 49aea53d92SJonathan Brassow * Destroys this object when you've finished with it. 50aea53d92SJonathan Brassow */ 51b2a11465SJonathan Brassow void (*dtr) (struct dm_exception_store *store); 52aea53d92SJonathan Brassow 53aea53d92SJonathan Brassow /* 54aea53d92SJonathan Brassow * The target shouldn't read the COW device until this is 55a159c1acSJonathan Brassow * called. As exceptions are read from the COW, they are 56a159c1acSJonathan Brassow * reported back via the callback. 57aea53d92SJonathan Brassow */ 58a159c1acSJonathan Brassow int (*read_metadata) (struct dm_exception_store *store, 59a159c1acSJonathan Brassow int (*callback)(void *callback_context, 60a159c1acSJonathan Brassow chunk_t old, chunk_t new), 61a159c1acSJonathan Brassow void *callback_context); 62aea53d92SJonathan Brassow 63aea53d92SJonathan Brassow /* 64aea53d92SJonathan Brassow * Find somewhere to store the next exception. 65aea53d92SJonathan Brassow */ 661ae25f9cSJonathan Brassow int (*prepare_exception) (struct dm_exception_store *store, 67aea53d92SJonathan Brassow struct dm_snap_exception *e); 68aea53d92SJonathan Brassow 69aea53d92SJonathan Brassow /* 70aea53d92SJonathan Brassow * Update the metadata with this exception. 71aea53d92SJonathan Brassow */ 721ae25f9cSJonathan Brassow void (*commit_exception) (struct dm_exception_store *store, 73aea53d92SJonathan Brassow struct dm_snap_exception *e, 74aea53d92SJonathan Brassow void (*callback) (void *, int success), 75aea53d92SJonathan Brassow void *callback_context); 76aea53d92SJonathan Brassow 77aea53d92SJonathan Brassow /* 78aea53d92SJonathan Brassow * The snapshot is invalid, note this in the metadata. 79aea53d92SJonathan Brassow */ 801ae25f9cSJonathan Brassow void (*drop_snapshot) (struct dm_exception_store *store); 81aea53d92SJonathan Brassow 82a159c1acSJonathan Brassow int (*status) (struct dm_exception_store *store, status_type_t status, 83a159c1acSJonathan Brassow char *result, unsigned int maxlen); 84a159c1acSJonathan Brassow 85aea53d92SJonathan Brassow /* 86aea53d92SJonathan Brassow * Return how full the snapshot is. 87aea53d92SJonathan Brassow */ 881ae25f9cSJonathan Brassow void (*fraction_full) (struct dm_exception_store *store, 89aea53d92SJonathan Brassow sector_t *numerator, 90aea53d92SJonathan Brassow sector_t *denominator); 91*493df71cSJonathan Brassow 92*493df71cSJonathan Brassow /* For internal device-mapper use only. */ 93*493df71cSJonathan Brassow struct list_head list; 94b2a11465SJonathan Brassow }; 95b2a11465SJonathan Brassow 96b2a11465SJonathan Brassow struct dm_exception_store { 97*493df71cSJonathan Brassow struct dm_exception_store_type *type; 98aea53d92SJonathan Brassow 99aea53d92SJonathan Brassow struct dm_snapshot *snap; 100b2a11465SJonathan Brassow 101aea53d92SJonathan Brassow void *context; 102aea53d92SJonathan Brassow }; 103aea53d92SJonathan Brassow 104aea53d92SJonathan Brassow /* 105aea53d92SJonathan Brassow * Funtions to manipulate consecutive chunks 106aea53d92SJonathan Brassow */ 107aea53d92SJonathan Brassow # if defined(CONFIG_LBD) || (BITS_PER_LONG == 64) 108aea53d92SJonathan Brassow # define DM_CHUNK_CONSECUTIVE_BITS 8 109aea53d92SJonathan Brassow # define DM_CHUNK_NUMBER_BITS 56 110aea53d92SJonathan Brassow 111aea53d92SJonathan Brassow static inline chunk_t dm_chunk_number(chunk_t chunk) 112aea53d92SJonathan Brassow { 113aea53d92SJonathan Brassow return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL); 114aea53d92SJonathan Brassow } 115aea53d92SJonathan Brassow 116aea53d92SJonathan Brassow static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e) 117aea53d92SJonathan Brassow { 118aea53d92SJonathan Brassow return e->new_chunk >> DM_CHUNK_NUMBER_BITS; 119aea53d92SJonathan Brassow } 120aea53d92SJonathan Brassow 121aea53d92SJonathan Brassow static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e) 122aea53d92SJonathan Brassow { 123aea53d92SJonathan Brassow e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS); 124aea53d92SJonathan Brassow 125aea53d92SJonathan Brassow BUG_ON(!dm_consecutive_chunk_count(e)); 126aea53d92SJonathan Brassow } 127aea53d92SJonathan Brassow 128aea53d92SJonathan Brassow # else 129aea53d92SJonathan Brassow # define DM_CHUNK_CONSECUTIVE_BITS 0 130aea53d92SJonathan Brassow 131aea53d92SJonathan Brassow static inline chunk_t dm_chunk_number(chunk_t chunk) 132aea53d92SJonathan Brassow { 133aea53d92SJonathan Brassow return chunk; 134aea53d92SJonathan Brassow } 135aea53d92SJonathan Brassow 136aea53d92SJonathan Brassow static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e) 137aea53d92SJonathan Brassow { 138aea53d92SJonathan Brassow return 0; 139aea53d92SJonathan Brassow } 140aea53d92SJonathan Brassow 141aea53d92SJonathan Brassow static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e) 142aea53d92SJonathan Brassow { 143aea53d92SJonathan Brassow } 144aea53d92SJonathan Brassow 145aea53d92SJonathan Brassow # endif 146aea53d92SJonathan Brassow 147*493df71cSJonathan Brassow int dm_exception_store_type_register(struct dm_exception_store_type *type); 148*493df71cSJonathan Brassow int dm_exception_store_type_unregister(struct dm_exception_store_type *type); 149*493df71cSJonathan Brassow 150*493df71cSJonathan Brassow int dm_exception_store_create(const char *type_name, 151*493df71cSJonathan Brassow struct dm_exception_store **store); 152*493df71cSJonathan Brassow void dm_exception_store_destroy(struct dm_exception_store *store); 153*493df71cSJonathan Brassow 1544db6bfe0SAlasdair G Kergon int dm_exception_store_init(void); 1554db6bfe0SAlasdair G Kergon void dm_exception_store_exit(void); 1564db6bfe0SAlasdair G Kergon 157aea53d92SJonathan Brassow /* 158aea53d92SJonathan Brassow * Two exception store implementations. 159aea53d92SJonathan Brassow */ 1604db6bfe0SAlasdair G Kergon int dm_persistent_snapshot_init(void); 1614db6bfe0SAlasdair G Kergon void dm_persistent_snapshot_exit(void); 1624db6bfe0SAlasdair G Kergon 1634db6bfe0SAlasdair G Kergon int dm_transient_snapshot_init(void); 1644db6bfe0SAlasdair G Kergon void dm_transient_snapshot_exit(void); 1654db6bfe0SAlasdair G Kergon 166aea53d92SJonathan Brassow #endif /* _LINUX_DM_EXCEPTION_STORE */ 167