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