[dm-devel] [PATCH 03/14] dm-multisnap-mikulas-headers
Mike Snitzer
snitzer at redhat.com
Tue Mar 2 00:23:47 UTC 2010
From: Mikulas Patocka <mpatocka at redhat.com>
Common header files for the exception store.
dm-multisnap-mikulas-struct.h contains on-disk structure definitions.
dm-multisnap-mikulas.h contains in-memory structures and kernel function
prototypes.
Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>
---
drivers/md/dm-multisnap-mikulas-struct.h | 380 ++++++++++++++++++++++++++++++
drivers/md/dm-multisnap-mikulas.h | 247 +++++++++++++++++++
2 files changed, 627 insertions(+), 0 deletions(-)
create mode 100644 drivers/md/dm-multisnap-mikulas-struct.h
create mode 100644 drivers/md/dm-multisnap-mikulas.h
diff --git a/drivers/md/dm-multisnap-mikulas-struct.h b/drivers/md/dm-multisnap-mikulas-struct.h
new file mode 100644
index 0000000..39eaa16
--- /dev/null
+++ b/drivers/md/dm-multisnap-mikulas-struct.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2009 Red Hat Czech, s.r.o.
+ *
+ * Mikulas Patocka <mpatocka at redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_MULTISNAP_MIKULAS_STRUCT_H
+#define DM_MULTISNAP_MIKULAS_STRUCT_H
+
+/* on-disk structures */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#include "dm-multisnap.h"
+
+/*
+ * Encoding of snapshot numbers:
+ *
+ * If CONFIG_DM_MULTISNAPSHOT_MIKULAS_SNAP_OF_SNAP is not selected (normally it
+ * is), then mikulas_snapid_t is 32-bit sequential number. It continually grows.
+ *
+ * IF CONFIG_DM_MULTISNAPSHOT_MIKULAS_SNAP_OF_SNAP is selected (by default),
+ * then mikulas_snapid_t is 64-bit number. The high 32 bits are sequential
+ * snapshot number. With each new snapshot, it is incremented. The low 32 bits
+ * are subsnapshot number. Single snapshots (snapshots of the origin) have
+ * low 32 bits equal to all ones. Snapshots-of-snapshots have high 32 bits
+ * equal as their master snapshot and low 32 bits start with zero and is
+ * incremented with each new snapshot-of-snapshot.
+ *
+ * More levels (snapshots-of-snapshots-of-snapshots) are not allowed.
+ */
+
+/*
+ * Description of on-disk format:
+ *
+ * The device is composed of blocks (also called chunks). The block size (also
+ * called chunk size) is specified in the superblock.
+ *
+ * The chunk and block mean the same. "chunk" comes from old snapshots.
+ * "block" comes from filesystems. We tend to use "chunk" in
+ * exception-store-independent code to make it consistent with snapshot
+ * terminology and "block" in exception-store code to make it consistent with
+ * filesystem terminology.
+ *
+ * The minimum block size is 512, the maximum block size is not specified (it is
+ * limited by 32-bit integer size and available memory). All on-disk pointers
+ * are in the units of blocks. The pointers are 48-bit, making this format
+ * capable of handling 2^48 blocks.
+ *
+ * Log-structured update is used, new data are only written to unallocated parts
+ * of the device. By writing a new commit block, these unallocated parts become
+ * allocated and the store makes a transition to the new state. This maintains
+ * data consistency across crashes.
+ *
+ * Super block
+ *
+ * Chunk 0 is the superblock. It is defined in 'struct multisnap_superblock'.
+ * The superblock contains chunk size, commit block stride, error (if non-zero,
+ * then the exception store is invalid) and pointer to the current commit block.
+ *
+ * Commit blocks
+ *
+ * Chunks 1, 1+cb_stride, 1+2*cb_stride, 1+3*cb_stride, etc. are commit blocks.
+ * Chunks at these locations ((location % cb_stride) == 1) are only used for
+ * commit blocks, they can't be used for anything else. A commit block is
+ * written each time a new state is committed. The snapshot store transitions
+ * from one consistent state to another consistent state by writing a commit
+ * block.
+ *
+ * All commit blocks must be present and initialized (i.e. have valid signature
+ * and sequence number). They are created when the device is initialized or
+ * extended. It is not allowed to have random uninitialized data in any commit
+ * block.
+ *
+ * For correctness, one commit block would be sufficient --- but to improve
+ * performance and minimize seek times, there are multiple commit blocks and
+ * we use the commit block that is near currently written data.
+ *
+ * The current commit block is stored in the super block. However, updates to
+ * the super block would make excessive disk seeks too, so the updates to super
+ * block are skipped if the commit block is written at the currently valid
+ * commit block or at the next location following the currently valid commit
+ * block. The following algorithm is used to find the commit block at mount:
+ * 1. read the commit block multisnap_superblock->commit_block
+ * 2. get its sequence number
+ * 3. read the next commit block
+ * 4. if the sequence number of the next commit block is higher than
+ * the sequence number of the previous block, go to step 3. (i.e. read
+ * another commit block)
+ * 5. if the sequence number of the next commit block is lower than
+ * the sequence number of the previous block, use the previous block
+ * as the most recent valid commit block
+ *
+ * Note: because the disks only support atomic writes of 512 bytes, the commit
+ * block has only 512 bytes of valid data. The remaining data in the commit
+ * block up to the chunk size is unused.
+ *
+ * B+tree
+ *
+ * To hold the information about reallocated chunks, we use b+tree. The b+tree
+ * leaf entry contains: old chunk (in the origin), new chunk (in the snapshot
+ * store), the range of snapshot IDs for which this mapping applies. The b+tree
+ * is keyed by (old chunk, snapshot ID range). The b+tree node is specified
+ * in 'struct dm_multisnap_bt_node', the b+tree entry is in 'struct
+ * dm_multisnap_bt_entry'. The maximum number of entries in one node is specified
+ * so that the node fits into one chunk.
+ *
+ * The internal nodes have the same structure as the leaf nodes, except that:
+ * Both snapshot ID range entries (snap_from and snap_to) must be equal.
+ * New_chunk is really pointer to the subordinate b+tree node.
+ *
+ * The pointer to the root node and the depth of the b+tree is stored in the
+ * commit block.
+ *
+ * Snapshot IDs
+ *
+ * We use 64-bit snapshot IDs. The high 32 bits is the number of a snapshot.
+ * This number always increases by one when creating a new snapshot. The
+ * snapshot IDs are never reused. It is expected that the admin won't create
+ * 2^32 snapshots.
+ *
+ * The low 32 bits is the subsnapshot ID and it allows to create snapshots of
+ * snapshots. The store allow holding snapshots of 2 levels --- i.e. master
+ * snapshots (they have all low 32 bits set to 1) and snapshots-of-snapshots
+ * (they have low 32 bits incrementing from 0 to 2^32-1).
+ *
+ * The valid snapshots IDs are stored in the b+tree. Special entries with chunk
+ * number DM_CHUNK_T_SNAP_PRESENT denote the present snapshot IDs. These entries
+ * point to no chunk, instead their presence shows the presence of the specified
+ * snapshot ID.
+ *
+ * When the snapshot is deleted, its entry is removed from the b+tree and the
+ * whole b+tree is scanned on background --- entries whose range doesn't cover
+ * any present snapshot are deleted.
+ *
+ * Bitmaps
+ *
+ * Free space is managed by bitmaps. Bitmaps are pointed to by a radix-tree.
+ * Each internal node contains 64-bit pointers to subordinate nodes, each leaf
+ * node contains individual bits, '1' meaning allocated and '0' meaning free.
+ * There are no structs defined for the radix tree because the internal node is
+ * just an array of "u64" and the leaf node is just a bit mask.
+ *
+ * The depth of the radix tree is dependent on the device size and chunk size.
+ * The smallest depth that covers the whole device is used. The depth is not
+ * stored on the device, it is calculated with
+ * dm_multisnap_bitmap_depth function.
+ *
+ * The bitmap root is stored in the commit block.
+ * If the depth is 0, this root bitmap contains just individual bits (the device
+ * is so small that its bitmap fits within one chunk), if the depth is 1, the
+ * bitmap root points to a block with 64-bit pointers to individual bitmaps.
+ * If the depth is 2, there are two levels of pointers ... etc.
+ *
+ * Remaps
+ *
+ * If we wanted to follow the log-structure principle (writing only to
+ * unallocated parts), we would have to always write a new pathway up to the
+ * b+tree root or bitmap root.
+ *
+ * To avoid these multiple writes, remaps are used. There are limited number
+ * of remap entries in the commit block: 27 entries of commit_block_tmp_remap.
+ * Each entry contains (old, new) pair of chunk numbers.
+ *
+ * When we need to update a b+tree block or a bitmap block, we write the new
+ * block to a new location and store the old block and the new block in the
+ * commit block remap. When reading a block, we check if the number is present
+ * in the remap array --- if it is, we read the new location from the remap
+ * instead.
+ *
+ * This way, if we need to update one bitmap or one b+tree block, we don't have
+ * to write the whole path down from the root. Eventually, the remap entries in
+ * the commit block will be exhausted and if this happens, we must free the
+ * remap entries by writing the path from the root.
+ *
+ * The bitmap_idx field in the remap is the index of the bitmap that the
+ * remapped chunk represents or CB_BITMAP_IDX_NONE if it represents a b+tree
+ * node. It is used to construct the path to the root. Bitmaps don't contain
+ * any other data except the bits, so the path must be constructed using this
+ * index. b+tree nodes contain the entries, so the path can be constructed by
+ * looking at the b+tree entries.
+ *
+ * Example: let's have a b+tree with depth 4 and pointers 10 -> 20 -> 30 -> 40.
+ * Now, if we want to change node 40: so write a new version to a chunk 41 and
+ * store the pair (40, 41) into the commit block.
+ * Now, we want to change this node again: so write a new version to a chunk 42
+ * and store the pair (40, 42) into the commit block.
+ * Now, let's do the same operation for other node --- the remap array in the
+ * commit block eventually fills up. When this happens, we expunge (40, 42) map
+ * by writing the path from the root:
+ * copy node 30 to 43, change the pointer from 40 to 42
+ * copy node 20 to 44, change the pointer from 30 to 43
+ * copy node 10 to 45, change the pointer from 20 to 44
+ * change the root pointer from 10 to 45.
+ * Now, the remap entry (40, 42) can be removed from the remap array.
+ *
+ * Freelist
+ *
+ * Freeing blocks is a bit tricky. If we freed blocks using the log-structured
+ * method, freeing would allocate and free more bitmap blocks, and the whole
+ * thing would get into an infinite loop. So, to free blocks, a different method
+ * is used: freelists.
+ *
+ * We have a 'struct dm_multisnap_freelist' that contains an array of runs of
+ * blocks to free. Each run is the pair (start, length). When we need to free
+ * a block, we add the block to the freelist. We optionally allocate a free
+ * list, if there is no freelist, or if the current freelist is full. If one
+ * freelist is not sufficient, a linked list of freelists is being created.
+ * In the commit we write the freelist location to the commit block and after
+ * the commit, we free individual bits in the bitmaps. If the computer crashes
+ * during freeing the bits we just free the bits again on next mount.
+ */
+
+#ifndef CONFIG_DM_MULTISNAPSHOT_MIKULAS_SNAP_OF_SNAP
+typedef __u32 mikulas_snapid_t;
+#define DM_MIKULAS_SNAPID_STEP_BITS 0
+#define mikulas_snapid_to_cpu le32_to_cpu
+#define cpu_to_mikulas_snapid cpu_to_le32
+#else
+typedef __u64 mikulas_snapid_t;
+#define DM_MIKULAS_SNAPID_STEP_BITS 32
+#define mikulas_snapid_to_cpu le64_to_cpu
+#define cpu_to_mikulas_snapid cpu_to_le64
+#endif
+
+#define DM_MIKULAS_SUBSNAPID_MASK (((mikulas_snapid_t)1 << DM_MIKULAS_SNAPID_STEP_BITS) - 1)
+#define DM_SNAPID_T_LAST ((mikulas_snapid_t)0xffffffffffffffffULL)
+#define DM_SNAPID_T_MAX ((mikulas_snapid_t)0xfffffffffffffffeULL)
+
+#define DM_CHUNK_BITS 48
+#define DM_CHUNK_T_LAST ((chunk_t)(1LL << DM_CHUNK_BITS) - 1)
+#define DM_CHUNK_T_SNAP_PRESENT ((chunk_t)(1LL << DM_CHUNK_BITS) - 1)
+#define DM_CHUNK_T_MAX ((chunk_t)(1LL << DM_CHUNK_BITS) - 2)
+
+#define CB_STRIDE_DEFAULT 1024
+
+#define SB_BLOCK 0
+
+#define SB_SIGNATURE cpu_to_be32(0xF6015342)
+
+struct multisnap_superblock {
+ __u32 signature;
+ __u32 chunk_size;
+ __u32 cb_stride;
+ __s32 error;
+ __u64 commit_block;
+};
+
+
+#define FIRST_CB_BLOCK 1
+
+#define CB_SIGNATURE cpu_to_be32(0xF6014342)
+
+struct commit_block_tmp_remap {
+ __u32 old1;
+ __u16 old2;
+ __u16 new2;
+ __u32 new1;
+ __u32 bitmap_idx; /* CB_BITMAP_IDX_* */
+};
+
+#define CB_BITMAP_IDX_MAX 0xfffffffd
+#define CB_BITMAP_IDX_NONE 0xfffffffe
+
+#define N_REMAPS 27
+
+struct multisnap_commit_block {
+ __u32 signature;
+ __u32 snapshot_num; /* new snapshot number to allocate */
+ __u64 sequence; /* a sequence, increased with each commit */
+
+ __u32 dev_size1; /* total size of the device in chunks */
+ __u16 dev_size2;
+ __u16 total_allocated2; /* total allocated chunks */
+ __u32 total_allocated1;
+ __u32 data_allocated1; /* chunks allocated for data */
+
+ __u16 data_allocated2;
+ __u16 bitmap_root2; /* bitmap root */
+ __u32 bitmap_root1;
+ __u32 alloc_rover1; /* the next place where to try allocation */
+ __u16 alloc_rover2;
+ __u16 freelist2; /* pointer to dm_multisnap_freelist */
+
+ __u32 freelist1;
+ __u32 delete_rover1; /* an index in the btree where to continue */
+ __u16 delete_rover2; /* searching for data to delete */
+ __u16 bt_root2; /* btree root chunk */
+ __u32 bt_root1;
+
+ __u8 bt_depth; /* depth of the btree */
+ __u8 flags; /* DM_MULTISNAP_FLAG_* */
+ __u8 pad[14];
+
+ struct commit_block_tmp_remap tmp_remap[N_REMAPS];
+};
+
+#define DM_MULTISNAP_FLAG_DELETING 0x01
+#define DM_MULTISNAP_FLAG_PENDING_DELETE 0x02
+
+#define MAX_BITMAP_DEPTH 6
+
+static inline int dm_multisnap_bitmap_depth(unsigned chunk_shift, __u64 device_size)
+{
+ unsigned depth = 0;
+ __u64 entries = 8 << chunk_shift;
+ while (entries < device_size) {
+ depth++;
+ entries <<= chunk_shift - 3;
+ if (!entries)
+ return -ERANGE;
+ }
+
+ if (depth > MAX_BITMAP_DEPTH)
+ return -ERANGE;
+
+ return depth;
+}
+
+
+/* B+-tree entry. Sorted by orig_chunk and snap_from/to */
+
+#define MAX_BT_DEPTH 12
+
+struct dm_multisnap_bt_entry {
+ __u32 orig_chunk1;
+ __u16 orig_chunk2;
+ __u16 new_chunk2;
+ __u32 new_chunk1;
+ __u32 flags;
+ mikulas_snapid_t snap_from;
+ mikulas_snapid_t snap_to;
+};
+
+#define BT_SIGNATURE cpu_to_be32(0xF6014254)
+
+struct dm_multisnap_bt_node {
+ __u32 signature;
+ __u32 n_entries;
+ struct dm_multisnap_bt_entry entries[0];
+};
+
+static inline unsigned dm_multisnap_btree_entries(unsigned chunk_size)
+{
+ return (chunk_size - sizeof(struct dm_multisnap_bt_node)) /
+ sizeof(struct dm_multisnap_bt_entry);
+}
+
+
+/* Freelist */
+
+struct dm_multisnap_freelist_entry {
+ __u32 block1;
+ __u16 block2;
+ __u16 run_length; /* FREELIST_* */
+};
+
+#define FREELIST_RL_MASK 0x7fff /* Run length */
+#define FREELIST_DATA_FLAG 0x8000 /* Represents a data block */
+
+#define FL_SIGNATURE cpu_to_be32(0xF601464C)
+
+struct dm_multisnap_freelist {
+ __u32 signature;
+ __u32 backlink1;
+ __u16 backlink2;
+ __u32 n_entries;
+ struct dm_multisnap_freelist_entry entries[0];
+};
+
+static inline unsigned dm_multisnap_freelist_entries(unsigned chunk_size)
+{
+ return (chunk_size - sizeof(struct dm_multisnap_freelist)) /
+ sizeof(struct dm_multisnap_freelist);
+}
+
+#endif
diff --git a/drivers/md/dm-multisnap-mikulas.h b/drivers/md/dm-multisnap-mikulas.h
new file mode 100644
index 0000000..52c87e0
--- /dev/null
+++ b/drivers/md/dm-multisnap-mikulas.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2009 Red Hat Czech, s.r.o.
+ *
+ * Mikulas Patocka <mpatocka at redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_MULTISNAP_MIKULAS_H
+#define DM_MULTISNAP_MIKULAS_H
+
+/*
+ * This can be optionally undefined to get 32-bit snapshot numbers.
+ * Breaks on-disk format compatibility.
+ */
+#define CONFIG_DM_MULTISNAPSHOT_MIKULAS_SNAP_OF_SNAP
+
+#include "dm-multisnap.h"
+#include "dm-multisnap-mikulas-struct.h"
+
+#include "dm-bufio.h"
+
+#include <linux/vmalloc.h>
+
+typedef __u32 bitmap_t;
+
+#define read_48(struc, entry) (le32_to_cpu((struc)->entry##1) |\
+ ((chunk_t)le16_to_cpu((struc)->entry##2) << 31 << 1))
+
+#define write_48(struc, entry, val) do { (struc)->entry##1 = cpu_to_le32(val); \
+ (struc)->entry##2 = cpu_to_le16((chunk_t)(val) >> 31 >> 1); } while (0)
+
+#define TMP_REMAP_HASH_SIZE 256
+#define TMP_REMAP_HASH(c) ((c) & (TMP_REMAP_HASH_SIZE - 1))
+
+#define UNCOMMITTED_BLOCK_HASH_SIZE 256
+#define UNCOMMITTED_BLOCK_HASH(c) ((c) & (UNCOMMITTED_BLOCK_HASH_SIZE - 1))
+
+struct tmp_remap {
+ /* List entry for tmp_remap */
+ struct hlist_node hash_list;
+ /* List entry for used_tmp_remaps/free_tmp_remaps */
+ struct list_head list;
+ chunk_t old;
+ chunk_t new;
+ bitmap_t bitmap_idx;
+ int uncommitted;
+};
+
+struct bt_key {
+ chunk_t chunk;
+ mikulas_snapid_t snap_from;
+ mikulas_snapid_t snap_to;
+};
+
+struct path_element {
+ chunk_t block;
+ unsigned idx;
+ unsigned n_entries;
+};
+
+struct dm_exception_store {
+ struct dm_multisnap *dm;
+ struct dm_bufio_client *bufio;
+
+ chunk_t dev_size;
+ unsigned chunk_size;
+ unsigned char chunk_shift;
+ unsigned char bitmap_depth;
+ unsigned btree_entries;
+ __u8 bt_depth;
+ __u8 flags;
+ __u32 snapshot_num;
+ unsigned cb_stride;
+
+ chunk_t bitmap_root;
+ chunk_t alloc_rover;
+ chunk_t bt_root;
+ chunk_t sb_commit_block;
+ chunk_t valid_commit_block;
+ chunk_t delete_rover_chunk;
+ mikulas_snapid_t delete_rover_snapid;
+
+ chunk_t total_allocated;
+ chunk_t data_allocated;
+
+ __u64 commit_sequence;
+
+ void *tmp_chunk;
+
+ struct rb_root active_snapshots;
+
+ /* Used during query/add remap */
+ chunk_t query_snapid;
+ struct bt_key query_new_key;
+ unsigned char query_active;
+ chunk_t query_block_from;
+ chunk_t query_block_to;
+
+ /* List heads for struct tmp_remap->list */
+ unsigned n_used_tmp_remaps;
+ struct list_head used_bitmap_tmp_remaps;
+ struct list_head used_bt_tmp_remaps;
+ struct list_head free_tmp_remaps;
+ /* List head for struct tmp_remap->hash_list */
+ struct hlist_head tmp_remap[TMP_REMAP_HASH_SIZE];
+ struct tmp_remap tmp_remap_store[N_REMAPS];
+
+ unsigned n_preallocated_blocks;
+ chunk_t preallocated_blocks[MAX_BITMAP_DEPTH * 2];
+
+ struct dm_multisnap_freelist *freelist;
+ chunk_t freelist_ptr;
+
+ struct dm_multisnap_background_work delete_work;
+ unsigned delete_commit_count;
+
+ __u64 cache_threshold;
+ __u64 cache_limit;
+
+ struct hlist_head uncommitted_blocks[UNCOMMITTED_BLOCK_HASH_SIZE];
+};
+
+/* dm-multisnap-alloc.c */
+
+void dm_multisnap_create_bitmaps(struct dm_exception_store *s, chunk_t *writing_block);
+void dm_multisnap_extend_bitmaps(struct dm_exception_store *s, chunk_t new_size);
+void *dm_multisnap_map_bitmap(struct dm_exception_store *s, bitmap_t bitmap,
+ struct dm_buffer **bp, chunk_t *block,
+ struct path_element *path);
+int dm_multisnap_alloc_blocks(struct dm_exception_store *s, chunk_t *results,
+ unsigned n_blocks, int flags);
+#define ALLOC_DRY 1
+void *dm_multisnap_alloc_duplicate_block(struct dm_exception_store *s, chunk_t block,
+ struct dm_buffer **bp, void *ptr);
+void *dm_multisnap_alloc_make_block(struct dm_exception_store *s, chunk_t *result,
+ struct dm_buffer **bp);
+void dm_multisnap_free_blocks_immediate(struct dm_exception_store *s, chunk_t block,
+ unsigned n_blocks);
+void dm_multisnap_bitmap_finalize_tmp_remap(struct dm_exception_store *s,
+ struct tmp_remap *tmp_remap);
+
+/* dm-multisnap-blocks.c */
+
+chunk_t dm_multisnap_remap_block(struct dm_exception_store *s, chunk_t block);
+void *dm_multisnap_read_block(struct dm_exception_store *s, chunk_t block,
+ struct dm_buffer **bp);
+int dm_multisnap_block_is_uncommitted(struct dm_exception_store *s, chunk_t block);
+void dm_multisnap_block_set_uncommitted(struct dm_exception_store *s, chunk_t block);
+void dm_multisnap_clear_uncommitted(struct dm_exception_store *s);
+void *dm_multisnap_duplicate_block(struct dm_exception_store *s, chunk_t old_chunk,
+ chunk_t new_chunk, bitmap_t bitmap_idx,
+ struct dm_buffer **bp, chunk_t *to_free);
+void dm_multisnap_free_tmp_remap(struct dm_exception_store *s, struct tmp_remap *t);
+void *dm_multisnap_make_block(struct dm_exception_store *s, chunk_t new_chunk,
+ struct dm_buffer **bp);
+void dm_multisnap_free_block_and_duplicates(struct dm_exception_store *s,
+ chunk_t block);
+
+int dm_multisnap_is_commit_block(struct dm_exception_store *s, chunk_t block);
+
+struct stop_cycles {
+ chunk_t key;
+ __u64 count;
+};
+
+void dm_multisnap_init_stop_cycles(struct stop_cycles *cy);
+int dm_multisnap_stop_cycles(struct dm_exception_store *s,
+ struct stop_cycles *cy, chunk_t key);
+
+/* dm-multisnap-btree.c */
+
+void dm_multisnap_create_btree(struct dm_exception_store *s, chunk_t *writing_block);
+int dm_multisnap_find_in_btree(struct dm_exception_store *s, struct bt_key *key,
+ chunk_t *result);
+void dm_multisnap_add_to_btree(struct dm_exception_store *s, struct bt_key *key,
+ chunk_t new_chunk);
+void dm_multisnap_restrict_btree_entry(struct dm_exception_store *s, struct bt_key *key);
+void dm_multisnap_extend_btree_entry(struct dm_exception_store *s, struct bt_key *key);
+void dm_multisnap_delete_from_btree(struct dm_exception_store *s, struct bt_key *key);
+void dm_multisnap_bt_finalize_tmp_remap(struct dm_exception_store *s,
+ struct tmp_remap *tmp_remap);
+int dm_multisnap_list_btree(struct dm_exception_store *s, struct bt_key *key,
+ int (*call)(struct dm_exception_store *,
+ struct dm_multisnap_bt_node *,
+ struct dm_multisnap_bt_entry *, void *),
+ void *cookie);
+
+/* dm-multisnap-commit.c */
+
+void dm_multisnap_transition_mark(struct dm_exception_store *s);
+void dm_multisnap_prepare_for_commit(struct dm_exception_store *s);
+void dm_multisnap_commit(struct dm_exception_store *s);
+
+/* dm-multisnap-delete.c */
+
+void dm_multisnap_background_delete(struct dm_exception_store *s,
+ struct dm_multisnap_background_work *bw);
+
+/* dm-multisnap-freelist.c */
+
+void dm_multisnap_init_freelist(struct dm_multisnap_freelist *fl, unsigned chunk_size);
+void dm_multisnap_free_block(struct dm_exception_store *s, chunk_t block, unsigned flags);
+int dm_multisnap_check_allocated_block(struct dm_exception_store *s, chunk_t block);
+void dm_multisnap_flush_freelist_before_commit(struct dm_exception_store *s);
+void dm_multisnap_load_freelist(struct dm_exception_store *s);
+
+/* dm-multisnap-io.c */
+
+int dm_multisnap_find_snapshot_chunk(struct dm_exception_store *s, snapid_t snapid,
+ chunk_t chunk, int write, chunk_t *result);
+void dm_multisnap_reset_query(struct dm_exception_store *s);
+int dm_multisnap_query_next_remap(struct dm_exception_store *s, chunk_t chunk);
+void dm_multisnap_add_next_remap(struct dm_exception_store *s,
+ union chunk_descriptor *cd, chunk_t *new_chunk);
+void dm_multisnap_make_chunk_writeable(struct dm_exception_store *s,
+ union chunk_descriptor *cd, chunk_t *new_chunk);
+int dm_multisnap_check_conflict(struct dm_exception_store *s, union chunk_descriptor *cd,
+ snapid_t snapid);
+
+/* dm-multisnap-snaps.c */
+
+snapid_t dm_multisnap_get_next_snapid(struct dm_exception_store *s, snapid_t snapid);
+int dm_multisnap_compare_snapids_for_create(const void *p1, const void *p2);
+int dm_multisnap_find_next_snapid_range(struct dm_exception_store *s, snapid_t snapid,
+ snapid_t *from, snapid_t *to);
+snapid_t dm_multisnap_find_next_subsnapshot(struct dm_exception_store *s, snapid_t snapid);
+
+void dm_multisnap_destroy_snapshot_tree(struct dm_exception_store *s);
+void dm_multisnap_read_snapshots(struct dm_exception_store *s);
+int dm_multisnap_allocate_snapid(struct dm_exception_store *s, snapid_t *snapid,
+ int snap_of_snap, snapid_t master);
+int dm_multisnap_create_snapshot(struct dm_exception_store *s, snapid_t snapid);
+int dm_multisnap_delete_snapshot(struct dm_exception_store *s, snapid_t snapid);
+
+void dm_multisnap_get_space(struct dm_exception_store *s, unsigned long long *chunks_total,
+ unsigned long long *chunks_allocated,
+ unsigned long long *chunks_metadata_allocated);
+
+#ifdef CONFIG_DM_MULTISNAPSHOT_MIKULAS_SNAP_OF_SNAP
+void dm_multisnap_print_snapid(struct dm_exception_store *s, char *string,
+ unsigned maxlen, snapid_t snapid);
+int dm_multisnap_read_snapid(struct dm_exception_store *s, char *string,
+ snapid_t *snapid, char **error);
+#endif
+
+#endif
--
1.6.5.2
More information about the dm-devel
mailing list