Line data Source code
1 : #include "clusterautoconfig.h"
2 :
3 : #include <stdio.h>
4 : #include <stdlib.h>
5 : #include <ctype.h>
6 : #include <string.h>
7 : #include <stdint.h>
8 : #include <inttypes.h>
9 : #include <sys/types.h>
10 : #include <sys/stat.h>
11 : #include <fcntl.h>
12 : #include <unistd.h>
13 : #include <errno.h>
14 : #include <curses.h>
15 : #include <term.h>
16 : #include <sys/ioctl.h>
17 : #include <limits.h>
18 : #include <sys/time.h>
19 : #include <zlib.h>
20 : #include <bzlib.h>
21 : #include <time.h>
22 :
23 : #include <logging.h>
24 : #include "osi_list.h"
25 : #include "gfs2hex.h"
26 : #include "hexedit.h"
27 : #include "libgfs2.h"
28 :
29 : #define DFT_SAVE_FILE "/tmp/gfsmeta.XXXXXX"
30 : #define MAX_JOURNALS_SAVED 256
31 :
32 : /* Header for the savemeta output file */
33 : struct savemeta_header {
34 : #define SAVEMETA_MAGIC (0x01171970)
35 : __be32 sh_magic;
36 : #define SAVEMETA_FORMAT (1)
37 : __be32 sh_format; /* In case we want to change the layout */
38 : __be64 sh_time; /* When savemeta was run */
39 : __be64 sh_fs_bytes; /* Size of the fs */
40 : uint8_t __reserved[104];
41 : };
42 :
43 : struct savemeta {
44 : time_t sm_time;
45 : unsigned sm_format;
46 : uint64_t sm_fs_bytes;
47 : };
48 :
49 : struct saved_metablock {
50 : __be64 blk;
51 : __be16 siglen; /* significant data length */
52 : /* This needs to be packed because old versions of gfs2_edit read and write the
53 : individual fields separately, so the hole after siglen must be eradicated
54 : before the struct reflects what's on disk. */
55 : } __attribute__((__packed__));
56 :
57 : struct metafd {
58 : int fd;
59 : gzFile gzfd;
60 : BZFILE *bzfd;
61 : const char *filename;
62 : int gziplevel;
63 : int eof;
64 : int (*read)(struct metafd *mfd, void *buf, unsigned len);
65 : void (*close)(struct metafd *mfd);
66 : const char* (*strerr)(struct metafd *mfd);
67 : };
68 :
69 : static char *restore_buf;
70 : static ssize_t restore_left;
71 : static off_t restore_off;
72 : #define RESTORE_BUF_SIZE (2 * 1024 * 1024)
73 :
74 460952 : static char *restore_buf_next(struct metafd *mfd, size_t required_len)
75 : {
76 460952 : if (restore_left < required_len) {
77 14 : char *tail = restore_buf + restore_off;
78 : int ret;
79 :
80 14 : memmove(restore_buf, tail, restore_left);
81 14 : ret = mfd->read(mfd, restore_buf + restore_left, RESTORE_BUF_SIZE - restore_left);
82 14 : if (ret < (int)required_len - restore_left)
83 6 : return NULL;
84 8 : restore_left += ret;
85 8 : restore_off = 0;
86 : }
87 460946 : restore_left -= required_len;
88 460946 : restore_off += required_len;
89 460946 : return &restore_buf[restore_off - required_len];
90 : }
91 :
92 : /* gzip compression method */
93 :
94 0 : static const char *gz_strerr(struct metafd *mfd)
95 : {
96 : int err;
97 0 : const char *errstr = gzerror(mfd->gzfd, &err);
98 :
99 0 : if (err == Z_ERRNO)
100 0 : return strerror(errno);
101 0 : return errstr;
102 : }
103 :
104 20 : static int gz_read(struct metafd *mfd, void *buf, unsigned len)
105 : {
106 20 : int ret = gzread(mfd->gzfd, buf, len);
107 20 : if (ret < len && gzeof(mfd->gzfd))
108 12 : mfd->eof = 1;
109 20 : return ret;
110 : }
111 :
112 6 : static void gz_close(struct metafd *mfd)
113 : {
114 6 : gzclose(mfd->gzfd);
115 6 : }
116 :
117 : /* This should be tried last because gzip doesn't distinguish between
118 : decompressing a gzip file and reading an uncompressed file */
119 6 : static int restore_try_gzip(struct metafd *mfd)
120 : {
121 6 : mfd->read = gz_read;
122 6 : mfd->close = gz_close;
123 6 : mfd->strerr = gz_strerr;
124 6 : lseek(mfd->fd, 0, SEEK_SET);
125 6 : mfd->gzfd = gzdopen(mfd->fd, "rb");
126 6 : if (!mfd->gzfd)
127 0 : return 1;
128 6 : gzbuffer(mfd->gzfd, (1<<20)); /* Increase zlib's buffers to 1MB */
129 6 : restore_left = mfd->read(mfd, restore_buf, RESTORE_BUF_SIZE);
130 6 : if (restore_left < 512)
131 0 : return -1;
132 6 : return 0;
133 : }
134 :
135 : /* bzip2 compression method */
136 :
137 0 : static const char *bz_strerr(struct metafd *mfd)
138 : {
139 : int err;
140 0 : const char *errstr = BZ2_bzerror(mfd->bzfd, &err);
141 :
142 0 : if (err == BZ_IO_ERROR)
143 0 : return strerror(errno);
144 0 : return errstr;
145 : }
146 :
147 6 : static int bz_read(struct metafd *mfd, void *buf, unsigned len)
148 : {
149 6 : int bzerr = BZ_OK;
150 : int ret;
151 :
152 6 : ret = BZ2_bzRead(&bzerr, mfd->bzfd, buf, len);
153 6 : if (bzerr == BZ_OK)
154 0 : return ret;
155 6 : if (bzerr == BZ_STREAM_END) {
156 0 : mfd->eof = 1;
157 0 : return ret;
158 : }
159 6 : return -1;
160 : }
161 :
162 0 : static void bz_close(struct metafd *mfd)
163 : {
164 0 : BZ2_bzclose(mfd->bzfd);
165 0 : }
166 :
167 6 : static int restore_try_bzip(struct metafd *mfd)
168 : {
169 : int bzerr;
170 : FILE *f;
171 :
172 6 : f = fdopen(mfd->fd, "r");
173 6 : if (f == NULL)
174 0 : return 1;
175 :
176 6 : mfd->read = bz_read;
177 6 : mfd->close = bz_close;
178 6 : mfd->strerr = bz_strerr;
179 6 : mfd->bzfd = BZ2_bzReadOpen(&bzerr, f, 0, 0, NULL, 0);
180 6 : if (!mfd->bzfd)
181 0 : return 1;
182 6 : restore_left = mfd->read(mfd, restore_buf, RESTORE_BUF_SIZE);
183 6 : if (restore_left < 512)
184 6 : return -1;
185 0 : return 0;
186 : }
187 :
188 : static uint64_t blks_saved;
189 : static uint64_t journal_blocks[MAX_JOURNALS_SAVED];
190 : static int journals_found = 0;
191 : int print_level = MSG_NOTICE;
192 :
193 28 : static int block_is_a_journal(uint64_t blk)
194 : {
195 : int j;
196 :
197 196 : for (j = 0; j < journals_found; j++)
198 168 : if (blk == journal_blocks[j])
199 0 : return TRUE;
200 28 : return FALSE;
201 : }
202 :
203 : static struct osi_root per_node_tree;
204 : struct per_node_node {
205 : struct osi_node node;
206 : uint64_t block;
207 : };
208 :
209 8 : static void destroy_per_node_lookup(void)
210 : {
211 : struct osi_node *n;
212 : struct per_node_node *pnp;
213 :
214 22 : while ((n = osi_first(&per_node_tree))) {
215 14 : pnp = (struct per_node_node *)n;
216 14 : osi_erase(n, &per_node_tree);
217 14 : free(pnp);
218 : }
219 8 : }
220 :
221 28 : static int block_is_in_per_node(uint64_t blk)
222 : {
223 28 : struct per_node_node *pnp = (struct per_node_node *)per_node_tree.osi_node;
224 :
225 45 : while (pnp) {
226 25 : if (blk < pnp->block)
227 6 : pnp = (struct per_node_node *)pnp->node.osi_left;
228 19 : else if (blk > pnp->block)
229 11 : pnp = (struct per_node_node *)pnp->node.osi_right;
230 : else
231 8 : return 1;
232 : }
233 :
234 20 : return 0;
235 : }
236 :
237 14 : static int insert_per_node_lookup(uint64_t blk)
238 : {
239 14 : struct osi_node **newn = &per_node_tree.osi_node, *parent = NULL;
240 : struct per_node_node *pnp;
241 :
242 52 : while (*newn) {
243 38 : struct per_node_node *cur = (struct per_node_node *)*newn;
244 :
245 38 : parent = *newn;
246 38 : if (blk < cur->block)
247 8 : newn = &((*newn)->osi_left);
248 30 : else if (blk > cur->block)
249 30 : newn = &((*newn)->osi_right);
250 : else
251 0 : return 0;
252 : }
253 :
254 14 : pnp = calloc(1, sizeof(struct per_node_node));
255 14 : if (pnp == NULL) {
256 0 : perror("Failed to insert per_node lookup entry");
257 0 : return 1;
258 : }
259 14 : pnp->block = blk;
260 14 : osi_link_node(&pnp->node, parent, newn);
261 14 : osi_insert_color(&pnp->node, &per_node_tree);
262 14 : return 0;
263 : }
264 :
265 8 : static int init_per_node_lookup(void)
266 : {
267 : int i;
268 : struct lgfs2_inode *per_node_di;
269 :
270 8 : per_node_di = lgfs2_inode_read(&sbd, masterblock("per_node"));
271 8 : if (per_node_di == NULL) {
272 0 : fprintf(stderr, "Failed to read per_node: %s\n", strerror(errno));
273 0 : return 1;
274 : }
275 :
276 8 : do_dinode_extended(per_node_di->i_bh->b_data);
277 8 : lgfs2_inode_put(&per_node_di);
278 :
279 11 : for (i = 0; i < indirect_blocks; i++) {
280 : int d;
281 17 : for (d = 0; d < indirect->ii[i].dirents; d++) {
282 14 : int ret = insert_per_node_lookup(indirect->ii[i].dirent[d].inum.in_addr);
283 14 : if (ret != 0)
284 0 : return ret;
285 : }
286 : }
287 8 : return 0;
288 : }
289 :
290 94 : static int block_is_systemfile(uint64_t blk)
291 : {
292 180 : return block_is_inum_file(blk) ||
293 164 : block_is_statfs_file(blk) ||
294 148 : block_is_quota_file(blk) ||
295 98 : block_is_rindex(blk) ||
296 56 : block_is_a_journal(blk) ||
297 208 : block_is_per_node(blk) ||
298 28 : block_is_in_per_node(blk);
299 : }
300 :
301 120 : static size_t di_save_len(const char *buf, uint64_t owner)
302 : {
303 : const struct gfs2_dinode *dn;
304 : uint16_t di_height;
305 : uint32_t di_mode;
306 :
307 120 : dn = (void *)buf;
308 120 : di_mode = be32_to_cpu(dn->di_mode);
309 120 : di_height = be16_to_cpu(dn->di_height);
310 :
311 : /* Do not save (user) data from the inode block unless they are
312 : indirect pointers, dirents, symlinks or fs internal data */
313 172 : if (di_height > 0 || S_ISDIR(di_mode) || S_ISLNK(di_mode) ||
314 52 : block_is_systemfile(owner))
315 100 : return sbd.sd_bsize;
316 20 : return sizeof(struct gfs2_dinode);
317 : }
318 :
319 : /*
320 : * get_struct_info - get block type and structure length
321 : *
322 : * @buf - The block buffer to examine
323 : * @owner - The block address of the parent structure
324 : * @block_type - pointer to integer to hold the block type
325 : * @gstruct_len - pointer to integer to hold the structure length
326 : *
327 : * returns: 0 if successful
328 : * -1 if this isn't gfs2 metadata.
329 : */
330 252382 : static int get_struct_info(const char *buf, uint64_t owner, unsigned *block_type,
331 : unsigned *gstruct_len)
332 : {
333 252382 : struct gfs2_meta_header *mh = (struct gfs2_meta_header *)buf;
334 :
335 252382 : if (block_type != NULL)
336 252382 : *block_type = 0;
337 :
338 252382 : if (gstruct_len != NULL)
339 252382 : *gstruct_len = sbd.sd_bsize;
340 :
341 252382 : if (be32_to_cpu(mh->mh_magic) != GFS2_MAGIC)
342 42 : return -1;
343 :
344 252340 : if (block_type != NULL)
345 252340 : *block_type = be32_to_cpu(mh->mh_type);
346 :
347 252340 : if (gstruct_len == NULL)
348 0 : return 0;
349 :
350 252340 : switch (be32_to_cpu(mh->mh_type)) {
351 8 : case GFS2_METATYPE_SB: /* 1 (superblock) */
352 8 : *gstruct_len = sizeof(struct gfs2_sb);
353 8 : break;
354 0 : case GFS2_METATYPE_RG: /* 2 (rsrc grp hdr) */
355 0 : *gstruct_len = sbd.sd_bsize; /*sizeof(struct gfs_rgrp);*/
356 0 : break;
357 0 : case GFS2_METATYPE_RB: /* 3 (rsrc grp bitblk) */
358 0 : *gstruct_len = sbd.sd_bsize;
359 0 : break;
360 120 : case GFS2_METATYPE_DI: /* 4 (disk inode) */
361 120 : *gstruct_len = di_save_len(buf, owner);
362 120 : break;
363 2094 : case GFS2_METATYPE_IN: /* 5 (indir inode blklst) */
364 2094 : *gstruct_len = sbd.sd_bsize; /*sizeof(struct gfs_indirect);*/
365 2094 : break;
366 6 : case GFS2_METATYPE_LF: /* 6 (leaf dinode blklst) */
367 6 : *gstruct_len = sbd.sd_bsize; /*sizeof(struct gfs_leaf);*/
368 6 : break;
369 0 : case GFS2_METATYPE_JD: /* 7 (journal data) */
370 0 : *gstruct_len = sbd.sd_bsize;
371 0 : break;
372 237568 : case GFS2_METATYPE_LH: /* 8 (log header) */
373 237568 : *gstruct_len = sizeof(struct gfs2_log_header);
374 237568 : break;
375 0 : case GFS2_METATYPE_LD: /* 9 (log descriptor) */
376 0 : *gstruct_len = sbd.sd_bsize;
377 0 : break;
378 0 : case GFS2_METATYPE_EA: /* 10 (extended attr hdr) */
379 0 : *gstruct_len = sbd.sd_bsize;
380 0 : break;
381 0 : case GFS2_METATYPE_ED: /* 11 (extended attr data) */
382 0 : *gstruct_len = sbd.sd_bsize;
383 0 : break;
384 12544 : default:
385 12544 : *gstruct_len = sbd.sd_bsize;
386 12544 : break;
387 : }
388 252340 : return 0;
389 : }
390 :
391 : /**
392 : * Print a progress message if one second has elapsed since the last time.
393 : * pblock: The latest block number processed
394 : * force: If this is non-zero, print immediately and add a newline after the
395 : * progress message.
396 : */
397 275931 : static void report_progress(uint64_t pblock, int force)
398 : {
399 : static struct timeval tv;
400 : static uint32_t seconds = 0;
401 :
402 275931 : gettimeofday(&tv, NULL);
403 275931 : if (!seconds)
404 14 : seconds = tv.tv_sec;
405 275931 : if (force || tv.tv_sec - seconds) {
406 : static uint64_t percent;
407 :
408 18 : seconds = tv.tv_sec;
409 18 : if (sbd.fssize) {
410 18 : printf("\r");
411 18 : percent = (pblock * 100) / sbd.fssize;
412 18 : printf("%"PRIu64" blocks saved (%"PRIu64"%% complete)",
413 : blks_saved, percent);
414 18 : if (force)
415 14 : printf("\n");
416 18 : fflush(stdout);
417 : }
418 : }
419 275931 : }
420 :
421 : /**
422 : * Open a file and prepare it for writing by savemeta()
423 : * out_fn: the path to the file, which will be truncated if it exists
424 : * gziplevel: 0 - do not compress the file,
425 : * 1-9 - use gzip compression level 1-9
426 : * Returns a struct metafd containing the opened file descriptor
427 : */
428 8 : static struct metafd savemetaopen(char *out_fn, int gziplevel)
429 : {
430 8 : struct metafd mfd = {0};
431 8 : char gzmode[3] = "w9";
432 8 : char dft_fn[] = DFT_SAVE_FILE;
433 8 : mode_t mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
434 : struct stat st;
435 :
436 8 : mfd.gziplevel = gziplevel;
437 :
438 8 : if (!out_fn) {
439 0 : out_fn = dft_fn;
440 0 : mfd.fd = mkstemp(out_fn);
441 : } else {
442 8 : mfd.fd = open(out_fn, O_RDWR | O_CREAT, 0644);
443 : }
444 8 : umask(mask);
445 8 : mfd.filename = out_fn;
446 :
447 8 : if (mfd.fd < 0) {
448 0 : fprintf(stderr, "Can't open %s: %s\n", out_fn, strerror(errno));
449 0 : exit(1);
450 : }
451 8 : if (fstat(mfd.fd, &st) == -1) {
452 0 : fprintf(stderr, "Failed to stat %s: %s\n", out_fn, strerror(errno));
453 0 : exit(1);
454 : }
455 8 : if (S_ISREG(st.st_mode) && ftruncate(mfd.fd, 0)) {
456 0 : fprintf(stderr, "Can't truncate %s: %s\n", out_fn, strerror(errno));
457 0 : exit(1);
458 : }
459 :
460 8 : if (gziplevel > 0) {
461 3 : gzmode[1] = '0' + gziplevel;
462 3 : mfd.gzfd = gzdopen(mfd.fd, gzmode);
463 3 : if (!mfd.gzfd) {
464 0 : fprintf(stderr, "gzdopen error: %s\n", strerror(errno));
465 0 : exit(1);
466 : }
467 3 : gzbuffer(mfd.gzfd, (1<<20)); /* Increase zlib's buffers to 1MB */
468 : }
469 :
470 8 : return mfd;
471 : }
472 :
473 : /**
474 : * Write nbyte bytes from buf to a file opened with savemetaopen()
475 : * mfd: the file descriptor opened using savemetaopen()
476 : * buf: the buffer to write data from
477 : * nbyte: the number of bytes to write
478 : * Returns the number of bytes written from buf or -1 on error
479 : */
480 297501 : static ssize_t savemetawrite(struct metafd *mfd, const void *buf, size_t nbyte)
481 : {
482 : ssize_t ret;
483 : int gzerr;
484 : const char *gzerrmsg;
485 :
486 297501 : if (mfd->gziplevel == 0) {
487 213595 : return write(mfd->fd, buf, nbyte);
488 : }
489 :
490 83906 : ret = gzwrite(mfd->gzfd, buf, nbyte);
491 83906 : if (ret != nbyte) {
492 0 : gzerrmsg = gzerror(mfd->gzfd, &gzerr);
493 0 : if (gzerr != Z_ERRNO) {
494 0 : fprintf(stderr, "Error: zlib: %s\n", gzerrmsg);
495 : }
496 : }
497 83906 : return ret;
498 : }
499 :
500 : /**
501 : * Closes a file descriptor previously opened using savemetaopen()
502 : * mfd: the file descriptor previously opened using savemetaopen()
503 : * Returns 0 on success or -1 on error
504 : */
505 8 : static int savemetaclose(struct metafd *mfd)
506 : {
507 : int gzret;
508 8 : if (mfd->gziplevel > 0) {
509 3 : gzret = gzclose(mfd->gzfd);
510 3 : if (gzret == Z_STREAM_ERROR) {
511 0 : fprintf(stderr, "gzclose: file is not valid\n");
512 0 : return -1;
513 3 : } else if (gzret == Z_ERRNO) {
514 0 : return -1;
515 : }
516 : }
517 8 : return close(mfd->fd);
518 : }
519 :
520 297493 : static int save_buf(struct metafd *mfd, const char *buf, uint64_t addr, unsigned blklen)
521 : {
522 : struct saved_metablock *savedata;
523 : size_t outsz;
524 :
525 : /* No need to save trailing zeroes, but leave that for compression to
526 : deal with when enabled as this adds a significant overhead */
527 297493 : if (mfd->gziplevel == 0)
528 43150243 : for (; blklen > 0 && buf[blklen - 1] == '\0'; blklen--);
529 :
530 297493 : if (blklen == 0) /* No significant data; skip. */
531 0 : return 0;
532 :
533 297493 : outsz = sizeof(*savedata) + blklen;
534 297493 : savedata = calloc(1, outsz);
535 297493 : if (savedata == NULL) {
536 0 : perror("Failed to save block");
537 0 : exit(1);
538 : }
539 297493 : savedata->blk = cpu_to_be64(addr);
540 297493 : savedata->siglen = cpu_to_be16(blklen);
541 297493 : memcpy(savedata + 1, buf, blklen);
542 :
543 297493 : if (savemetawrite(mfd, savedata, outsz) != outsz) {
544 0 : fprintf(stderr, "write error: %s from %s:%d: block %"PRIu64"\n",
545 0 : strerror(errno), __FUNCTION__, __LINE__, addr);
546 0 : free(savedata);
547 0 : exit(-1);
548 : }
549 297493 : blks_saved++;
550 297493 : free(savedata);
551 297493 : return 0;
552 : }
553 :
554 : struct block_range {
555 : struct block_range *next;
556 : uint64_t start;
557 : unsigned len;
558 : unsigned *blktype;
559 : unsigned *blklen;
560 : char *buf;
561 : };
562 :
563 2367 : static int block_range_prepare(struct block_range *br)
564 : {
565 2367 : br->buf = calloc(br->len, sbd.sd_bsize + sizeof(*br->blktype) + sizeof(*br->blklen));
566 2367 : if (br->buf == NULL) {
567 0 : perror("Failed to allocate block range buffer");
568 0 : return 1;
569 : }
570 2367 : br->blktype = (unsigned *)(br->buf + (br->len * sbd.sd_bsize));
571 2367 : br->blklen = br->blktype + br->len;
572 2367 : return 0;
573 : }
574 :
575 2367 : static int block_range_check(struct block_range *br)
576 : {
577 2367 : if (br->start >= LGFS2_SB_ADDR(&sbd) && br->start + br->len <= sbd.fssize)
578 2367 : return 0;
579 :
580 0 : fprintf(stderr, "Warning: bad range 0x%"PRIx64" (%u blocks) ignored.\n",
581 : br->start, br->len);
582 0 : free(br->buf);
583 0 : br->buf = NULL;
584 0 : return 1;
585 : }
586 :
587 2367 : static void block_range_setinfo(struct block_range *br, uint64_t owner)
588 : {
589 254749 : for (unsigned i = 0; i < br->len; i++) {
590 252382 : char *buf = br->buf + (i * sbd.sd_bsize);
591 252382 : uint64_t addr = br->start + i;
592 252382 : uint64_t _owner = (owner == 0) ? addr : owner;
593 :
594 252424 : if (get_struct_info(buf, _owner, br->blktype + i, br->blklen + i) &&
595 42 : !block_is_systemfile(_owner)) {
596 0 : br->blklen[i] = 0;
597 : }
598 : }
599 2367 : }
600 :
601 213 : static void block_range_free(struct block_range **brp)
602 : {
603 213 : free((*brp)->buf);
604 213 : free(*brp);
605 213 : *brp = NULL;
606 213 : }
607 :
608 : struct block_range_queue {
609 : struct block_range *tail;
610 : struct block_range **head;
611 : };
612 :
613 1200 : static void block_range_queue_init(struct block_range_queue *q)
614 : {
615 1200 : q->head = &q->tail;
616 1200 : }
617 :
618 213 : static void block_range_queue_insert(struct block_range_queue *q, struct block_range *br)
619 : {
620 213 : *q->head = br;
621 213 : q->head = &br->next;
622 213 : }
623 :
624 213 : static struct block_range *block_range_queue_pop(struct block_range_queue *q)
625 : {
626 213 : struct block_range *br = q->tail;
627 :
628 213 : q->tail = br->next;
629 213 : br->next = NULL;
630 213 : return br;
631 : }
632 :
633 2359 : static int save_range(struct metafd *mfd, struct block_range *br)
634 : {
635 254733 : for (unsigned i = 0; i < br->len; i++) {
636 : int err;
637 :
638 252374 : err = save_buf(mfd, br->buf + (i * sbd.sd_bsize), br->start + i, br->blklen[i]);
639 252374 : if (err != 0)
640 0 : return err;
641 : }
642 2359 : return 0;
643 : }
644 :
645 2367 : static int check_read_range(int fd, struct block_range *br, uint64_t owner)
646 : {
647 : size_t size;
648 :
649 2367 : if (block_range_prepare(br) != 0)
650 0 : return 1;
651 :
652 2367 : if (block_range_check(br) != 0)
653 0 : return 1;
654 :
655 2367 : size = br->len * sbd.sd_bsize;
656 2367 : if (pread(sbd.device_fd, br->buf, size, sbd.sd_bsize * br->start) != size) {
657 0 : fprintf(stderr, "Failed to read block range 0x%"PRIx64" (%u blocks): %s\n",
658 0 : br->start, br->len, strerror(errno));
659 0 : free(br->buf);
660 0 : br->buf = NULL;
661 0 : return 1;
662 : }
663 2367 : block_range_setinfo(br, owner);
664 2367 : return 0;
665 : }
666 :
667 8 : static char *check_read_block(int fd, uint64_t blk, uint64_t owner, int *blktype, size_t *blklen)
668 : {
669 8 : struct block_range br = {
670 : .start = blk,
671 : .len = 1
672 : };
673 :
674 8 : if (check_read_range(fd, &br, owner) != 0)
675 0 : return NULL;
676 8 : if (blklen != NULL)
677 0 : *blklen = *br.blklen;
678 8 : if (blktype != NULL)
679 0 : *blktype = *br.blktype;
680 8 : return br.buf;
681 : }
682 :
683 : /*
684 : * save_ea_block - save off an extended attribute block
685 : */
686 0 : static void save_ea_block(struct metafd *mfd, char *buf, uint64_t owner)
687 : {
688 : struct gfs2_ea_header *ea;
689 0 : uint32_t rec_len = 0;
690 : int e;
691 :
692 0 : for (e = sizeof(struct gfs2_meta_header); e < sbd.sd_bsize; e += rec_len) {
693 : uint64_t blk;
694 : int charoff, i;
695 : __be64 *b;
696 :
697 0 : ea = (void *)(buf + e);
698 : /* ea_num_ptrs and ea_name_len are u8 so no endianness worries */
699 0 : for (i = 0; i < ea->ea_num_ptrs; i++) {
700 : char *_buf;
701 :
702 0 : charoff = e + ea->ea_name_len +
703 : sizeof(struct gfs2_ea_header) +
704 0 : sizeof(uint64_t) - 1;
705 0 : charoff /= sizeof(uint64_t);
706 0 : b = (__be64 *)buf;
707 0 : b += charoff + i;
708 0 : blk = be64_to_cpu(*b);
709 0 : _buf = check_read_block(sbd.device_fd, blk, owner, NULL, NULL);
710 0 : if (_buf != NULL) {
711 0 : save_buf(mfd, _buf, blk, sbd.sd_bsize);
712 0 : free(_buf);
713 : }
714 : }
715 0 : rec_len = be32_to_cpu(ea->ea_rec_len);
716 0 : if (rec_len == 0)
717 0 : break;
718 : }
719 0 : }
720 :
721 2302 : static void save_indirect_range(struct metafd *mfd, struct block_range **brp, uint64_t owner,
722 : struct block_range_queue *q)
723 : {
724 2302 : struct block_range *br = *brp;
725 :
726 2302 : if (check_read_range(sbd.device_fd, br, owner) != 0)
727 0 : return;
728 :
729 2302 : save_range(mfd, br);
730 254556 : for (unsigned i = 0; i < br->len; i++) {
731 252254 : if (br->blktype[i] == GFS2_METATYPE_EA)
732 0 : save_ea_block(mfd, br->buf + (i * sbd.sd_bsize), owner);
733 : }
734 2302 : if (q) {
735 213 : block_range_queue_insert(q, br);
736 213 : *brp = NULL; /* The list now has ownership of it */
737 : } else {
738 2089 : free(br->buf);
739 2089 : br->buf = NULL;
740 : }
741 : }
742 :
743 2134 : static void save_indirect_blocks(struct metafd *mfd, char *buf, uint64_t owner,
744 : struct block_range_queue *q, unsigned headsize)
745 : {
746 2134 : uint64_t old_block = 0, indir_block;
747 2134 : struct block_range *br = NULL;
748 : __be64 *ptr;
749 :
750 2134 : for (ptr = (__be64 *)(buf + headsize);
751 267908 : (char *)ptr < (buf + sbd.sd_bsize); ptr++) {
752 265774 : if (!*ptr)
753 13398 : continue;
754 :
755 252376 : indir_block = be64_to_cpu(*ptr);
756 252376 : if (indir_block == old_block)
757 122 : continue;
758 252254 : old_block = indir_block;
759 :
760 252254 : if (br == NULL) {
761 2134 : new_range:
762 2299 : br = calloc(1, sizeof(*br));
763 2299 : if (br == NULL) {
764 0 : perror("Failed to save indirect blocks");
765 0 : return;
766 : }
767 2299 : br->start = indir_block;
768 2299 : br->len = 1;
769 250120 : } else if (indir_block == br->start + br->len) {
770 249952 : br->len++;
771 : } else {
772 168 : save_indirect_range(mfd, &br, owner, q);
773 168 : if (br == NULL) /* This one was queued up for later */
774 165 : goto new_range;
775 3 : br->start = indir_block;
776 3 : br->len = 1;
777 : }
778 : }
779 2134 : if (br != NULL && br->start != 0)
780 2134 : save_indirect_range(mfd, &br, owner, q);
781 2134 : free(br);
782 : }
783 :
784 0 : static int save_leaf_chain(struct metafd *mfd, struct lgfs2_sbd *sdp, char *buf)
785 : {
786 0 : struct gfs2_leaf *leaf = (struct gfs2_leaf *)buf;
787 :
788 0 : while (leaf->lf_next != 0) {
789 0 : uint64_t blk = be64_to_cpu(leaf->lf_next);
790 : ssize_t r;
791 :
792 0 : if (lgfs2_check_range(sdp, blk) != 0)
793 0 : return 0;
794 :
795 0 : r = pread(sdp->device_fd, buf, sdp->sd_bsize, sdp->sd_bsize * blk);
796 0 : if (r != sdp->sd_bsize) {
797 0 : fprintf(stderr, "Failed to read leaf block %"PRIx64": %s\n",
798 0 : blk, strerror(errno));
799 0 : return 1;
800 : }
801 0 : report_progress(blk, 0);
802 0 : if (lgfs2_check_meta(buf, GFS2_METATYPE_LF) == 0) {
803 0 : int ret = save_buf(mfd, buf, blk, sdp->sd_bsize);
804 0 : if (ret != 0)
805 0 : return ret;
806 : }
807 0 : leaf = (struct gfs2_leaf *)buf;
808 : }
809 0 : return 0;
810 : }
811 :
812 4 : static void save_leaf_blocks(struct metafd *mfd, struct block_range_queue *q)
813 : {
814 4 : while (q->tail != NULL) {
815 0 : struct block_range *br = q->tail;
816 :
817 0 : for (unsigned i = 0; i < br->len; i++) {
818 0 : char *buf = br->buf + (i * sbd.sd_bsize);
819 :
820 0 : save_leaf_chain(mfd, &sbd, buf);
821 : }
822 0 : q->tail = br->next;
823 0 : block_range_free(&br);
824 : }
825 4 : }
826 :
827 : /*
828 : * save_inode_data - save off important data associated with an inode
829 : *
830 : * mfd - destination file descriptor
831 : * buf - buffer containing the inode block
832 : * iblk - block number of the inode to save the data for
833 : *
834 : * For user files, we don't want anything except all the indirect block
835 : * pointers that reside on blocks on all but the highest height.
836 : *
837 : * For system files like statfs and inum, we want everything because they
838 : * may contain important clues and no user data.
839 : *
840 : * For file system journals, the "data" is a mixture of metadata and
841 : * journaled data. We want all the metadata and none of the user data.
842 : */
843 120 : static void save_inode_data(struct metafd *mfd, char *ibuf, uint64_t iblk)
844 : {
845 120 : struct block_range_queue indq[GFS2_MAX_META_HEIGHT] = {{NULL}};
846 120 : struct gfs2_dinode *dip = (struct gfs2_dinode *)ibuf;
847 : uint16_t height;
848 : int is_exhash;
849 :
850 1320 : for (unsigned i = 0; i < GFS2_MAX_META_HEIGHT; i++)
851 1200 : block_range_queue_init(&indq[i]);
852 :
853 120 : height = be16_to_cpu(dip->di_height);
854 :
855 : /* If this is a user inode, we don't follow to the file height.
856 : We stop one level less. That way we save off the indirect
857 : pointer blocks but not the actual file contents. The exception
858 : is directories, where the height represents the level at which
859 : the hash table exists, and we have to save the directory data. */
860 :
861 152 : is_exhash = S_ISDIR(be32_to_cpu(dip->di_mode)) &&
862 32 : be32_to_cpu(dip->di_flags) & GFS2_DIF_EXHASH;
863 120 : if (is_exhash)
864 4 : height++;
865 116 : else if (height > 0 && !(be32_to_cpu(dip->di_flags) & GFS2_DIF_SYSTEM) &&
866 0 : !block_is_systemfile(iblk) && !S_ISDIR(be32_to_cpu(dip->di_mode)))
867 0 : height--;
868 :
869 120 : if (height == 1)
870 21 : save_indirect_blocks(mfd, ibuf, iblk, NULL, sizeof(*dip));
871 99 : else if (height > 1)
872 19 : save_indirect_blocks(mfd, ibuf, iblk, &indq[0], sizeof(*dip));
873 :
874 144 : for (unsigned i = 1; i < height; i++) {
875 24 : struct block_range_queue *nextq = &indq[i];
876 :
877 24 : if (!is_exhash && i == height - 1)
878 19 : nextq = NULL;
879 :
880 : /* Coverity can't figure out that the tail becomes NULL eventually. */
881 : /* coverity[loop_top:SUPPRESS] */
882 237 : while (indq[i - 1].tail != NULL) {
883 213 : struct block_range *q = block_range_queue_pop(&indq[i - 1]);
884 :
885 2307 : for (unsigned j = 0; j < q->len; j++) {
886 2094 : char *_buf = q->buf + (j * sbd.sd_bsize);
887 :
888 2094 : save_indirect_blocks(mfd, _buf, iblk, nextq, sizeof(dip->di_header));
889 : }
890 213 : report_progress(q->start + q->len, 0);
891 213 : block_range_free(&q);
892 : }
893 : }
894 120 : if (is_exhash)
895 4 : save_leaf_blocks(mfd, &indq[height - 1]);
896 120 : if (dip->di_eattr) { /* if this inode has extended attributes */
897 : size_t blklen;
898 : uint64_t blk;
899 : int mhtype;
900 : char *buf;
901 :
902 0 : blk = be64_to_cpu(dip->di_eattr);
903 0 : buf = check_read_block(sbd.device_fd, blk, iblk, &mhtype, &blklen);
904 0 : if (buf != NULL) {
905 0 : save_buf(mfd, buf, blk, blklen);
906 0 : if (mhtype == GFS2_METATYPE_EA)
907 0 : save_ea_block(mfd, buf, iblk);
908 0 : else if (mhtype == GFS2_METATYPE_IN)
909 0 : save_indirect_blocks(mfd, buf, iblk, NULL, sizeof(dip->di_header));
910 0 : free(buf);
911 : }
912 : }
913 120 : }
914 :
915 8 : static void get_journal_inode_blocks(void)
916 : {
917 : int journal;
918 :
919 8 : journals_found = 0;
920 8 : memset(journal_blocks, 0, sizeof(journal_blocks));
921 : /* Save off all the journals--but only the metadata.
922 : * This is confusing so I'll explain. The journals contain important
923 : * metadata. However, in gfs2 the journals are regular files within
924 : * the system directory. Since they're regular files, the blocks
925 : * within the journals are considered data, not metadata. Therefore,
926 : * they won't have been saved by the code above. We want to dump
927 : * these blocks, but we have to be careful. We only care about the
928 : * journal blocks that look like metadata, and we need to not save
929 : * journaled user data that may exist there as well. */
930 8 : for (journal = 0; ; journal++) { /* while journals exist */
931 : uint64_t jblock;
932 :
933 56 : if (journal + 3 > indirect->ii[0].dirents)
934 8 : break;
935 48 : jblock = indirect->ii[0].dirent[journal + 2].inum.in_addr;
936 48 : journal_blocks[journals_found++] = jblock;
937 : }
938 8 : }
939 :
940 57 : static void save_allocated_range(struct metafd *mfd, struct block_range *br)
941 : {
942 57 : if (check_read_range(sbd.device_fd, br, 0) != 0)
943 0 : return;
944 :
945 57 : save_range(mfd, br);
946 177 : for (unsigned i = 0; i < br->len; i++) {
947 120 : char *buf = br->buf + (i * sbd.sd_bsize);
948 :
949 120 : if (br->blktype[i] == GFS2_METATYPE_DI)
950 120 : save_inode_data(mfd, buf, br->start + i);
951 : }
952 57 : free(br->buf);
953 : }
954 :
955 574 : static void save_allocated(struct lgfs2_rgrp_tree *rgd, struct metafd *mfd)
956 : {
957 574 : uint64_t blk = 0;
958 : unsigned i, j, m;
959 574 : uint64_t *ibuf = malloc(sbd.sd_bsize * GFS2_NBBY * sizeof(uint64_t));
960 :
961 45685 : for (i = 0; i < rgd->rt_length; i++) {
962 45111 : struct block_range br = {0};
963 :
964 45111 : m = lgfs2_bm_scan(rgd, i, ibuf, GFS2_BLKST_DINODE);
965 :
966 45231 : for (j = 0; j < m; j++) {
967 120 : blk = ibuf[j];
968 120 : if (br.start == 0) {
969 35 : br.start = blk;
970 35 : br.len = 1;
971 85 : } else if (blk == br.start + br.len) {
972 63 : br.len++;
973 : } else {
974 22 : save_allocated_range(mfd, &br);
975 22 : br.start = blk;
976 22 : br.len = 1;
977 : }
978 120 : report_progress(blk, 0);
979 : }
980 45111 : if (br.start != 0)
981 35 : save_allocated_range(mfd, &br);
982 : }
983 574 : free(ibuf);
984 574 : }
985 :
986 574 : static char *rgrp_read(struct lgfs2_sbd *sdp, uint64_t addr, unsigned blocks)
987 : {
988 574 : size_t len = blocks * sdp->sd_bsize;
989 574 : off_t off = addr * sdp->sd_bsize;
990 : char *buf;
991 :
992 574 : if (blocks == 0 || lgfs2_check_range(sdp, addr))
993 0 : return NULL;
994 :
995 574 : buf = calloc(1, len);
996 574 : if (buf == NULL)
997 0 : return NULL;
998 :
999 574 : if (pread(sdp->device_fd, buf, len, off) != len) {
1000 0 : free(buf);
1001 0 : return NULL;
1002 : }
1003 574 : return buf;
1004 : }
1005 :
1006 574 : static void save_rgrp(struct lgfs2_sbd *sdp, struct metafd *mfd, struct lgfs2_rgrp_tree *rgd, int withcontents)
1007 : {
1008 574 : uint64_t addr = rgd->rt_addr;
1009 : char *buf;
1010 :
1011 574 : buf = rgrp_read(sdp, rgd->rt_addr, rgd->rt_length);
1012 574 : if (buf == NULL)
1013 0 : return;
1014 :
1015 45685 : for (unsigned i = 0; i < rgd->rt_length; i++)
1016 45111 : rgd->rt_bits[i].bi_data = buf + (i * sdp->sd_bsize);
1017 :
1018 574 : log_debug("RG at %"PRIu64" is %"PRIu32" long\n", addr, rgd->rt_length);
1019 : /* Save the rg and bitmaps */
1020 45685 : for (unsigned i = 0; i < rgd->rt_length; i++) {
1021 45111 : report_progress(rgd->rt_addr + i, 0);
1022 45111 : save_buf(mfd, buf + (i * sdp->sd_bsize), rgd->rt_addr + i, sdp->sd_bsize);
1023 : }
1024 : /* Save the other metadata: inodes, etc. if mode is not 'savergs' */
1025 574 : if (withcontents)
1026 574 : save_allocated(rgd, mfd);
1027 :
1028 574 : free(buf);
1029 45685 : for (unsigned i = 0; i < rgd->rt_length; i++)
1030 45111 : rgd->rt_bits[i].bi_data = NULL;
1031 : }
1032 :
1033 8 : static int save_header(struct metafd *mfd, uint64_t fsbytes)
1034 : {
1035 40 : struct savemeta_header smh = {
1036 8 : .sh_magic = cpu_to_be32(SAVEMETA_MAGIC),
1037 8 : .sh_format = cpu_to_be32(SAVEMETA_FORMAT),
1038 8 : .sh_time = cpu_to_be64(time(NULL)),
1039 8 : .sh_fs_bytes = cpu_to_be64(fsbytes)
1040 : };
1041 :
1042 8 : if (savemetawrite(mfd, (char *)(&smh), sizeof(smh)) != sizeof(smh))
1043 0 : return -1;
1044 8 : return 0;
1045 : }
1046 :
1047 6 : static int parse_header(char *buf, struct savemeta *sm)
1048 : {
1049 6 : struct savemeta_header *smh = (void *)buf;
1050 :
1051 6 : if (be32_to_cpu(smh->sh_magic) != SAVEMETA_MAGIC) {
1052 0 : printf("No valid file header found. Falling back to old format...\n");
1053 0 : return 1;
1054 : }
1055 6 : if (be32_to_cpu(smh->sh_format) > SAVEMETA_FORMAT) {
1056 0 : printf("This version of gfs2_edit is too old to restore this metadata format.\n");
1057 0 : return -1;
1058 : }
1059 6 : sm->sm_format = be32_to_cpu(smh->sh_format);
1060 6 : sm->sm_time = be64_to_cpu(smh->sh_time);
1061 6 : sm->sm_fs_bytes = be64_to_cpu(smh->sh_fs_bytes);
1062 6 : printf("Metadata saved at %s", ctime(&sm->sm_time)); /* ctime() adds \n */
1063 6 : printf("File system size %.2fGB\n", sm->sm_fs_bytes / ((float)(1 << 30)));
1064 6 : return 0;
1065 : }
1066 :
1067 8 : void savemeta(char *out_fn, int saveoption, int gziplevel)
1068 : {
1069 : struct metafd mfd;
1070 : struct osi_node *n;
1071 : uint64_t sb_addr;
1072 8 : int err = 0;
1073 : char *buf;
1074 :
1075 8 : sbd.md.journals = 1;
1076 :
1077 8 : mfd = savemetaopen(out_fn, gziplevel);
1078 :
1079 8 : blks_saved = 0;
1080 8 : printf("There are %"PRIu64" blocks of %u bytes in the filesystem.\n",
1081 : sbd.fssize, sbd.sd_bsize);
1082 :
1083 8 : printf("Filesystem size: %.2fGB\n", (sbd.fssize * sbd.sd_bsize) / ((float)(1 << 30)));
1084 8 : get_journal_inode_blocks();
1085 :
1086 8 : err = init_per_node_lookup();
1087 8 : if (err)
1088 0 : exit(1);
1089 :
1090 : /* Write the savemeta file header */
1091 8 : err = save_header(&mfd, sbd.fssize * sbd.sd_bsize);
1092 8 : if (err) {
1093 0 : perror("Failed to write metadata file header");
1094 0 : exit(1);
1095 : }
1096 : /* Save off the superblock */
1097 8 : sb_addr = GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sbd.sd_bsize;
1098 8 : buf = check_read_block(sbd.device_fd, sb_addr, 0, NULL, NULL);
1099 8 : if (buf != NULL) {
1100 8 : save_buf(&mfd, buf, sb_addr, sizeof(struct gfs2_sb));
1101 8 : free(buf);
1102 : }
1103 : /* Walk through the resource groups saving everything within */
1104 582 : for (n = osi_first(&sbd.rgtree); n; n = osi_next(n)) {
1105 : struct lgfs2_rgrp_tree *rgd;
1106 :
1107 574 : rgd = (struct lgfs2_rgrp_tree *)n;
1108 574 : save_rgrp(&sbd, &mfd, rgd, (saveoption != 2));
1109 : }
1110 : /* Clean up */
1111 : /* There may be a gap between end of file system and end of device */
1112 : /* so we tell the user that we've processed everything. */
1113 8 : report_progress(sbd.fssize, 1);
1114 8 : printf("\nMetadata saved to file %s ", mfd.filename);
1115 8 : if (mfd.gziplevel) {
1116 3 : printf("(gzipped, level %d).\n", mfd.gziplevel);
1117 : } else {
1118 5 : printf("(uncompressed).\n");
1119 : }
1120 8 : savemetaclose(&mfd);
1121 8 : close(sbd.device_fd);
1122 8 : destroy_per_node_lookup();
1123 8 : free(indirect);
1124 8 : lgfs2_rgrp_free(&sbd, &sbd.rgtree);
1125 8 : exit(0);
1126 : }
1127 :
1128 230479 : static char *restore_block(struct metafd *mfd, uint64_t *blk, uint16_t *siglen)
1129 : {
1130 : struct saved_metablock *svb;
1131 : const char *errstr;
1132 230479 : char *buf = NULL;
1133 :
1134 230479 : svb = (struct saved_metablock *)(restore_buf_next(mfd, sizeof(*svb)));
1135 230479 : if (svb == NULL)
1136 6 : goto nobuffer;
1137 230473 : *blk = be64_to_cpu(svb->blk);
1138 230473 : *siglen = be16_to_cpu(svb->siglen);
1139 :
1140 230473 : if (sbd.fssize && *blk >= sbd.fssize) {
1141 0 : fprintf(stderr, "Error: File system is too small to restore this metadata.\n");
1142 0 : fprintf(stderr, "File system is %"PRIu64" blocks. Restore block = %"PRIu64"\n",
1143 : sbd.fssize, *blk);
1144 0 : return NULL;
1145 : }
1146 :
1147 230473 : if (*siglen > sbd.sd_bsize) {
1148 0 : fprintf(stderr, "Bad record length: %u for block %"PRIu64" (0x%"PRIx64").\n",
1149 0 : *siglen, *blk, *blk);
1150 0 : return NULL;
1151 : }
1152 :
1153 230473 : buf = restore_buf_next(mfd, *siglen);
1154 230473 : if (buf != NULL) {
1155 230473 : return buf;
1156 : }
1157 0 : nobuffer:
1158 6 : if (mfd->eof)
1159 6 : return NULL;
1160 :
1161 0 : errstr = mfd->strerr(mfd);
1162 0 : fprintf(stderr, "Failed to restore block: %s\n", errstr);
1163 0 : return NULL;
1164 : }
1165 :
1166 6 : static int restore_super(struct metafd *mfd, void *buf, int printonly)
1167 : {
1168 : int ret;
1169 :
1170 6 : lgfs2_sb_in(&sbd, buf);
1171 6 : ret = lgfs2_check_sb(buf);
1172 6 : if (ret < 0) {
1173 0 : fprintf(stderr, "Error: Invalid superblock in metadata file.\n");
1174 0 : return -1;
1175 : }
1176 6 : if ((!printonly) && lgfs2_sb_write(&sbd, sbd.device_fd)) {
1177 0 : fprintf(stderr, "Failed to write superblock\n");
1178 0 : return -1;
1179 : }
1180 6 : blks_saved++;
1181 6 : return 0;
1182 : }
1183 :
1184 6 : static int restore_data(int fd, struct metafd *mfd, int printonly)
1185 : {
1186 6 : uint64_t writes = 0;
1187 : char *buf;
1188 :
1189 6 : buf = calloc(1, sbd.sd_bsize);
1190 6 : if (buf == NULL) {
1191 0 : perror("Failed to restore data");
1192 0 : exit(1);
1193 : }
1194 :
1195 230473 : while (TRUE) {
1196 230479 : uint16_t siglen = 0;
1197 230479 : uint64_t blk = 0;
1198 : char *bp;
1199 :
1200 230479 : bp = restore_block(mfd, &blk, &siglen);
1201 230479 : if (bp == NULL && mfd->eof)
1202 6 : break;
1203 230473 : if (bp == NULL) {
1204 0 : free(buf);
1205 0 : return -1;
1206 : }
1207 230473 : if (printonly) {
1208 0 : if (printonly > 1 && printonly == blk) {
1209 0 : display_block_type(bp, blk, TRUE);
1210 0 : display_gfs2(bp);
1211 0 : break;
1212 0 : } else if (printonly == 1) {
1213 0 : print_gfs2("%"PRId64" (l=0x%x): ", blks_saved, siglen);
1214 0 : display_block_type(bp, blk, TRUE);
1215 : }
1216 : } else {
1217 230473 : report_progress(blk, 0);
1218 230473 : memcpy(buf, bp, siglen);
1219 230473 : memset(buf + siglen, 0, sbd.sd_bsize - siglen);
1220 230473 : if (pwrite(fd, buf, sbd.sd_bsize, blk * sbd.sd_bsize) != sbd.sd_bsize) {
1221 0 : fprintf(stderr, "write error: %s from %s:%d: block %"PRIu64" (0x%"PRIx64")\n",
1222 0 : strerror(errno), __FUNCTION__, __LINE__, blk, blk);
1223 0 : free(buf);
1224 0 : return -1;
1225 : }
1226 230473 : writes++;
1227 230473 : if (writes % 1000 == 0)
1228 226 : fsync(fd);
1229 : }
1230 230473 : blks_saved++;
1231 : }
1232 6 : if (!printonly)
1233 6 : report_progress(sbd.fssize, 1);
1234 6 : free(buf);
1235 6 : return 0;
1236 : }
1237 :
1238 0 : static void restoremeta_usage(void)
1239 : {
1240 0 : fprintf(stderr, "Usage:\n");
1241 0 : fprintf(stderr, "gfs2_edit restoremeta <metadata_file> <block_device>\n");
1242 0 : }
1243 :
1244 6 : static int restore_init(const char *path, struct metafd *mfd, struct savemeta *sm, int printonly)
1245 : {
1246 : struct gfs2_sb rsb;
1247 : uint16_t sb_siglen;
1248 : char *end;
1249 : char *bp;
1250 : int ret;
1251 :
1252 6 : blks_saved = 0;
1253 6 : restore_buf = malloc(RESTORE_BUF_SIZE);
1254 6 : if (restore_buf == NULL) {
1255 0 : perror("Restore failed");
1256 0 : return -1;
1257 : }
1258 6 : restore_off = 0;
1259 6 : restore_left = 0;
1260 :
1261 6 : mfd->filename = path;
1262 6 : mfd->fd = open(path, O_RDONLY|O_CLOEXEC);
1263 6 : if (mfd->fd < 0) {
1264 0 : perror("Could not open metadata file");
1265 0 : return 1;
1266 : }
1267 12 : if (restore_try_bzip(mfd) != 0 &&
1268 6 : restore_try_gzip(mfd) != 0) {
1269 0 : fprintf(stderr, "Failed to read metadata file header and superblock\n");
1270 0 : return -1;
1271 : }
1272 6 : bp = restore_buf;
1273 6 : ret = parse_header(bp, sm);
1274 6 : if (ret == 0) {
1275 6 : bp = restore_buf + sizeof(struct savemeta_header);
1276 6 : restore_off = sizeof(struct savemeta_header);
1277 0 : } else if (ret == -1) {
1278 0 : return -1;
1279 : }
1280 : /* Scan for the position of the superblock. Required to support old formats(?). */
1281 6 : end = &restore_buf[256 + sizeof(struct saved_metablock) + sizeof(struct gfs2_meta_header)];
1282 6 : while (bp <= end) {
1283 6 : memcpy(&rsb, bp + sizeof(struct saved_metablock), sizeof(rsb));
1284 6 : sb_siglen = be16_to_cpu(((struct saved_metablock *)bp)->siglen);
1285 12 : if (be32_to_cpu(rsb.sb_header.mh_magic) == GFS2_MAGIC &&
1286 6 : be32_to_cpu(rsb.sb_header.mh_type) == GFS2_METATYPE_SB)
1287 6 : break;
1288 0 : bp++;
1289 : }
1290 6 : if (bp > end) {
1291 0 : fprintf(stderr, "No superblock found in metadata file\n");
1292 0 : return -1;
1293 : }
1294 6 : bp += sizeof(struct saved_metablock);
1295 6 : ret = restore_super(mfd, &rsb, printonly);
1296 6 : if (ret != 0)
1297 0 : return ret;
1298 :
1299 6 : if (sm->sm_fs_bytes > 0) {
1300 6 : sbd.fssize = sm->sm_fs_bytes / sbd.sd_bsize;
1301 6 : printf("Saved file system size is %"PRIu64" blocks, %.2fGB\n",
1302 6 : sbd.fssize, sm->sm_fs_bytes / ((float)(1 << 30)));
1303 : }
1304 6 : printf("Block size is %uB\n", sbd.sd_bsize);
1305 6 : printf("This is gfs2 metadata.\n");
1306 6 : if (printonly > 1 && printonly == LGFS2_SB_ADDR(&sbd)) {
1307 0 : display_block_type(bp, LGFS2_SB_ADDR(&sbd), TRUE);
1308 0 : display_gfs2(bp);
1309 6 : } else if (printonly == 1) {
1310 0 : print_gfs2("0 (l=0x%x): ", sb_siglen);
1311 0 : display_block_type(bp, LGFS2_SB_ADDR(&sbd), TRUE);
1312 : }
1313 6 : bp += sb_siglen;
1314 6 : restore_off = bp - restore_buf;
1315 6 : restore_left -= restore_off;
1316 6 : return 0;
1317 : }
1318 :
1319 6 : void restoremeta(const char *in_fn, const char *out_device, uint64_t printonly)
1320 : {
1321 6 : struct metafd mfd = {0};
1322 6 : struct savemeta sm = {0};
1323 : struct stat st;
1324 : int error;
1325 :
1326 6 : termlines = 0;
1327 6 : if (in_fn == NULL || in_fn[0] == '\0') {
1328 0 : fprintf(stderr, "No source file specified.");
1329 0 : restoremeta_usage();
1330 0 : exit(1);
1331 : }
1332 6 : if (!printonly && (out_device == NULL || out_device[0] == '\0')) {
1333 0 : fprintf(stderr, "No destination file system specified.");
1334 0 : restoremeta_usage();
1335 0 : exit(1);
1336 : }
1337 6 : if (!printonly) {
1338 6 : sbd.device_fd = open(out_device, O_RDWR);
1339 6 : if (sbd.device_fd < 0) {
1340 0 : fprintf(stderr, "Failed to open target '%s': %s\n",
1341 0 : out_device, strerror(errno));
1342 0 : exit(1);
1343 : }
1344 0 : } else if (out_device) /* for printsavedmeta, the out_device is an
1345 : optional block no */
1346 0 : printonly = check_keywords(out_device);
1347 :
1348 6 : error = restore_init(in_fn, &mfd, &sm, printonly);
1349 6 : if (error != 0)
1350 0 : exit(error);
1351 :
1352 6 : if (!printonly) {
1353 6 : uint64_t space = lseek(sbd.device_fd, 0, SEEK_END) / sbd.sd_bsize;
1354 6 : printf("There are %"PRIu64" free blocks on the destination device.\n", space);
1355 : }
1356 :
1357 6 : error = restore_data(sbd.device_fd, &mfd, printonly);
1358 :
1359 : /* When there is a metadata header available, truncate to filesystem
1360 : size if our device_fd is a regular file */
1361 6 : if (!printonly) {
1362 6 : if (fstat(sbd.device_fd, &st) == -1) {
1363 0 : fprintf(stderr, "Failed to stat %s: %s\n", out_device, strerror(errno));
1364 0 : error = errno;
1365 : }
1366 :
1367 6 : if (sm.sm_fs_bytes > 0 && S_ISREG(st.st_mode)) {
1368 6 : if (ftruncate(sbd.device_fd, sm.sm_fs_bytes) != 0) {
1369 0 : fprintf(stderr, "Failed to truncate: %s, %s\n", out_device, strerror(errno));
1370 0 : error = errno;
1371 : }
1372 : }
1373 : }
1374 :
1375 6 : printf("File %s %s %s.\n", in_fn,
1376 : (printonly ? "print" : "restore"),
1377 : (error ? "error" : "successful"));
1378 :
1379 6 : mfd.close(&mfd);
1380 6 : if (!printonly)
1381 6 : close(sbd.device_fd);
1382 6 : free(indirect);
1383 6 : exit(error);
1384 : }
|