]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/sb.c
xfsprogs: Release v6.7.0
[thirdparty/xfsprogs-dev.git] / repair / sb.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6 #include "libfrog/util.h"
7 #include "libxfs.h"
8 #include "libxcmd.h"
9 #include "libxlog.h"
10 #include "agheader.h"
11 #include "globals.h"
12 #include "protos.h"
13 #include "err_protos.h"
14 #include "xfs_multidisk.h"
15
16 #define BSIZE (1024 * 1024)
17
18 /*
19 * copy the fields of a superblock that are present in primary and
20 * secondaries -- preserve fields that are different in the primary.
21 */
22 static void
23 copy_sb(xfs_sb_t *source, xfs_sb_t *dest)
24 {
25 xfs_ino_t rootino;
26 xfs_ino_t rbmino;
27 xfs_ino_t rsumino;
28 xfs_ino_t uquotino;
29 xfs_ino_t gquotino;
30 xfs_ino_t pquotino;
31 uint16_t versionnum;
32
33 rootino = dest->sb_rootino;
34 rbmino = dest->sb_rbmino;
35 rsumino = dest->sb_rsumino;
36 uquotino = dest->sb_uquotino;
37 gquotino = dest->sb_gquotino;
38 pquotino = dest->sb_pquotino;
39
40 versionnum = dest->sb_versionnum;
41
42 *dest = *source;
43
44 dest->sb_rootino = rootino;
45 dest->sb_rbmino = rbmino;
46 dest->sb_rsumino = rsumino;
47 dest->sb_uquotino = uquotino;
48 dest->sb_gquotino = gquotino;
49 dest->sb_pquotino = pquotino;
50
51 dest->sb_versionnum = versionnum;
52
53 /*
54 * copy over version bits that are stamped into all
55 * secondaries and cannot be changed at run time in
56 * the primary superblock
57 */
58 if (xfs_sb_version_hasdalign(source))
59 dest->sb_versionnum |= XFS_SB_VERSION_DALIGNBIT;
60 dest->sb_versionnum |= XFS_SB_VERSION_EXTFLGBIT;
61
62 /*
63 * these are all supposed to be zero or will get reset anyway
64 */
65 dest->sb_icount = 0;
66 dest->sb_ifree = 0;
67 dest->sb_fdblocks = 0;
68 dest->sb_frextents = 0;
69
70 memset(source->sb_fname, 0, 12);
71 }
72
73 static int
74 verify_sb_blocksize(xfs_sb_t *sb)
75 {
76 /* check to make sure blocksize is legal 2^N, 9 <= N <= 16 */
77 if (sb->sb_blocksize == 0)
78 return XR_BAD_BLOCKSIZE;
79 if (sb->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG ||
80 sb->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG)
81 return XR_BAD_BLOCKLOG;
82 if (sb->sb_blocksize != (1 << sb->sb_blocklog))
83 return XR_BAD_BLOCKLOG;
84
85 return 0;
86 }
87
88 /*
89 * find a secondary superblock, copy it into the sb buffer.
90 * start is the point to begin reading BSIZE bytes.
91 * skip contains a byte-count of how far to advance for next read.
92 */
93 static int
94 __find_secondary_sb(
95 xfs_sb_t *rsb,
96 uint64_t start,
97 uint64_t skip)
98 {
99 xfs_off_t off;
100 xfs_sb_t *sb;
101 xfs_sb_t bufsb;
102 char *c_bufsb;
103 int done;
104 int i;
105 int dirty;
106 int retval;
107 int bsize;
108
109 sb = (xfs_sb_t *)memalign(libxfs_device_alignment(), BSIZE);
110 if (!sb) {
111 do_error(
112 _("error finding secondary superblock -- failed to memalign buffer\n"));
113 exit(1);
114 }
115
116 memset(&bufsb, 0, sizeof(xfs_sb_t));
117 retval = 0;
118 dirty = 0;
119 bsize = 0;
120
121 /*
122 * skip first sector since we know that's bad
123 */
124 for (done = 0, off = start; !done ; off += skip) {
125 /*
126 * read disk 1 MByte at a time.
127 */
128 if (lseek(x.data.fd, off, SEEK_SET) != off)
129 done = 1;
130
131 if (!done && (bsize = read(x.data.fd, sb, BSIZE)) <= 0)
132 done = 1;
133
134 do_warn(".");
135
136 /*
137 * check the buffer 512 bytes at a time since
138 * we don't know how big the sectors really are.
139 */
140 for (i = 0; !done && i < bsize; i += BBSIZE) {
141 c_bufsb = (char *)sb + i;
142 libxfs_sb_from_disk(&bufsb, (struct xfs_dsb *)c_bufsb);
143
144 if (verify_sb(c_bufsb, &bufsb, 0) != XR_OK)
145 continue;
146
147 do_warn(_("found candidate secondary superblock...\n"));
148
149 /*
150 * found one. now verify it by looking
151 * for other secondaries.
152 */
153 memmove(rsb, &bufsb, sizeof(xfs_sb_t));
154 rsb->sb_inprogress = 0;
155 copied_sunit = 1;
156
157 if (verify_set_primary_sb(rsb, 0, &dirty) == XR_OK) {
158 do_warn(
159 _("verified secondary superblock...\n"));
160 done = 1;
161 retval = 1;
162 } else {
163 do_warn(
164 _("unable to verify superblock, continuing...\n"));
165 }
166 }
167 }
168
169 free(sb);
170 return retval;
171 }
172
173 static int
174 guess_default_geometry(
175 uint64_t *agsize,
176 uint64_t *agcount,
177 struct libxfs_init *x)
178 {
179 struct fs_topology ft;
180 int blocklog;
181 uint64_t dblocks;
182 int multidisk;
183
184 memset(&ft, 0, sizeof(ft));
185 get_topology(x, &ft, 1);
186
187 /*
188 * get geometry from get_topology result.
189 * Use default block size (2^12)
190 */
191 blocklog = 12;
192 multidisk = ft.dswidth | ft.dsunit;
193 dblocks = x->data.size >> (blocklog - BBSHIFT);
194 calc_default_ag_geometry(blocklog, dblocks, multidisk,
195 agsize, agcount);
196
197 return blocklog;
198 }
199
200 int
201 find_secondary_sb(xfs_sb_t *rsb)
202 {
203 int retval = 0;
204 uint64_t agcount;
205 uint64_t agsize;
206 uint64_t skip;
207 int blocklog;
208
209 /*
210 * Attempt to find secondary sb with a coarse approach,
211 * first trying agblocks and blocksize read from sb, providing
212 * they're sane.
213 */
214 do_warn(_("\nattempting to find secondary superblock...\n"));
215
216 if (verify_sb_blocksize(rsb) == 0) {
217 skip = (uint64_t)rsb->sb_agblocks * rsb->sb_blocksize;
218 if (skip >= XFS_AG_MIN_BYTES && skip <= XFS_AG_MAX_BYTES)
219 retval = __find_secondary_sb(rsb, skip, skip);
220 }
221
222 /* If that failed, retry coarse approach, using default geometry */
223 if (!retval) {
224 blocklog = guess_default_geometry(&agsize, &agcount, &x);
225 skip = agsize << blocklog;
226 retval = __find_secondary_sb(rsb, skip, skip);
227 }
228
229 /* If that failed, fall back to the brute force method */
230 if (!retval)
231 retval = __find_secondary_sb(rsb, XFS_AG_MIN_BYTES, BSIZE);
232
233 return retval;
234 }
235
236 /*
237 * Calculate what the inode alignment field ought to be based on internal
238 * superblock info and determine if it is valid.
239 *
240 * For standard v5 superblocks, the inode alignment must either match
241 * XFS_INODE_BIG_CLUSTER_SIZE or a multiple based on the inode size. For v5
242 * superblocks with sparse inode chunks enabled, inode alignment must match the
243 * inode chunk size.
244 *
245 * Return true if the alignment is valid, false otherwise.
246 */
247 static bool
248 sb_validate_ino_align(struct xfs_sb *sb)
249 {
250 xfs_extlen_t align;
251
252 if (!xfs_sb_version_hasalign(sb))
253 return true;
254
255 /* standard cluster size alignment is always valid */
256 align = XFS_INODE_BIG_CLUSTER_SIZE >> sb->sb_blocklog;
257 if (align == sb->sb_inoalignmt)
258 return true;
259
260 /* alignment scaled by inode size is v5 only for now */
261 if (!xfs_sb_version_hascrc(sb))
262 return false;
263
264 align = (XFS_INODE_BIG_CLUSTER_SIZE *
265 sb->sb_inodesize / XFS_DINODE_MIN_SIZE) >> sb->sb_blocklog;
266 if (align == sb->sb_inoalignmt)
267 return true;
268
269 /*
270 * Sparse inodes requires inoalignmt to match full inode chunk size and
271 * spino_align to match the scaled alignment (as calculated above).
272 */
273 if (xfs_sb_version_hassparseinodes(sb)) {
274 if (align != sb->sb_spino_align)
275 return false;
276
277 align = (sb->sb_inodesize * XFS_INODES_PER_CHUNK)
278 >> sb->sb_blocklog;
279 if (align == sb->sb_inoalignmt)
280 return true;
281 }
282
283 return false;
284 }
285
286 /*
287 * Validate the given log space. Derived from xfs_log_mount, though we
288 * can't validate the minimum log size until later. We only do this
289 * validation on V5 filesystems because the kernel doesn't reject malformed
290 * log geometry on older revision filesystems.
291 *
292 * Returns false if the log is garbage.
293 */
294 static bool
295 verify_sb_loginfo(
296 struct xfs_sb *sb)
297 {
298 if (xfs_sb_version_hascrc(sb) &&
299 (sb->sb_logblocks == 0 ||
300 sb->sb_logblocks > XFS_MAX_LOG_BLOCKS ||
301 ((unsigned long long)sb->sb_logblocks << sb->sb_blocklog) >
302 XFS_MAX_LOG_BYTES))
303 return false;
304
305 if (sb->sb_logsunit > 1 && sb->sb_logsunit % sb->sb_blocksize)
306 return false;
307
308 return true;
309 }
310
311 /*
312 * verify a superblock -- does not verify root inode #
313 * can only check that geometry info is internally
314 * consistent. because of growfs, that's no guarantee
315 * of correctness (e.g. geometry may have changed)
316 *
317 * fields verified or consistency checked:
318 *
319 * sb_magicnum
320 *
321 * sb_versionnum
322 *
323 * sb_inprogress
324 *
325 * sb_blocksize (as a group)
326 * sb_blocklog
327 *
328 * geometry info - sb_dblocks (as a group)
329 * sb_agcount
330 * sb_agblocks
331 * sb_agblklog
332 *
333 * inode info - sb_inodesize (x-checked with geo info)
334 * sb_inopblock
335 *
336 * sector size info -
337 * sb_sectsize
338 * sb_sectlog
339 * sb_logsectsize
340 * sb_logsectlog
341 *
342 * not checked here -
343 * sb_rootino
344 * sb_fname
345 * sb_fpack
346 * sb_logstart
347 * sb_uuid
348 *
349 * ALL real-time fields
350 * final 4 summary counters
351 */
352
353 int
354 verify_sb(char *sb_buf, xfs_sb_t *sb, int is_primary_sb)
355 {
356 uint32_t bsize;
357 int i;
358 int ret;
359
360 /* check magic number and version number */
361
362 if (sb->sb_magicnum != XFS_SB_MAGIC)
363 return(XR_BAD_MAGIC);
364
365 if (!xfs_sb_good_version(sb))
366 return(XR_BAD_VERSION);
367
368 /* does sb think mkfs really finished ? */
369 if (is_primary_sb && sb->sb_inprogress)
370 return(XR_BAD_INPROGRESS);
371
372 /*
373 * before going *any further*, validate the sector size and if the
374 * version says we should have CRCs enabled, validate that.
375 */
376
377 /* check to make sure sectorsize is legal 2^N, 9 <= N <= 15 */
378 if (sb->sb_sectsize == 0)
379 return(XR_BAD_SECT_SIZE_DATA);
380
381 bsize = 1;
382 for (i = 0; bsize < sb->sb_sectsize &&
383 i < sizeof(sb->sb_sectsize) * NBBY; i++) {
384 bsize <<= 1;
385 }
386
387 if (i < XFS_MIN_SECTORSIZE_LOG || i > XFS_MAX_SECTORSIZE_LOG)
388 return(XR_BAD_SECT_SIZE_DATA);
389
390 /* check sb sectorsize field against sb sectlog field */
391 if (i != sb->sb_sectlog)
392 return(XR_BAD_SECT_SIZE_DATA);
393
394 /* sector size in range - CRC check time */
395 if (xfs_sb_version_hascrc(sb) &&
396 !libxfs_verify_cksum(sb_buf, sb->sb_sectsize, XFS_SB_CRC_OFF))
397 return XR_BAD_CRC;
398
399 /* check to ensure blocksize and blocklog are legal */
400 ret = verify_sb_blocksize(sb);
401 if (ret != 0)
402 return ret;
403
404 /* sanity check ag count, size fields against data size field */
405
406 if (sb->sb_dblocks == 0 ||
407 sb->sb_dblocks > XFS_MAX_DBLOCKS(sb) ||
408 sb->sb_dblocks < XFS_MIN_DBLOCKS(sb))
409 return(XR_BAD_FS_SIZE_DATA);
410
411 if (sb->sb_agblklog != (uint8_t)log2_roundup(sb->sb_agblocks))
412 return(XR_BAD_FS_SIZE_DATA);
413
414 if (sb->sb_inodesize < XFS_DINODE_MIN_SIZE ||
415 sb->sb_inodesize > XFS_DINODE_MAX_SIZE ||
416 sb->sb_inodelog < XFS_DINODE_MIN_LOG ||
417 sb->sb_inodelog > XFS_DINODE_MAX_LOG ||
418 sb->sb_inodesize != (1 << sb->sb_inodelog) ||
419 sb->sb_logsunit > XLOG_MAX_RECORD_BSIZE ||
420 sb->sb_inopblock != howmany(sb->sb_blocksize, sb->sb_inodesize) ||
421 (sb->sb_blocklog - sb->sb_inodelog != sb->sb_inopblog))
422 return XR_BAD_INO_SIZE_DATA;
423
424 if (!verify_sb_loginfo(sb))
425 return XR_BAD_LOG_GEOMETRY;
426
427 if (xfs_sb_version_hassector(sb)) {
428
429 /* check to make sure log sector is legal 2^N, 9 <= N <= 15 */
430
431 if (sb->sb_logsectsize == 0)
432 return(XR_BAD_SECT_SIZE_DATA);
433
434 bsize = 1;
435
436 for (i = 0; bsize < sb->sb_logsectsize &&
437 i < sizeof(sb->sb_logsectsize) * NBBY; i++) {
438 bsize <<= 1;
439 }
440
441 if (i < XFS_MIN_SECTORSIZE_LOG || i > XFS_MAX_SECTORSIZE_LOG)
442 return(XR_BAD_SECT_SIZE_DATA);
443
444 /* check sb log sectorsize field against sb log sectlog field */
445
446 if (i != sb->sb_logsectlog)
447 return(XR_BAD_SECT_SIZE_DATA);
448 }
449
450 /*
451 * real-time extent size is always set
452 */
453 if (sb->sb_rextsize * sb->sb_blocksize > XFS_MAX_RTEXTSIZE)
454 return(XR_BAD_RT_GEO_DATA);
455
456 if (sb->sb_rextsize * sb->sb_blocksize < XFS_MIN_RTEXTSIZE)
457 return(XR_BAD_RT_GEO_DATA);
458
459 if (sb->sb_rblocks == 0) {
460 if (sb->sb_rextents != 0)
461 return(XR_BAD_RT_GEO_DATA);
462
463 if (sb->sb_rbmblocks != 0)
464 return(XR_BAD_RT_GEO_DATA);
465
466 if (sb->sb_rextslog != 0)
467 return(XR_BAD_RT_GEO_DATA);
468
469 if (sb->sb_frextents != 0)
470 return(XR_BAD_RT_GEO_DATA);
471 } else {
472 /*
473 * if we have a real-time partition, sanity-check geometry
474 */
475 if (sb->sb_rblocks / sb->sb_rextsize != sb->sb_rextents)
476 return(XR_BAD_RT_GEO_DATA);
477
478 if (sb->sb_rextslog !=
479 libxfs_highbit32((unsigned int)sb->sb_rextents))
480 return(XR_BAD_RT_GEO_DATA);
481
482 if (sb->sb_rbmblocks != (xfs_extlen_t) howmany(sb->sb_rextents,
483 NBBY * sb->sb_blocksize))
484 return(XR_BAD_RT_GEO_DATA);
485 }
486
487 /*
488 * verify correctness of inode alignment if it's there
489 */
490 if (!sb_validate_ino_align(sb))
491 return(XR_BAD_INO_ALIGN);
492
493 /*
494 * verify max. % of inodes (sb_imax_pct)
495 */
496 if (sb->sb_imax_pct > 100)
497 return(XR_BAD_INO_MAX_PCT);
498
499 /*
500 * verify stripe alignment fields if present
501 */
502 if (xfs_sb_version_hasdalign(sb)) {
503 if ((!sb->sb_unit && sb->sb_width) ||
504 (sb->sb_unit && sb->sb_agblocks % sb->sb_unit))
505 return(XR_BAD_SB_UNIT);
506 if ((sb->sb_unit && !sb->sb_width) ||
507 (sb->sb_width && sb->sb_unit && sb->sb_width % sb->sb_unit))
508 return(XR_BAD_SB_WIDTH);
509 } else if (sb->sb_unit || sb->sb_width)
510 return XR_BAD_SB_WIDTH;
511
512 /* Directory block log */
513 if (sb->sb_blocklog + sb->sb_dirblklog > XFS_MAX_BLOCKSIZE_LOG)
514 return XR_BAD_DIR_SIZE_DATA;
515
516 return(XR_OK);
517 }
518
519 void
520 write_primary_sb(xfs_sb_t *sbp, int size)
521 {
522 struct xfs_dsb *buf;
523
524 if (no_modify)
525 return;
526
527 buf = memalign(libxfs_device_alignment(), size);
528 if (buf == NULL) {
529 do_error(_("failed to memalign superblock buffer\n"));
530 return;
531 }
532 memset(buf, 0, size);
533
534 if (lseek(x.data.fd, 0LL, SEEK_SET) != 0LL) {
535 free(buf);
536 do_error(_("couldn't seek to offset 0 in filesystem\n"));
537 }
538
539 libxfs_sb_to_disk(buf, sbp);
540
541 if (xfs_sb_version_hascrc(sbp))
542 xfs_update_cksum((char *)buf, size, XFS_SB_CRC_OFF);
543
544 if (write(x.data.fd, buf, size) != size) {
545 free(buf);
546 do_error(_("primary superblock write failed!\n"));
547 }
548
549 free(buf);
550 }
551
552 /*
553 * get a possible superblock -- checks for internal consistency
554 */
555 int
556 get_sb(xfs_sb_t *sbp, xfs_off_t off, int size, xfs_agnumber_t agno)
557 {
558 int error, rval;
559 struct xfs_dsb *buf;
560
561 buf = memalign(libxfs_device_alignment(), size);
562 if (buf == NULL) {
563 do_error(
564 _("error reading superblock %u -- failed to memalign buffer\n"),
565 agno);
566 exit(1);
567 }
568 memset(buf, 0, size);
569 memset(sbp, 0, sizeof(*sbp));
570
571 /* try and read it first */
572
573 if (lseek(x.data.fd, off, SEEK_SET) != off) {
574 do_warn(
575 _("error reading superblock %u -- seek to offset %" PRId64 " failed\n"),
576 agno, off);
577 free(buf);
578 return(XR_EOF);
579 }
580
581 if ((rval = read(x.data.fd, buf, size)) != size) {
582 error = errno;
583 do_warn(
584 _("superblock read failed, offset %" PRId64 ", size %d, ag %u, rval %d\n"),
585 off, size, agno, rval);
586 do_error("%s\n", strerror(error));
587 }
588 libxfs_sb_from_disk(sbp, buf);
589
590 rval = verify_sb((char *)buf, sbp, agno == 0);
591 free(buf);
592 return rval;
593 }
594
595 /* returns element on list with highest reference count */
596 static fs_geo_list_t *
597 get_best_geo(fs_geo_list_t *list)
598 {
599 int cnt = 0;
600 fs_geo_list_t *current, *rval = NULL;
601
602 current = list;
603
604 while (current != NULL) {
605 if (current->refs > cnt) {
606 rval = current;
607 cnt = current->refs;
608 }
609 current = current->next;
610 }
611
612 return(rval);
613 }
614
615 /* adds geometry info to linked list. returns (sometimes new) head of list */
616 static fs_geo_list_t *
617 add_geo(fs_geo_list_t *list, fs_geometry_t *geo_p, int index)
618 {
619 fs_geo_list_t *current = list;
620
621 while (current != NULL) {
622 if (memcmp(geo_p, &current->geo, sizeof(fs_geometry_t)) == 0) {
623 current->refs++;
624 return(list);
625 }
626
627 current = current->next;
628 }
629
630 if ((current = malloc(sizeof(fs_geo_list_t))) == NULL) {
631 do_error(_("couldn't malloc geometry structure\n"));
632 exit(1);
633 }
634
635 current->geo = *geo_p;
636 current->refs = 1;
637 current->next = list;
638 current->index = index;
639
640 return(current);
641 }
642
643 static void
644 free_geo(fs_geo_list_t *list)
645 {
646 fs_geo_list_t *next;
647 fs_geo_list_t *current;
648
649 for (current = list; current != NULL; current = next) {
650 next = current->next;
651 free(current);
652 }
653 }
654
655 void
656 get_sb_geometry(fs_geometry_t *geo, xfs_sb_t *sbp)
657 {
658 memset(geo, 0, sizeof(fs_geometry_t));
659
660 /*
661 * blindly set fields that we know are always good
662 */
663 geo->sb_blocksize = sbp->sb_blocksize;
664 geo->sb_dblocks = sbp->sb_dblocks;
665 geo->sb_rblocks = sbp->sb_rblocks;
666 geo->sb_rextents = sbp->sb_rextents;
667 geo->sb_logstart = sbp->sb_logstart;
668 geo->sb_rextsize = sbp->sb_rextsize;
669 geo->sb_agblocks = sbp->sb_agblocks;
670 geo->sb_agcount = sbp->sb_agcount;
671 geo->sb_rbmblocks = sbp->sb_rbmblocks;
672 geo->sb_logblocks = sbp->sb_logblocks;
673 geo->sb_sectsize = sbp->sb_sectsize;
674 geo->sb_inodesize = sbp->sb_inodesize;
675
676 if (xfs_sb_version_hasalign(sbp))
677 geo->sb_ialignbit = 1;
678
679 if (xfs_sb_version_hasdalign(sbp))
680 geo->sb_salignbit = 1;
681
682 geo->sb_extflgbit = 1;
683 geo->sb_fully_zeroed = 1;
684 }
685
686 /*
687 * the way to verify that a primary sb is consistent with the
688 * filesystem is find the secondaries given the info in the
689 * primary and compare the geometries in the secondaries against
690 * the geometry indicated by the primary.
691 *
692 * returns 0 if ok, else error code (XR_EOF, XR_INSUFF_SEC_SB, etc).
693 */
694 int
695 verify_set_primary_sb(xfs_sb_t *rsb,
696 int sb_index,
697 int *sb_modified)
698 {
699 xfs_off_t off;
700 fs_geometry_t geo;
701 xfs_sb_t *sb;
702 fs_geo_list_t *list;
703 fs_geo_list_t *current;
704 xfs_agnumber_t agno;
705 int num_sbs;
706 int size;
707 int num_ok;
708 int retval;
709
710 /*
711 * We haven't been able to validate the sector size yet properly
712 * (e.g. in the case of repairing an image in a file), so we need to
713 * take into account sector mismatches and so use the maximum possible
714 * sector size rather than the sector size in @rsb.
715 */
716 size = NUM_AGH_SECTS * (1 << (XFS_MAX_SECTORSIZE_LOG));
717 list = NULL;
718 num_ok = 0;
719 *sb_modified = 0;
720 num_sbs = rsb->sb_agcount;
721
722 sb = (xfs_sb_t *) alloc_ag_buf(size);
723
724 /*
725 * put the primary sb geometry info onto the geometry list
726 */
727 get_sb_geometry(&geo, rsb);
728 list = add_geo(list, &geo, sb_index);
729
730 /*
731 * scan the secondaries and check them off as we get them so we only
732 * process each one once
733 */
734 for (agno = 1; agno < rsb->sb_agcount; agno++) {
735 off = (xfs_off_t)agno * rsb->sb_agblocks << rsb->sb_blocklog;
736
737 retval = get_sb(sb, off, size, agno);
738 if (retval == XR_EOF)
739 goto out_free_list;
740
741 if (retval == XR_OK) {
742 /*
743 * save away geometry info. don't bother checking the
744 * sb against the agi/agf as the odds of the sb being
745 * corrupted in a way that it is internally consistent
746 * but not consistent with the rest of the filesystem is
747 * really really low.
748 */
749 get_sb_geometry(&geo, sb);
750 list = add_geo(list, &geo, agno);
751 num_ok++;
752 }
753 }
754
755 /*
756 * see if we have enough superblocks to bother with
757 */
758 retval = 0;
759 if (num_ok < num_sbs / 2) {
760 retval = XR_INSUFF_SEC_SB;
761 goto out_free_list;
762 }
763
764 current = get_best_geo(list);
765
766 /*
767 * check that enough sbs agree that we're willing to
768 * go with this geometry. if not, print out the
769 * geometry and a message about the force option.
770 */
771 switch (num_sbs) {
772 case 2:
773 /*
774 * If we only have two allocation groups, and the superblock
775 * in the second allocation group differs from the primary
776 * superblock we can't verify the geometry information.
777 * Warn the user about this situation and get out unless
778 * explicitly overridden.
779 */
780 if (current->refs != 2) {
781 if (!force_geo) {
782 do_warn(
783 _("Only two AGs detected and they do not match - "
784 "cannot validate filesystem geometry.\n"
785 "Use the -o force_geometry option to proceed.\n"));
786 exit(1);
787 }
788 }
789 goto out_free_list;
790 case 1:
791 /*
792 * If we only have a single allocation group there is no
793 * secondary superblock that we can use to verify the geometry
794 * information. Warn the user about this situation and get
795 * out unless explicitly overridden.
796 */
797 if (!force_geo) {
798 do_warn(
799 _("Only one AG detected - "
800 "cannot validate filesystem geometry.\n"
801 "Use the -o force_geometry option to proceed.\n"));
802 exit(1);
803 }
804 goto out_free_list;
805 default:
806 /*
807 * at least half of the probed superblocks have
808 * to agree. if they don't, this fs is probably
809 * too far gone anyway considering the fact that
810 * XFS normally doesn't alter the secondary superblocks.
811 */
812 if (current->refs < num_sbs / 2) {
813 do_warn(
814 _("Not enough matching superblocks - cannot proceed.\n"));
815 exit(1);
816 }
817 }
818
819 /*
820 * set the geometry into primary superblock if necessary.
821 */
822
823 if (current->index != sb_index) {
824 *sb_modified = 1;
825 off = (xfs_off_t)current->index * current->geo.sb_agblocks
826 * current->geo.sb_blocksize;
827 if (get_sb(sb, off, current->geo.sb_sectsize,
828 current->index) != XR_OK)
829 do_error(_("could not read superblock\n"));
830
831 copy_sb(sb, rsb);
832
833 /*
834 * turn off inprogress bit since this is the primary.
835 * also save away values that we need to ensure are
836 * consistent in the other secondaries.
837 */
838 rsb->sb_inprogress = 0;
839 sb_inoalignmt = sb->sb_inoalignmt;
840 sb_unit = sb->sb_unit;
841 sb_width = sb->sb_width;
842 }
843
844 out_free_list:
845 free_geo(list);
846 free(sb);
847 return retval;
848 }