18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (C) 2001-2002 Sistina Software (UK) Limited. 38c2ecf20Sopenharmony_ci * Copyright (C) 2008 Red Hat, Inc. All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Device-mapper snapshot exception store. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This file is released under the GPL. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifndef _LINUX_DM_EXCEPTION_STORE 118c2ecf20Sopenharmony_ci#define _LINUX_DM_EXCEPTION_STORE 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 148c2ecf20Sopenharmony_ci#include <linux/list_bl.h> 158c2ecf20Sopenharmony_ci#include <linux/device-mapper.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* 188c2ecf20Sopenharmony_ci * The snapshot code deals with largish chunks of the disk at a 198c2ecf20Sopenharmony_ci * time. Typically 32k - 512k. 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_citypedef sector_t chunk_t; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* 248c2ecf20Sopenharmony_ci * An exception is used where an old chunk of data has been 258c2ecf20Sopenharmony_ci * replaced by a new one. 268c2ecf20Sopenharmony_ci * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number 278c2ecf20Sopenharmony_ci * of chunks that follow contiguously. Remaining bits hold the number of the 288c2ecf20Sopenharmony_ci * chunk within the device. 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_cistruct dm_exception { 318c2ecf20Sopenharmony_ci struct hlist_bl_node hash_list; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci chunk_t old_chunk; 348c2ecf20Sopenharmony_ci chunk_t new_chunk; 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci/* 388c2ecf20Sopenharmony_ci * Abstraction to handle the meta/layout of exception stores (the 398c2ecf20Sopenharmony_ci * COW device). 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_cistruct dm_exception_store; 428c2ecf20Sopenharmony_cistruct dm_exception_store_type { 438c2ecf20Sopenharmony_ci const char *name; 448c2ecf20Sopenharmony_ci struct module *module; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci int (*ctr) (struct dm_exception_store *store, char *options); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci /* 498c2ecf20Sopenharmony_ci * Destroys this object when you've finished with it. 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_ci void (*dtr) (struct dm_exception_store *store); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* 548c2ecf20Sopenharmony_ci * The target shouldn't read the COW device until this is 558c2ecf20Sopenharmony_ci * called. As exceptions are read from the COW, they are 568c2ecf20Sopenharmony_ci * reported back via the callback. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_ci int (*read_metadata) (struct dm_exception_store *store, 598c2ecf20Sopenharmony_ci int (*callback)(void *callback_context, 608c2ecf20Sopenharmony_ci chunk_t old, chunk_t new), 618c2ecf20Sopenharmony_ci void *callback_context); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci /* 648c2ecf20Sopenharmony_ci * Find somewhere to store the next exception. 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_ci int (*prepare_exception) (struct dm_exception_store *store, 678c2ecf20Sopenharmony_ci struct dm_exception *e); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci /* 708c2ecf20Sopenharmony_ci * Update the metadata with this exception. 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ci void (*commit_exception) (struct dm_exception_store *store, 738c2ecf20Sopenharmony_ci struct dm_exception *e, int valid, 748c2ecf20Sopenharmony_ci void (*callback) (void *, int success), 758c2ecf20Sopenharmony_ci void *callback_context); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* 788c2ecf20Sopenharmony_ci * Returns 0 if the exception store is empty. 798c2ecf20Sopenharmony_ci * 808c2ecf20Sopenharmony_ci * If there are exceptions still to be merged, sets 818c2ecf20Sopenharmony_ci * *last_old_chunk and *last_new_chunk to the most recent 828c2ecf20Sopenharmony_ci * still-to-be-merged chunk and returns the number of 838c2ecf20Sopenharmony_ci * consecutive previous ones. 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ci int (*prepare_merge) (struct dm_exception_store *store, 868c2ecf20Sopenharmony_ci chunk_t *last_old_chunk, chunk_t *last_new_chunk); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* 898c2ecf20Sopenharmony_ci * Clear the last n exceptions. 908c2ecf20Sopenharmony_ci * nr_merged must be <= the value returned by prepare_merge. 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_ci int (*commit_merge) (struct dm_exception_store *store, int nr_merged); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* 958c2ecf20Sopenharmony_ci * The snapshot is invalid, note this in the metadata. 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_ci void (*drop_snapshot) (struct dm_exception_store *store); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci unsigned (*status) (struct dm_exception_store *store, 1008c2ecf20Sopenharmony_ci status_type_t status, char *result, 1018c2ecf20Sopenharmony_ci unsigned maxlen); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci /* 1048c2ecf20Sopenharmony_ci * Return how full the snapshot is. 1058c2ecf20Sopenharmony_ci */ 1068c2ecf20Sopenharmony_ci void (*usage) (struct dm_exception_store *store, 1078c2ecf20Sopenharmony_ci sector_t *total_sectors, sector_t *sectors_allocated, 1088c2ecf20Sopenharmony_ci sector_t *metadata_sectors); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* For internal device-mapper use only. */ 1118c2ecf20Sopenharmony_ci struct list_head list; 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistruct dm_snapshot; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistruct dm_exception_store { 1178c2ecf20Sopenharmony_ci struct dm_exception_store_type *type; 1188c2ecf20Sopenharmony_ci struct dm_snapshot *snap; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* Size of data blocks saved - must be a power of 2 */ 1218c2ecf20Sopenharmony_ci unsigned chunk_size; 1228c2ecf20Sopenharmony_ci unsigned chunk_mask; 1238c2ecf20Sopenharmony_ci unsigned chunk_shift; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci void *context; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci bool userspace_supports_overflow; 1288c2ecf20Sopenharmony_ci}; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* 1318c2ecf20Sopenharmony_ci * Obtain the origin or cow device used by a given snapshot. 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_cistruct dm_dev *dm_snap_origin(struct dm_snapshot *snap); 1348c2ecf20Sopenharmony_cistruct dm_dev *dm_snap_cow(struct dm_snapshot *snap); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci/* 1378c2ecf20Sopenharmony_ci * Funtions to manipulate consecutive chunks 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci#define DM_CHUNK_CONSECUTIVE_BITS 8 1408c2ecf20Sopenharmony_ci#define DM_CHUNK_NUMBER_BITS 56 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic inline chunk_t dm_chunk_number(chunk_t chunk) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic inline unsigned dm_consecutive_chunk_count(struct dm_exception *e) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci return e->new_chunk >> DM_CHUNK_NUMBER_BITS; 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic inline void dm_consecutive_chunk_count_inc(struct dm_exception *e) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci BUG_ON(!dm_consecutive_chunk_count(e)); 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic inline void dm_consecutive_chunk_count_dec(struct dm_exception *e) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci BUG_ON(!dm_consecutive_chunk_count(e)); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci e->new_chunk -= (1ULL << DM_CHUNK_NUMBER_BITS); 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci/* 1678c2ecf20Sopenharmony_ci * Return the number of sectors in the device. 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_cistatic inline sector_t get_dev_size(struct block_device *bdev) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic inline chunk_t sector_to_chunk(struct dm_exception_store *store, 1758c2ecf20Sopenharmony_ci sector_t sector) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci return sector >> store->chunk_shift; 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ciint dm_exception_store_type_register(struct dm_exception_store_type *type); 1818c2ecf20Sopenharmony_ciint dm_exception_store_type_unregister(struct dm_exception_store_type *type); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ciint dm_exception_store_set_chunk_size(struct dm_exception_store *store, 1848c2ecf20Sopenharmony_ci unsigned chunk_size, 1858c2ecf20Sopenharmony_ci char **error); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ciint dm_exception_store_create(struct dm_target *ti, int argc, char **argv, 1888c2ecf20Sopenharmony_ci struct dm_snapshot *snap, 1898c2ecf20Sopenharmony_ci unsigned *args_used, 1908c2ecf20Sopenharmony_ci struct dm_exception_store **store); 1918c2ecf20Sopenharmony_civoid dm_exception_store_destroy(struct dm_exception_store *store); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ciint dm_exception_store_init(void); 1948c2ecf20Sopenharmony_civoid dm_exception_store_exit(void); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci/* 1978c2ecf20Sopenharmony_ci * Two exception store implementations. 1988c2ecf20Sopenharmony_ci */ 1998c2ecf20Sopenharmony_ciint dm_persistent_snapshot_init(void); 2008c2ecf20Sopenharmony_civoid dm_persistent_snapshot_exit(void); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ciint dm_transient_snapshot_init(void); 2038c2ecf20Sopenharmony_civoid dm_transient_snapshot_exit(void); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#endif /* _LINUX_DM_EXCEPTION_STORE */ 206