1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (C) 2001-2002 Sistina Software (UK) Limited. |
4 | * Copyright (C) 2008 Red Hat, Inc. All rights reserved. |
5 | * |
6 | * Device-mapper snapshot exception store. |
7 | * |
8 | * This file is released under the GPL. |
9 | */ |
10 | |
11 | #ifndef _LINUX_DM_EXCEPTION_STORE |
12 | #define _LINUX_DM_EXCEPTION_STORE |
13 | |
14 | #include <linux/blkdev.h> |
15 | #include <linux/list_bl.h> |
16 | #include <linux/device-mapper.h> |
17 | |
18 | /* |
19 | * The snapshot code deals with largish chunks of the disk at a |
20 | * time. Typically 32k - 512k. |
21 | */ |
22 | typedef sector_t chunk_t; |
23 | |
24 | /* |
25 | * An exception is used where an old chunk of data has been |
26 | * replaced by a new one. |
27 | * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number |
28 | * of chunks that follow contiguously. Remaining bits hold the number of the |
29 | * chunk within the device. |
30 | */ |
31 | struct dm_exception { |
32 | struct hlist_bl_node hash_list; |
33 | |
34 | chunk_t old_chunk; |
35 | chunk_t new_chunk; |
36 | }; |
37 | |
38 | /* |
39 | * Abstraction to handle the meta/layout of exception stores (the |
40 | * COW device). |
41 | */ |
42 | struct dm_exception_store; |
43 | struct dm_exception_store_type { |
44 | const char *name; |
45 | struct module *module; |
46 | |
47 | int (*ctr)(struct dm_exception_store *store, char *options); |
48 | |
49 | /* |
50 | * Destroys this object when you've finished with it. |
51 | */ |
52 | void (*dtr)(struct dm_exception_store *store); |
53 | |
54 | /* |
55 | * The target shouldn't read the COW device until this is |
56 | * called. As exceptions are read from the COW, they are |
57 | * reported back via the callback. |
58 | */ |
59 | int (*read_metadata)(struct dm_exception_store *store, |
60 | int (*callback)(void *callback_context, |
61 | chunk_t old, chunk_t new), |
62 | void *callback_context); |
63 | |
64 | /* |
65 | * Find somewhere to store the next exception. |
66 | */ |
67 | int (*prepare_exception)(struct dm_exception_store *store, |
68 | struct dm_exception *e); |
69 | |
70 | /* |
71 | * Update the metadata with this exception. |
72 | */ |
73 | void (*commit_exception)(struct dm_exception_store *store, |
74 | struct dm_exception *e, int valid, |
75 | void (*callback)(void *, int success), |
76 | void *callback_context); |
77 | |
78 | /* |
79 | * Returns 0 if the exception store is empty. |
80 | * |
81 | * If there are exceptions still to be merged, sets |
82 | * *last_old_chunk and *last_new_chunk to the most recent |
83 | * still-to-be-merged chunk and returns the number of |
84 | * consecutive previous ones. |
85 | */ |
86 | int (*prepare_merge)(struct dm_exception_store *store, |
87 | chunk_t *last_old_chunk, chunk_t *last_new_chunk); |
88 | |
89 | /* |
90 | * Clear the last n exceptions. |
91 | * nr_merged must be <= the value returned by prepare_merge. |
92 | */ |
93 | int (*commit_merge)(struct dm_exception_store *store, int nr_merged); |
94 | |
95 | /* |
96 | * The snapshot is invalid, note this in the metadata. |
97 | */ |
98 | void (*drop_snapshot)(struct dm_exception_store *store); |
99 | |
100 | unsigned int (*status)(struct dm_exception_store *store, |
101 | status_type_t status, char *result, |
102 | unsigned int maxlen); |
103 | |
104 | /* |
105 | * Return how full the snapshot is. |
106 | */ |
107 | void (*usage)(struct dm_exception_store *store, |
108 | sector_t *total_sectors, sector_t *sectors_allocated, |
109 | sector_t *metadata_sectors); |
110 | |
111 | /* For internal device-mapper use only. */ |
112 | struct list_head list; |
113 | }; |
114 | |
115 | struct dm_snapshot; |
116 | |
117 | struct dm_exception_store { |
118 | struct dm_exception_store_type *type; |
119 | struct dm_snapshot *snap; |
120 | |
121 | /* Size of data blocks saved - must be a power of 2 */ |
122 | unsigned int chunk_size; |
123 | unsigned int chunk_mask; |
124 | unsigned int chunk_shift; |
125 | |
126 | void *context; |
127 | |
128 | bool userspace_supports_overflow; |
129 | }; |
130 | |
131 | /* |
132 | * Obtain the origin or cow device used by a given snapshot. |
133 | */ |
134 | struct dm_dev *dm_snap_origin(struct dm_snapshot *snap); |
135 | struct dm_dev *dm_snap_cow(struct dm_snapshot *snap); |
136 | |
137 | /* |
138 | * Funtions to manipulate consecutive chunks |
139 | */ |
140 | #define DM_CHUNK_CONSECUTIVE_BITS 8 |
141 | #define DM_CHUNK_NUMBER_BITS 56 |
142 | |
143 | static inline chunk_t dm_chunk_number(chunk_t chunk) |
144 | { |
145 | return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL); |
146 | } |
147 | |
148 | static inline unsigned int dm_consecutive_chunk_count(struct dm_exception *e) |
149 | { |
150 | return e->new_chunk >> DM_CHUNK_NUMBER_BITS; |
151 | } |
152 | |
153 | static inline void dm_consecutive_chunk_count_inc(struct dm_exception *e) |
154 | { |
155 | e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS); |
156 | |
157 | BUG_ON(!dm_consecutive_chunk_count(e)); |
158 | } |
159 | |
160 | static inline void dm_consecutive_chunk_count_dec(struct dm_exception *e) |
161 | { |
162 | BUG_ON(!dm_consecutive_chunk_count(e)); |
163 | |
164 | e->new_chunk -= (1ULL << DM_CHUNK_NUMBER_BITS); |
165 | } |
166 | |
167 | /* |
168 | * Return the number of sectors in the device. |
169 | */ |
170 | static inline sector_t get_dev_size(struct block_device *bdev) |
171 | { |
172 | return bdev_nr_sectors(bdev); |
173 | } |
174 | |
175 | static inline chunk_t sector_to_chunk(struct dm_exception_store *store, |
176 | sector_t sector) |
177 | { |
178 | return sector >> store->chunk_shift; |
179 | } |
180 | |
181 | int dm_exception_store_type_register(struct dm_exception_store_type *type); |
182 | int dm_exception_store_type_unregister(struct dm_exception_store_type *type); |
183 | |
184 | int dm_exception_store_set_chunk_size(struct dm_exception_store *store, |
185 | unsigned int chunk_size, |
186 | char **error); |
187 | |
188 | int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, |
189 | struct dm_snapshot *snap, |
190 | unsigned int *args_used, |
191 | struct dm_exception_store **store); |
192 | void dm_exception_store_destroy(struct dm_exception_store *store); |
193 | |
194 | int dm_exception_store_init(void); |
195 | void dm_exception_store_exit(void); |
196 | |
197 | /* |
198 | * Two exception store implementations. |
199 | */ |
200 | int dm_persistent_snapshot_init(void); |
201 | void dm_persistent_snapshot_exit(void); |
202 | |
203 | int dm_transient_snapshot_init(void); |
204 | void dm_transient_snapshot_exit(void); |
205 | |
206 | #endif /* _LINUX_DM_EXCEPTION_STORE */ |
207 | |