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