]>
Commit | Line | Data |
---|---|---|
0340a1bb DM |
1 | From acdcd483ac6977e096ef7cde746d22bbf82e04d3 Mon Sep 17 00:00:00 2001 |
2 | From: Dietmar Maurer <dietmar@proxmox.com> | |
3 | Date: Mon, 11 Mar 2013 07:07:46 +0100 | |
4 | Subject: [PATCH v5 7/7] vma: add verify command | |
5 | ||
6 | Users wants to verify the archive after backup. | |
7 | ||
8 | Examples: | |
9 | ||
10 | # vma verify -v test.vma | |
11 | ||
12 | # lzop -d -c test.vma.lzo |vma verify - | |
13 | ||
14 | Signed-off-by: Dietmar Maurer <dietmar@proxmox.com> | |
15 | --- | |
16 | vma-reader.c | 118 +++++++++++++++++++++++++++++++++++++++++++--------------- | |
17 | vma.c | 57 +++++++++++++++++++++++++++- | |
18 | vma.h | 1 + | |
19 | 3 files changed, 145 insertions(+), 31 deletions(-) | |
20 | ||
21 | diff --git a/vma-reader.c b/vma-reader.c | |
22 | index bc36cba..a740f04 100644 | |
23 | --- a/vma-reader.c | |
24 | +++ b/vma-reader.c | |
25 | @@ -53,6 +53,8 @@ struct VmaReader { | |
26 | time_t start_time; | |
27 | int64_t cluster_count; | |
28 | int64_t clusters_read; | |
29 | + int64_t zero_cluster_data; | |
30 | + int64_t partial_zero_cluster_data; | |
31 | int clusters_read_per; | |
32 | }; | |
33 | ||
34 | @@ -433,6 +435,27 @@ VmaDeviceInfo *vma_reader_get_device_info(VmaReader *vmar, guint8 dev_id) | |
35 | return NULL; | |
36 | } | |
37 | ||
38 | +static void allocate_rstate(VmaReader *vmar, guint8 dev_id, | |
39 | + BlockDriverState *bs, bool write_zeroes) | |
40 | +{ | |
41 | + assert(vmar); | |
42 | + assert(dev_id); | |
43 | + | |
44 | + vmar->rstate[dev_id].bs = bs; | |
45 | + vmar->rstate[dev_id].write_zeroes = write_zeroes; | |
46 | + | |
47 | + int64_t size = vmar->devinfo[dev_id].size; | |
48 | + | |
49 | + int64_t bitmap_size = (size/BDRV_SECTOR_SIZE) + | |
50 | + (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG - 1; | |
51 | + bitmap_size /= (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG; | |
52 | + | |
53 | + vmar->rstate[dev_id].bitmap_size = bitmap_size; | |
54 | + vmar->rstate[dev_id].bitmap = g_new0(unsigned long, bitmap_size); | |
55 | + | |
56 | + vmar->cluster_count += size/VMA_CLUSTER_SIZE; | |
57 | +} | |
58 | + | |
59 | int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id, BlockDriverState *bs, | |
60 | bool write_zeroes, Error **errp) | |
61 | { | |
62 | @@ -449,17 +472,7 @@ int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id, BlockDriverState *bs, | |
63 | return -1; | |
64 | } | |
65 | ||
66 | - vmar->rstate[dev_id].bs = bs; | |
67 | - vmar->rstate[dev_id].write_zeroes = write_zeroes; | |
68 | - | |
69 | - int64_t bitmap_size = (size/BDRV_SECTOR_SIZE) + | |
70 | - (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG - 1; | |
71 | - bitmap_size /= (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG; | |
72 | - | |
73 | - vmar->rstate[dev_id].bitmap_size = bitmap_size; | |
74 | - vmar->rstate[dev_id].bitmap = g_new0(unsigned long, bitmap_size); | |
75 | - | |
76 | - vmar->cluster_count += size/VMA_CLUSTER_SIZE; | |
77 | + allocate_rstate(vmar, dev_id, bs, write_zeroes); | |
78 | ||
79 | return 0; | |
80 | } | |
81 | @@ -526,9 +539,10 @@ static int restore_write_data(VmaReader *vmar, guint8 dev_id, | |
82 | } | |
83 | return 0; | |
84 | } | |
85 | + | |
86 | static int restore_extent(VmaReader *vmar, unsigned char *buf, | |
87 | int extent_size, int vmstate_fd, | |
88 | - bool verbose, Error **errp) | |
89 | + bool verbose, bool verify, Error **errp) | |
90 | { | |
91 | assert(vmar); | |
92 | assert(buf); | |
93 | @@ -553,7 +567,7 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf, | |
94 | ||
95 | if (dev_id != vmar->vmstate_stream) { | |
96 | bs = rstate->bs; | |
97 | - if (!bs) { | |
98 | + if (!verify && !bs) { | |
99 | error_setg(errp, "got wrong dev id %d", dev_id); | |
100 | return -1; | |
101 | } | |
102 | @@ -609,10 +623,13 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf, | |
103 | return -1; | |
104 | } | |
105 | ||
106 | - int nb_sectors = end_sector - sector_num; | |
107 | - if (restore_write_data(vmar, dev_id, bs, vmstate_fd, buf + start, | |
108 | - sector_num, nb_sectors, errp) < 0) { | |
109 | - return -1; | |
110 | + if (!verify) { | |
111 | + int nb_sectors = end_sector - sector_num; | |
112 | + if (restore_write_data(vmar, dev_id, bs, vmstate_fd, | |
113 | + buf + start, sector_num, nb_sectors, | |
114 | + errp) < 0) { | |
115 | + return -1; | |
116 | + } | |
117 | } | |
118 | ||
119 | start += VMA_CLUSTER_SIZE; | |
120 | @@ -642,26 +659,37 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf, | |
121 | return -1; | |
122 | } | |
123 | ||
124 | - int nb_sectors = end_sector - sector_num; | |
125 | - if (restore_write_data(vmar, dev_id, bs, vmstate_fd, | |
126 | - buf + start, sector_num, | |
127 | - nb_sectors, errp) < 0) { | |
128 | - return -1; | |
129 | + if (!verify) { | |
130 | + int nb_sectors = end_sector - sector_num; | |
131 | + if (restore_write_data(vmar, dev_id, bs, vmstate_fd, | |
132 | + buf + start, sector_num, | |
133 | + nb_sectors, errp) < 0) { | |
134 | + return -1; | |
135 | + } | |
136 | } | |
137 | ||
138 | start += VMA_BLOCK_SIZE; | |
139 | ||
140 | } else { | |
141 | ||
142 | - if (rstate->write_zeroes && (end_sector > sector_num)) { | |
143 | + | |
144 | + if (end_sector > sector_num) { | |
145 | /* Todo: use bdrv_co_write_zeroes (but that need to | |
146 | * be run inside coroutine?) | |
147 | */ | |
148 | int nb_sectors = end_sector - sector_num; | |
149 | - if (restore_write_data(vmar, dev_id, bs, vmstate_fd, | |
150 | - zero_vma_block, sector_num, | |
151 | - nb_sectors, errp) < 0) { | |
152 | - return -1; | |
153 | + int zero_size = BDRV_SECTOR_SIZE*nb_sectors; | |
154 | + vmar->zero_cluster_data += zero_size; | |
155 | + if (mask != 0) { | |
156 | + vmar->partial_zero_cluster_data += zero_size; | |
157 | + } | |
158 | + | |
159 | + if (rstate->write_zeroes && !verify) { | |
160 | + if (restore_write_data(vmar, dev_id, bs, vmstate_fd, | |
161 | + zero_vma_block, sector_num, | |
162 | + nb_sectors, errp) < 0) { | |
163 | + return -1; | |
164 | + } | |
165 | } | |
166 | } | |
167 | } | |
168 | @@ -679,8 +707,9 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf, | |
169 | return 0; | |
170 | } | |
171 | ||
172 | -int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose, | |
173 | - Error **errp) | |
174 | +static int vma_reader_restore_full(VmaReader *vmar, int vmstate_fd, | |
175 | + bool verbose, bool verify, | |
176 | + Error **errp) | |
177 | { | |
178 | assert(vmar); | |
179 | assert(vmar->head_data); | |
180 | @@ -747,7 +776,7 @@ int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose, | |
181 | } | |
182 | ||
183 | if (restore_extent(vmar, buf, extent_size, vmstate_fd, verbose, | |
184 | - errp) < 0) { | |
185 | + verify, errp) < 0) { | |
186 | return -1; | |
187 | } | |
188 | ||
189 | @@ -794,6 +823,35 @@ int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose, | |
190 | } | |
191 | } | |
192 | ||
193 | + if (verbose) { | |
194 | + printf("total bytes read %zd, sparse bytes %zd (%.3g%%)\n", | |
195 | + vmar->clusters_read*VMA_CLUSTER_SIZE, | |
196 | + vmar->zero_cluster_data, | |
197 | + (double)(100.0*vmar->zero_cluster_data)/ | |
198 | + (vmar->clusters_read*VMA_CLUSTER_SIZE)); | |
27f6b7fc | 199 | + printf("space reduction due to 4K zero blocks %.3g%%\n", |
0340a1bb DM |
200 | + (double)(100.0*vmar->partial_zero_cluster_data) / |
201 | + (vmar->clusters_read*VMA_CLUSTER_SIZE-vmar->zero_cluster_data)); | |
202 | + } | |
203 | return ret; | |
204 | } | |
205 | ||
206 | +int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose, | |
207 | + Error **errp) | |
208 | +{ | |
209 | + return vma_reader_restore_full(vmar, vmstate_fd, verbose, false, errp); | |
210 | +} | |
211 | + | |
212 | +int vma_reader_verify(VmaReader *vmar, bool verbose, Error **errp) | |
213 | +{ | |
214 | + guint8 dev_id; | |
215 | + | |
216 | + for (dev_id = 1; dev_id < 255; dev_id++) { | |
217 | + if (vma_reader_get_device_info(vmar, dev_id)) { | |
218 | + allocate_rstate(vmar, dev_id, NULL, false); | |
219 | + } | |
220 | + } | |
221 | + | |
222 | + return vma_reader_restore_full(vmar, -1, verbose, true, errp); | |
223 | +} | |
224 | + | |
225 | diff --git a/vma.c b/vma.c | |
226 | index 6633aa5..bcde379 100644 | |
227 | --- a/vma.c | |
228 | +++ b/vma.c | |
229 | @@ -33,7 +33,8 @@ static void help(void) | |
230 | "\n" | |
231 | "vma list <filename>\n" | |
232 | "vma create <filename> [-c config] <archive> pathname ...\n" | |
233 | - "vma extract <filename> [-r] <targetdir>\n" | |
234 | + "vma extract <filename> [-v] [-r] <targetdir>\n" | |
235 | + "vma verify <filename> [-v]\n" | |
236 | ; | |
237 | ||
238 | printf("%s", help_msg); | |
239 | @@ -337,6 +338,58 @@ static int extract_content(int argc, char **argv) | |
240 | return ret; | |
241 | } | |
242 | ||
243 | +static int verify_content(int argc, char **argv) | |
244 | +{ | |
245 | + int c, ret = 0; | |
246 | + int verbose = 0; | |
247 | + const char *filename; | |
248 | + | |
249 | + for (;;) { | |
250 | + c = getopt(argc, argv, "hv"); | |
251 | + if (c == -1) { | |
252 | + break; | |
253 | + } | |
254 | + switch (c) { | |
255 | + case '?': | |
256 | + case 'h': | |
257 | + help(); | |
258 | + break; | |
259 | + case 'v': | |
260 | + verbose = 1; | |
261 | + break; | |
262 | + default: | |
263 | + help(); | |
264 | + } | |
265 | + } | |
266 | + | |
267 | + /* Get the filename */ | |
268 | + if ((optind + 1) != argc) { | |
269 | + help(); | |
270 | + } | |
271 | + filename = argv[optind++]; | |
272 | + | |
273 | + Error *errp = NULL; | |
274 | + VmaReader *vmar = vma_reader_create(filename, &errp); | |
275 | + | |
276 | + if (!vmar) { | |
277 | + g_error("%s", error_get_pretty(errp)); | |
278 | + } | |
279 | + | |
280 | + if (verbose) { | |
281 | + print_content(vmar); | |
282 | + } | |
283 | + | |
284 | + if (vma_reader_verify(vmar, verbose, &errp) < 0) { | |
285 | + g_error("verify failed - %s", error_get_pretty(errp)); | |
286 | + } | |
287 | + | |
288 | + vma_reader_destroy(vmar); | |
289 | + | |
290 | + bdrv_close_all(); | |
291 | + | |
292 | + return ret; | |
293 | +} | |
294 | + | |
295 | typedef struct BackupCB { | |
296 | VmaWriter *vmaw; | |
297 | uint8_t dev_id; | |
298 | @@ -554,6 +607,8 @@ int main(int argc, char **argv) | |
299 | return create_archive(argc, argv); | |
300 | } else if (!strcmp(cmdname, "extract")) { | |
301 | return extract_content(argc, argv); | |
302 | + } else if (!strcmp(cmdname, "verify")) { | |
303 | + return verify_content(argc, argv); | |
304 | } | |
305 | ||
306 | help(); | |
307 | diff --git a/vma.h b/vma.h | |
308 | index 76d0dc8..ebd96c1 100644 | |
309 | --- a/vma.h | |
310 | +++ b/vma.h | |
311 | @@ -141,5 +141,6 @@ int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id, | |
312 | Error **errp); | |
313 | int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose, | |
314 | Error **errp); | |
315 | +int vma_reader_verify(VmaReader *vmar, bool verbose, Error **errp); | |
316 | ||
317 | #endif /* BACKUP_VMA_H */ | |
318 | -- | |
319 | 1.7.2.5 | |
320 |