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 393939 : static char *restore_buf_next(struct metafd *mfd, size_t required_len)
75 : {
76 393939 : if (restore_left < required_len) {
77 10 : char *tail = restore_buf + restore_off;
78 : int ret;
79 :
80 10 : memmove(restore_buf, tail, restore_left);
81 10 : ret = mfd->read(mfd, restore_buf + restore_left, RESTORE_BUF_SIZE - restore_left);
82 10 : if (ret < (int)required_len - restore_left)
83 5 : return NULL;
84 5 : restore_left += ret;
85 5 : restore_off = 0;
86 : }
87 393934 : restore_left -= required_len;
88 393934 : restore_off += required_len;
89 393934 : 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 15 : static int gz_read(struct metafd *mfd, void *buf, unsigned len)
105 : {
106 15 : int ret = gzread(mfd->gzfd, buf, len);
107 15 : if (ret < len && gzeof(mfd->gzfd))
108 10 : mfd->eof = 1;
109 15 : return ret;
110 : }
111 :
112 5 : static void gz_close(struct metafd *mfd)
113 : {
114 5 : gzclose(mfd->gzfd);
115 5 : }
116 :
117 : /* This should be tried last because gzip doesn't distinguish between
118 : decompressing a gzip file and reading an uncompressed file */
119 5 : static int restore_try_gzip(struct metafd *mfd)
120 : {
121 5 : mfd->read = gz_read;
122 5 : mfd->close = gz_close;
123 5 : mfd->strerr = gz_strerr;
124 5 : lseek(mfd->fd, 0, SEEK_SET);
125 5 : mfd->gzfd = gzdopen(mfd->fd, "rb");
126 5 : if (!mfd->gzfd)
127 0 : return 1;
128 5 : gzbuffer(mfd->gzfd, (1<<20)); /* Increase zlib's buffers to 1MB */
129 5 : restore_left = mfd->read(mfd, restore_buf, RESTORE_BUF_SIZE);
130 5 : if (restore_left < 512)
131 0 : return -1;
132 5 : 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 5 : static int bz_read(struct metafd *mfd, void *buf, unsigned len)
148 : {
149 5 : int bzerr = BZ_OK;
150 : int ret;
151 :
152 5 : ret = BZ2_bzRead(&bzerr, mfd->bzfd, buf, len);
153 5 : if (bzerr == BZ_OK)
154 0 : return ret;
155 5 : if (bzerr == BZ_STREAM_END) {
156 0 : mfd->eof = 1;
157 0 : return ret;
158 : }
159 5 : return -1;
160 : }
161 :
162 0 : static void bz_close(struct metafd *mfd)
163 : {
164 0 : BZ2_bzclose(mfd->bzfd);
165 0 : }
166 :
167 5 : static int restore_try_bzip(struct metafd *mfd)
168 : {
169 : int bzerr;
170 : FILE *f;
171 :
172 5 : f = fdopen(mfd->fd, "r");
173 5 : if (f == NULL)
174 0 : return 1;
175 :
176 5 : mfd->read = bz_read;
177 5 : mfd->close = bz_close;
178 5 : mfd->strerr = bz_strerr;
179 5 : mfd->bzfd = BZ2_bzReadOpen(&bzerr, f, 0, 0, NULL, 0);
180 5 : if (!mfd->bzfd)
181 0 : return 1;
182 5 : restore_left = mfd->read(mfd, restore_buf, RESTORE_BUF_SIZE);
183 5 : if (restore_left < 512)
184 5 : 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 26 : static int block_is_a_journal(uint64_t blk)
194 : {
195 : int j;
196 :
197 182 : for (j = 0; j < journals_found; j++)
198 156 : if (blk == journal_blocks[j])
199 0 : return TRUE;
200 26 : 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 7 : static void destroy_per_node_lookup(void)
210 : {
211 : struct osi_node *n;
212 : struct per_node_node *pnp;
213 :
214 21 : 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 7 : }
220 :
221 26 : static int block_is_in_per_node(uint64_t blk)
222 : {
223 26 : struct per_node_node *pnp = (struct per_node_node *)per_node_tree.osi_node;
224 :
225 43 : 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 18 : 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 7 : static int init_per_node_lookup(void)
266 : {
267 : int i;
268 : struct lgfs2_inode *per_node_di;
269 :
270 7 : per_node_di = lgfs2_inode_read(&sbd, masterblock("per_node"));
271 7 : 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 7 : do_dinode_extended(per_node_di->i_bh->b_data);
277 7 : lgfs2_inode_put(&per_node_di);
278 :
279 10 : 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 7 : return 0;
288 : }
289 :
290 87 : static int block_is_systemfile(uint64_t blk)
291 : {
292 167 : return block_is_inum_file(blk) ||
293 153 : block_is_statfs_file(blk) ||
294 139 : block_is_quota_file(blk) ||
295 92 : block_is_rindex(blk) ||
296 52 : block_is_a_journal(blk) ||
297 193 : block_is_per_node(blk) ||
298 26 : block_is_in_per_node(blk);
299 : }
300 :
301 108 : 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 108 : dn = (void *)buf;
308 108 : di_mode = be32_to_cpu(dn->di_mode);
309 108 : 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 155 : if (di_height > 0 || S_ISDIR(di_mode) || S_ISLNK(di_mode) ||
314 47 : block_is_systemfile(owner))
315 90 : return sbd.sd_bsize;
316 18 : 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 219278 : static int get_struct_info(const char *buf, uint64_t owner, unsigned *block_type,
331 : unsigned *gstruct_len)
332 : {
333 219278 : struct gfs2_meta_header *mh = (struct gfs2_meta_header *)buf;
334 :
335 219278 : if (block_type != NULL)
336 219278 : *block_type = 0;
337 :
338 219278 : if (gstruct_len != NULL)
339 219278 : *gstruct_len = sbd.sd_bsize;
340 :
341 219278 : if (be32_to_cpu(mh->mh_magic) != GFS2_MAGIC)
342 40 : return -1;
343 :
344 219238 : if (block_type != NULL)
345 219238 : *block_type = be32_to_cpu(mh->mh_type);
346 :
347 219238 : if (gstruct_len == NULL)
348 0 : return 0;
349 :
350 219238 : switch (be32_to_cpu(mh->mh_type)) {
351 7 : case GFS2_METATYPE_SB: /* 1 (superblock) */
352 7 : *gstruct_len = sizeof(struct gfs2_sb);
353 7 : 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 108 : case GFS2_METATYPE_DI: /* 4 (disk inode) */
361 108 : *gstruct_len = di_save_len(buf, owner);
362 108 : break;
363 2029 : case GFS2_METATYPE_IN: /* 5 (indir inode blklst) */
364 2029 : *gstruct_len = sbd.sd_bsize; /*sizeof(struct gfs_indirect);*/
365 2029 : 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 204800 : case GFS2_METATYPE_LH: /* 8 (log header) */
373 204800 : *gstruct_len = sizeof(struct gfs2_log_header);
374 204800 : 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 12288 : default:
385 12288 : *gstruct_len = sbd.sd_bsize;
386 12288 : break;
387 : }
388 219238 : 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 242007 : static void report_progress(uint64_t pblock, int force)
398 : {
399 : static struct timeval tv;
400 : static uint32_t seconds = 0;
401 :
402 242007 : gettimeofday(&tv, NULL);
403 242007 : if (!seconds)
404 12 : seconds = tv.tv_sec;
405 242007 : if (force || tv.tv_sec - seconds) {
406 : static uint64_t percent;
407 :
408 17 : seconds = tv.tv_sec;
409 17 : if (sbd.fssize) {
410 17 : printf("\r");
411 17 : percent = (pblock * 100) / sbd.fssize;
412 17 : printf("%"PRIu64" blocks saved (%"PRIu64"%% complete)",
413 : blks_saved, percent);
414 17 : if (force)
415 12 : printf("\n");
416 17 : fflush(stdout);
417 : }
418 : }
419 242007 : }
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 7 : static struct metafd savemetaopen(char *out_fn, int gziplevel)
429 : {
430 7 : struct metafd mfd = {0};
431 7 : char gzmode[3] = "w9";
432 7 : char dft_fn[] = DFT_SAVE_FILE;
433 7 : mode_t mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
434 : struct stat st;
435 :
436 7 : mfd.gziplevel = gziplevel;
437 :
438 7 : if (!out_fn) {
439 0 : out_fn = dft_fn;
440 0 : mfd.fd = mkstemp(out_fn);
441 : } else {
442 7 : mfd.fd = open(out_fn, O_RDWR | O_CREAT, 0644);
443 : }
444 7 : umask(mask);
445 7 : mfd.filename = out_fn;
446 :
447 7 : if (mfd.fd < 0) {
448 0 : fprintf(stderr, "Can't open %s: %s\n", out_fn, strerror(errno));
449 0 : exit(1);
450 : }
451 7 : 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 7 : 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 7 : if (gziplevel > 0) {
461 2 : gzmode[1] = '0' + gziplevel;
462 2 : mfd.gzfd = gzdopen(mfd.fd, gzmode);
463 2 : if (!mfd.gzfd) {
464 0 : fprintf(stderr, "gzdopen error: %s\n", strerror(errno));
465 0 : exit(1);
466 : }
467 2 : gzbuffer(mfd.gzfd, (1<<20)); /* Increase zlib's buffers to 1MB */
468 : }
469 :
470 7 : 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 263993 : 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 263993 : if (mfd->gziplevel == 0) {
487 213595 : return write(mfd->fd, buf, nbyte);
488 : }
489 :
490 50398 : ret = gzwrite(mfd->gzfd, buf, nbyte);
491 50398 : 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 50398 : 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 7 : static int savemetaclose(struct metafd *mfd)
506 : {
507 : int gzret;
508 7 : if (mfd->gziplevel > 0) {
509 2 : gzret = gzclose(mfd->gzfd);
510 2 : if (gzret == Z_STREAM_ERROR) {
511 0 : fprintf(stderr, "gzclose: file is not valid\n");
512 0 : return -1;
513 2 : } else if (gzret == Z_ERRNO) {
514 0 : return -1;
515 : }
516 : }
517 7 : return close(mfd->fd);
518 : }
519 :
520 263986 : 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 263986 : if (mfd->gziplevel == 0)
528 43150243 : for (; blklen > 0 && buf[blklen - 1] == '\0'; blklen--);
529 :
530 263986 : if (blklen == 0) /* No significant data; skip. */
531 0 : return 0;
532 :
533 263986 : outsz = sizeof(*savedata) + blklen;
534 263986 : savedata = calloc(1, outsz);
535 263986 : if (savedata == NULL) {
536 0 : perror("Failed to save block");
537 0 : exit(1);
538 : }
539 263986 : savedata->blk = cpu_to_be64(addr);
540 263986 : savedata->siglen = cpu_to_be16(blklen);
541 263986 : memcpy(savedata + 1, buf, blklen);
542 :
543 263986 : 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 263986 : blks_saved++;
550 263986 : free(savedata);
551 263986 : 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 2293 : static int block_range_prepare(struct block_range *br)
564 : {
565 2293 : br->buf = calloc(br->len, sbd.sd_bsize + sizeof(*br->blktype) + sizeof(*br->blklen));
566 2293 : if (br->buf == NULL) {
567 0 : perror("Failed to allocate block range buffer");
568 0 : return 1;
569 : }
570 2293 : br->blktype = (unsigned *)(br->buf + (br->len * sbd.sd_bsize));
571 2293 : br->blklen = br->blktype + br->len;
572 2293 : return 0;
573 : }
574 :
575 2293 : static int block_range_check(struct block_range *br)
576 : {
577 2293 : if (br->start >= LGFS2_SB_ADDR(&sbd) && br->start + br->len <= sbd.fssize)
578 2293 : 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 2293 : static void block_range_setinfo(struct block_range *br, uint64_t owner)
588 : {
589 221571 : for (unsigned i = 0; i < br->len; i++) {
590 219278 : char *buf = br->buf + (i * sbd.sd_bsize);
591 219278 : uint64_t addr = br->start + i;
592 219278 : uint64_t _owner = (owner == 0) ? addr : owner;
593 :
594 219318 : if (get_struct_info(buf, _owner, br->blktype + i, br->blklen + i) &&
595 40 : !block_is_systemfile(_owner)) {
596 0 : br->blklen[i] = 0;
597 : }
598 : }
599 2293 : }
600 :
601 212 : static void block_range_free(struct block_range **brp)
602 : {
603 212 : free((*brp)->buf);
604 212 : free(*brp);
605 212 : *brp = NULL;
606 212 : }
607 :
608 : struct block_range_queue {
609 : struct block_range *tail;
610 : struct block_range **head;
611 : };
612 :
613 1080 : static void block_range_queue_init(struct block_range_queue *q)
614 : {
615 1080 : q->head = &q->tail;
616 1080 : }
617 :
618 212 : static void block_range_queue_insert(struct block_range_queue *q, struct block_range *br)
619 : {
620 212 : *q->head = br;
621 212 : q->head = &br->next;
622 212 : }
623 :
624 212 : static struct block_range *block_range_queue_pop(struct block_range_queue *q)
625 : {
626 212 : struct block_range *br = q->tail;
627 :
628 212 : q->tail = br->next;
629 212 : br->next = NULL;
630 212 : return br;
631 : }
632 :
633 2286 : static int save_range(struct metafd *mfd, struct block_range *br)
634 : {
635 221557 : for (unsigned i = 0; i < br->len; i++) {
636 : int err;
637 :
638 219271 : err = save_buf(mfd, br->buf + (i * sbd.sd_bsize), br->start + i, br->blklen[i]);
639 219271 : if (err != 0)
640 0 : return err;
641 : }
642 2286 : return 0;
643 : }
644 :
645 2293 : static int check_read_range(int fd, struct block_range *br, uint64_t owner)
646 : {
647 : size_t size;
648 :
649 2293 : if (block_range_prepare(br) != 0)
650 0 : return 1;
651 :
652 2293 : if (block_range_check(br) != 0)
653 0 : return 1;
654 :
655 2293 : size = br->len * sbd.sd_bsize;
656 2293 : 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 2293 : block_range_setinfo(br, owner);
664 2293 : return 0;
665 : }
666 :
667 7 : static char *check_read_block(int fd, uint64_t blk, uint64_t owner, int *blktype, size_t *blklen)
668 : {
669 7 : struct block_range br = {
670 : .start = blk,
671 : .len = 1
672 : };
673 :
674 7 : if (check_read_range(fd, &br, owner) != 0)
675 0 : return NULL;
676 7 : if (blklen != NULL)
677 0 : *blklen = *br.blklen;
678 7 : if (blktype != NULL)
679 0 : *blktype = *br.blktype;
680 7 : 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 2234 : static void save_indirect_range(struct metafd *mfd, struct block_range **brp, uint64_t owner,
722 : struct block_range_queue *q)
723 : {
724 2234 : struct block_range *br = *brp;
725 :
726 2234 : if (check_read_range(sbd.device_fd, br, owner) != 0)
727 0 : return;
728 :
729 2234 : save_range(mfd, br);
730 221397 : for (unsigned i = 0; i < br->len; i++) {
731 219163 : if (br->blktype[i] == GFS2_METATYPE_EA)
732 0 : save_ea_block(mfd, br->buf + (i * sbd.sd_bsize), owner);
733 : }
734 2234 : if (q) {
735 212 : block_range_queue_insert(q, br);
736 212 : *brp = NULL; /* The list now has ownership of it */
737 : } else {
738 2022 : free(br->buf);
739 2022 : br->buf = NULL;
740 : }
741 : }
742 :
743 2066 : static void save_indirect_blocks(struct metafd *mfd, char *buf, uint64_t owner,
744 : struct block_range_queue *q, unsigned headsize)
745 : {
746 2066 : uint64_t old_block = 0, indir_block;
747 2066 : struct block_range *br = NULL;
748 : __be64 *ptr;
749 :
750 2066 : for (ptr = (__be64 *)(buf + headsize);
751 233306 : (char *)ptr < (buf + sbd.sd_bsize); ptr++) {
752 231240 : if (!*ptr)
753 11955 : continue;
754 :
755 219285 : indir_block = be64_to_cpu(*ptr);
756 219285 : if (indir_block == old_block)
757 122 : continue;
758 219163 : old_block = indir_block;
759 :
760 219163 : if (br == NULL) {
761 2066 : new_range:
762 2231 : br = calloc(1, sizeof(*br));
763 2231 : if (br == NULL) {
764 0 : perror("Failed to save indirect blocks");
765 0 : return;
766 : }
767 2231 : br->start = indir_block;
768 2231 : br->len = 1;
769 217097 : } else if (indir_block == br->start + br->len) {
770 216929 : 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 2066 : if (br != NULL && br->start != 0)
780 2066 : save_indirect_range(mfd, &br, owner, q);
781 2066 : 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 108 : static void save_inode_data(struct metafd *mfd, char *ibuf, uint64_t iblk)
844 : {
845 108 : struct block_range_queue indq[GFS2_MAX_META_HEIGHT] = {{NULL}};
846 108 : struct gfs2_dinode *dip = (struct gfs2_dinode *)ibuf;
847 : uint16_t height;
848 : int is_exhash;
849 :
850 1188 : for (unsigned i = 0; i < GFS2_MAX_META_HEIGHT; i++)
851 1080 : block_range_queue_init(&indq[i]);
852 :
853 108 : 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 136 : is_exhash = S_ISDIR(be32_to_cpu(dip->di_mode)) &&
862 28 : be32_to_cpu(dip->di_flags) & GFS2_DIF_EXHASH;
863 108 : if (is_exhash)
864 4 : height++;
865 104 : 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 108 : if (height == 1)
870 19 : save_indirect_blocks(mfd, ibuf, iblk, NULL, sizeof(*dip));
871 89 : else if (height > 1)
872 18 : save_indirect_blocks(mfd, ibuf, iblk, &indq[0], sizeof(*dip));
873 :
874 131 : for (unsigned i = 1; i < height; i++) {
875 23 : struct block_range_queue *nextq = &indq[i];
876 :
877 23 : if (!is_exhash && i == height - 1)
878 18 : nextq = NULL;
879 :
880 : /* Coverity can't figure out that the tail becomes NULL eventually. */
881 : /* coverity[loop_top:SUPPRESS] */
882 235 : while (indq[i - 1].tail != NULL) {
883 212 : struct block_range *q = block_range_queue_pop(&indq[i - 1]);
884 :
885 2241 : for (unsigned j = 0; j < q->len; j++) {
886 2029 : char *_buf = q->buf + (j * sbd.sd_bsize);
887 :
888 2029 : save_indirect_blocks(mfd, _buf, iblk, nextq, sizeof(dip->di_header));
889 : }
890 212 : report_progress(q->start + q->len, 0);
891 212 : block_range_free(&q);
892 : }
893 : }
894 108 : if (is_exhash)
895 4 : save_leaf_blocks(mfd, &indq[height - 1]);
896 108 : 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 108 : }
914 :
915 7 : static void get_journal_inode_blocks(void)
916 : {
917 : int journal;
918 :
919 7 : journals_found = 0;
920 7 : 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 7 : for (journal = 0; ; journal++) { /* while journals exist */
931 : uint64_t jblock;
932 :
933 49 : if (journal + 3 > indirect->ii[0].dirents)
934 7 : break;
935 42 : jblock = indirect->ii[0].dirent[journal + 2].inum.in_addr;
936 42 : journal_blocks[journals_found++] = jblock;
937 : }
938 7 : }
939 :
940 52 : static void save_allocated_range(struct metafd *mfd, struct block_range *br)
941 : {
942 52 : if (check_read_range(sbd.device_fd, br, 0) != 0)
943 0 : return;
944 :
945 52 : save_range(mfd, br);
946 160 : for (unsigned i = 0; i < br->len; i++) {
947 108 : char *buf = br->buf + (i * sbd.sd_bsize);
948 :
949 108 : if (br->blktype[i] == GFS2_METATYPE_DI)
950 108 : save_inode_data(mfd, buf, br->start + i);
951 : }
952 52 : free(br->buf);
953 : }
954 :
955 493 : static void save_allocated(struct lgfs2_rgrp_tree *rgd, struct metafd *mfd)
956 : {
957 493 : uint64_t blk = 0;
958 : unsigned i, j, m;
959 493 : uint64_t *ibuf = malloc(sbd.sd_bsize * GFS2_NBBY * sizeof(uint64_t));
960 :
961 45201 : for (i = 0; i < rgd->rt_length; i++) {
962 44708 : struct block_range br = {0};
963 :
964 44708 : m = lgfs2_bm_scan(rgd, i, ibuf, GFS2_BLKST_DINODE);
965 :
966 44816 : for (j = 0; j < m; j++) {
967 108 : blk = ibuf[j];
968 108 : if (br.start == 0) {
969 32 : br.start = blk;
970 32 : br.len = 1;
971 76 : } else if (blk == br.start + br.len) {
972 56 : br.len++;
973 : } else {
974 20 : save_allocated_range(mfd, &br);
975 20 : br.start = blk;
976 20 : br.len = 1;
977 : }
978 108 : report_progress(blk, 0);
979 : }
980 44708 : if (br.start != 0)
981 32 : save_allocated_range(mfd, &br);
982 : }
983 493 : free(ibuf);
984 493 : }
985 :
986 493 : static char *rgrp_read(struct lgfs2_sbd *sdp, uint64_t addr, unsigned blocks)
987 : {
988 493 : size_t len = blocks * sdp->sd_bsize;
989 493 : off_t off = addr * sdp->sd_bsize;
990 : char *buf;
991 :
992 493 : if (blocks == 0 || lgfs2_check_range(sdp, addr))
993 0 : return NULL;
994 :
995 493 : buf = calloc(1, len);
996 493 : if (buf == NULL)
997 0 : return NULL;
998 :
999 493 : if (pread(sdp->device_fd, buf, len, off) != len) {
1000 0 : free(buf);
1001 0 : return NULL;
1002 : }
1003 493 : return buf;
1004 : }
1005 :
1006 493 : static void save_rgrp(struct lgfs2_sbd *sdp, struct metafd *mfd, struct lgfs2_rgrp_tree *rgd, int withcontents)
1007 : {
1008 493 : uint64_t addr = rgd->rt_addr;
1009 : char *buf;
1010 :
1011 493 : buf = rgrp_read(sdp, rgd->rt_addr, rgd->rt_length);
1012 493 : if (buf == NULL)
1013 0 : return;
1014 :
1015 45201 : for (unsigned i = 0; i < rgd->rt_length; i++)
1016 44708 : rgd->rt_bits[i].bi_data = buf + (i * sdp->sd_bsize);
1017 :
1018 493 : log_debug("RG at %"PRIu64" is %"PRIu32" long\n", addr, rgd->rt_length);
1019 : /* Save the rg and bitmaps */
1020 45201 : for (unsigned i = 0; i < rgd->rt_length; i++) {
1021 44708 : report_progress(rgd->rt_addr + i, 0);
1022 44708 : 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 493 : if (withcontents)
1026 493 : save_allocated(rgd, mfd);
1027 :
1028 493 : free(buf);
1029 45201 : for (unsigned i = 0; i < rgd->rt_length; i++)
1030 44708 : rgd->rt_bits[i].bi_data = NULL;
1031 : }
1032 :
1033 7 : static int save_header(struct metafd *mfd, uint64_t fsbytes)
1034 : {
1035 35 : struct savemeta_header smh = {
1036 7 : .sh_magic = cpu_to_be32(SAVEMETA_MAGIC),
1037 7 : .sh_format = cpu_to_be32(SAVEMETA_FORMAT),
1038 7 : .sh_time = cpu_to_be64(time(NULL)),
1039 7 : .sh_fs_bytes = cpu_to_be64(fsbytes)
1040 : };
1041 :
1042 7 : if (savemetawrite(mfd, (char *)(&smh), sizeof(smh)) != sizeof(smh))
1043 0 : return -1;
1044 7 : return 0;
1045 : }
1046 :
1047 5 : static int parse_header(char *buf, struct savemeta *sm)
1048 : {
1049 5 : struct savemeta_header *smh = (void *)buf;
1050 :
1051 5 : 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 5 : 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 5 : sm->sm_format = be32_to_cpu(smh->sh_format);
1060 5 : sm->sm_time = be64_to_cpu(smh->sh_time);
1061 5 : sm->sm_fs_bytes = be64_to_cpu(smh->sh_fs_bytes);
1062 5 : printf("Metadata saved at %s", ctime(&sm->sm_time)); /* ctime() adds \n */
1063 5 : printf("File system size %.2fGB\n", sm->sm_fs_bytes / ((float)(1 << 30)));
1064 5 : return 0;
1065 : }
1066 :
1067 7 : 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 7 : int err = 0;
1073 : char *buf;
1074 :
1075 7 : sbd.md.journals = 1;
1076 :
1077 7 : mfd = savemetaopen(out_fn, gziplevel);
1078 :
1079 7 : blks_saved = 0;
1080 7 : printf("There are %"PRIu64" blocks of %u bytes in the filesystem.\n",
1081 : sbd.fssize, sbd.sd_bsize);
1082 :
1083 7 : printf("Filesystem size: %.2fGB\n", (sbd.fssize * sbd.sd_bsize) / ((float)(1 << 30)));
1084 7 : get_journal_inode_blocks();
1085 :
1086 7 : err = init_per_node_lookup();
1087 7 : if (err)
1088 0 : exit(1);
1089 :
1090 : /* Write the savemeta file header */
1091 7 : err = save_header(&mfd, sbd.fssize * sbd.sd_bsize);
1092 7 : if (err) {
1093 0 : perror("Failed to write metadata file header");
1094 0 : exit(1);
1095 : }
1096 : /* Save off the superblock */
1097 7 : sb_addr = GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sbd.sd_bsize;
1098 7 : buf = check_read_block(sbd.device_fd, sb_addr, 0, NULL, NULL);
1099 7 : if (buf != NULL) {
1100 7 : save_buf(&mfd, buf, sb_addr, sizeof(struct gfs2_sb));
1101 7 : free(buf);
1102 : }
1103 : /* Walk through the resource groups saving everything within */
1104 500 : for (n = osi_first(&sbd.rgtree); n; n = osi_next(n)) {
1105 : struct lgfs2_rgrp_tree *rgd;
1106 :
1107 493 : rgd = (struct lgfs2_rgrp_tree *)n;
1108 493 : 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 7 : report_progress(sbd.fssize, 1);
1114 7 : printf("\nMetadata saved to file %s ", mfd.filename);
1115 7 : if (mfd.gziplevel) {
1116 2 : printf("(gzipped, level %d).\n", mfd.gziplevel);
1117 : } else {
1118 5 : printf("(uncompressed).\n");
1119 : }
1120 7 : savemetaclose(&mfd);
1121 7 : close(sbd.device_fd);
1122 7 : destroy_per_node_lookup();
1123 7 : free(indirect);
1124 7 : lgfs2_rgrp_free(&sbd, &sbd.rgtree);
1125 7 : exit(0);
1126 : }
1127 :
1128 196972 : static char *restore_block(struct metafd *mfd, uint64_t *blk, uint16_t *siglen)
1129 : {
1130 : struct saved_metablock *svb;
1131 : const char *errstr;
1132 196972 : char *buf = NULL;
1133 :
1134 196972 : svb = (struct saved_metablock *)(restore_buf_next(mfd, sizeof(*svb)));
1135 196972 : if (svb == NULL)
1136 5 : goto nobuffer;
1137 196967 : *blk = be64_to_cpu(svb->blk);
1138 196967 : *siglen = be16_to_cpu(svb->siglen);
1139 :
1140 196967 : 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 196967 : 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 196967 : buf = restore_buf_next(mfd, *siglen);
1154 196967 : if (buf != NULL) {
1155 196967 : return buf;
1156 : }
1157 0 : nobuffer:
1158 5 : if (mfd->eof)
1159 5 : 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 5 : static int restore_super(struct metafd *mfd, void *buf, int printonly)
1167 : {
1168 : int ret;
1169 :
1170 5 : lgfs2_sb_in(&sbd, buf);
1171 5 : ret = lgfs2_check_sb(buf);
1172 5 : if (ret < 0) {
1173 0 : fprintf(stderr, "Error: Invalid superblock in metadata file.\n");
1174 0 : return -1;
1175 : }
1176 5 : if ((!printonly) && lgfs2_sb_write(&sbd, sbd.device_fd)) {
1177 0 : fprintf(stderr, "Failed to write superblock\n");
1178 0 : return -1;
1179 : }
1180 5 : blks_saved++;
1181 5 : return 0;
1182 : }
1183 :
1184 5 : static int restore_data(int fd, struct metafd *mfd, int printonly)
1185 : {
1186 5 : uint64_t writes = 0;
1187 : char *buf;
1188 :
1189 5 : buf = calloc(1, sbd.sd_bsize);
1190 5 : if (buf == NULL) {
1191 0 : perror("Failed to restore data");
1192 0 : exit(1);
1193 : }
1194 :
1195 196967 : while (TRUE) {
1196 196972 : uint16_t siglen = 0;
1197 196972 : uint64_t blk = 0;
1198 : char *bp;
1199 :
1200 196972 : bp = restore_block(mfd, &blk, &siglen);
1201 196972 : if (bp == NULL && mfd->eof)
1202 5 : break;
1203 196967 : if (bp == NULL) {
1204 0 : free(buf);
1205 0 : return -1;
1206 : }
1207 196967 : 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 196967 : report_progress(blk, 0);
1218 196967 : memcpy(buf, bp, siglen);
1219 196967 : memset(buf + siglen, 0, sbd.sd_bsize - siglen);
1220 196967 : 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 196967 : writes++;
1227 196967 : if (writes % 1000 == 0)
1228 193 : fsync(fd);
1229 : }
1230 196967 : blks_saved++;
1231 : }
1232 5 : if (!printonly)
1233 5 : report_progress(sbd.fssize, 1);
1234 5 : free(buf);
1235 5 : 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 5 : static int restore_init(const char *path, struct metafd *mfd, int printonly)
1245 : {
1246 5 : struct savemeta sm = {0};
1247 : struct gfs2_sb rsb;
1248 : uint16_t sb_siglen;
1249 : char *end;
1250 : char *bp;
1251 : int ret;
1252 :
1253 5 : blks_saved = 0;
1254 5 : restore_buf = malloc(RESTORE_BUF_SIZE);
1255 5 : if (restore_buf == NULL) {
1256 0 : perror("Restore failed");
1257 0 : return -1;
1258 : }
1259 5 : restore_off = 0;
1260 5 : restore_left = 0;
1261 :
1262 5 : mfd->filename = path;
1263 5 : mfd->fd = open(path, O_RDONLY|O_CLOEXEC);
1264 5 : if (mfd->fd < 0) {
1265 0 : perror("Could not open metadata file");
1266 0 : return 1;
1267 : }
1268 10 : if (restore_try_bzip(mfd) != 0 &&
1269 5 : restore_try_gzip(mfd) != 0) {
1270 0 : fprintf(stderr, "Failed to read metadata file header and superblock\n");
1271 0 : return -1;
1272 : }
1273 5 : bp = restore_buf;
1274 5 : ret = parse_header(bp, &sm);
1275 5 : if (ret == 0) {
1276 5 : bp = restore_buf + sizeof(struct savemeta_header);
1277 5 : restore_off = sizeof(struct savemeta_header);
1278 0 : } else if (ret == -1) {
1279 0 : return -1;
1280 : }
1281 : /* Scan for the position of the superblock. Required to support old formats(?). */
1282 5 : end = &restore_buf[256 + sizeof(struct saved_metablock) + sizeof(struct gfs2_meta_header)];
1283 5 : while (bp <= end) {
1284 5 : memcpy(&rsb, bp + sizeof(struct saved_metablock), sizeof(rsb));
1285 5 : sb_siglen = be16_to_cpu(((struct saved_metablock *)bp)->siglen);
1286 10 : if (be32_to_cpu(rsb.sb_header.mh_magic) == GFS2_MAGIC &&
1287 5 : be32_to_cpu(rsb.sb_header.mh_type) == GFS2_METATYPE_SB)
1288 5 : break;
1289 0 : bp++;
1290 : }
1291 5 : if (bp > end) {
1292 0 : fprintf(stderr, "No superblock found in metadata file\n");
1293 0 : return -1;
1294 : }
1295 5 : bp += sizeof(struct saved_metablock);
1296 5 : ret = restore_super(mfd, &rsb, printonly);
1297 5 : if (ret != 0)
1298 0 : return ret;
1299 :
1300 5 : if (sm.sm_fs_bytes > 0) {
1301 5 : sbd.fssize = sm.sm_fs_bytes / sbd.sd_bsize;
1302 5 : printf("Saved file system size is %"PRIu64" blocks, %.2fGB\n",
1303 5 : sbd.fssize, sm.sm_fs_bytes / ((float)(1 << 30)));
1304 : }
1305 5 : printf("Block size is %uB\n", sbd.sd_bsize);
1306 5 : printf("This is gfs2 metadata.\n");
1307 5 : if (printonly > 1 && printonly == LGFS2_SB_ADDR(&sbd)) {
1308 0 : display_block_type(bp, LGFS2_SB_ADDR(&sbd), TRUE);
1309 0 : display_gfs2(bp);
1310 5 : } else if (printonly == 1) {
1311 0 : print_gfs2("0 (l=0x%x): ", sb_siglen);
1312 0 : display_block_type(bp, LGFS2_SB_ADDR(&sbd), TRUE);
1313 : }
1314 5 : bp += sb_siglen;
1315 5 : restore_off = bp - restore_buf;
1316 5 : restore_left -= restore_off;
1317 5 : return 0;
1318 : }
1319 :
1320 5 : void restoremeta(const char *in_fn, const char *out_device, uint64_t printonly)
1321 : {
1322 5 : struct metafd mfd = {0};
1323 : int error;
1324 :
1325 5 : termlines = 0;
1326 5 : if (in_fn == NULL || in_fn[0] == '\0') {
1327 0 : fprintf(stderr, "No source file specified.");
1328 0 : restoremeta_usage();
1329 0 : exit(1);
1330 : }
1331 5 : if (!printonly && (out_device == NULL || out_device[0] == '\0')) {
1332 0 : fprintf(stderr, "No destination file system specified.");
1333 0 : restoremeta_usage();
1334 0 : exit(1);
1335 : }
1336 5 : if (!printonly) {
1337 5 : sbd.device_fd = open(out_device, O_RDWR);
1338 5 : if (sbd.device_fd < 0) {
1339 0 : fprintf(stderr, "Failed to open target '%s': %s\n",
1340 0 : out_device, strerror(errno));
1341 0 : exit(1);
1342 : }
1343 0 : } else if (out_device) /* for printsavedmeta, the out_device is an
1344 : optional block no */
1345 0 : printonly = check_keywords(out_device);
1346 :
1347 5 : error = restore_init(in_fn, &mfd, printonly);
1348 5 : if (error != 0)
1349 0 : exit(error);
1350 :
1351 5 : if (!printonly) {
1352 5 : uint64_t space = lseek(sbd.device_fd, 0, SEEK_END) / sbd.sd_bsize;
1353 5 : printf("There are %"PRIu64" free blocks on the destination device.\n", space);
1354 : }
1355 :
1356 5 : error = restore_data(sbd.device_fd, &mfd, printonly);
1357 5 : printf("File %s %s %s.\n", in_fn,
1358 : (printonly ? "print" : "restore"),
1359 : (error ? "error" : "successful"));
1360 :
1361 5 : mfd.close(&mfd);
1362 5 : if (!printonly)
1363 5 : close(sbd.device_fd);
1364 5 : free(indirect);
1365 5 : exit(error);
1366 : }
|