]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/sb.c
Apply RAID5 checks to RAID4 too.
[thirdparty/xfsprogs-dev.git] / repair / sb.c
CommitLineData
2bd0ea18
NS
1/*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33#include <errno.h>
34#include <libxfs.h>
35#include <malloc.h>
36#include "agheader.h"
37#include "globals.h"
38#include "protos.h"
39#include "err_protos.h"
40
41
42/*
43 * copy the fields of a superblock that are present in primary and
44 * secondaries -- preserve fields that are different in the primary.
45 */
46void
47copy_sb(xfs_sb_t *source, xfs_sb_t *dest)
48{
49 xfs_ino_t rootino;
50 xfs_ino_t rbmino;
51 xfs_ino_t rsumino;
52 xfs_ino_t uquotino;
53 xfs_ino_t pquotino;
54 __uint16_t versionnum;
55
56 rootino = dest->sb_rootino;
57 rbmino = dest->sb_rbmino;
58 rsumino = dest->sb_rsumino;
59 uquotino = dest->sb_uquotino;
60 pquotino = dest->sb_pquotino;
61
62 versionnum = dest->sb_versionnum;
63
64 *dest = *source;
65
66 dest->sb_rootino = rootino;
67 dest->sb_rbmino = rbmino;
68 dest->sb_rsumino = rsumino;
69 dest->sb_uquotino = uquotino;
70 dest->sb_pquotino = pquotino;
71
72 dest->sb_versionnum = versionnum;
73
74 /*
75 * copy over version bits that are stamped into all
76 * secondaries and cannot be changed at run time in
77 * the primary superblock
78 */
79 if (XFS_SB_VERSION_HASDALIGN(source))
80 XFS_SB_VERSION_ADDDALIGN(dest);
81 if (XFS_SB_VERSION_HASEXTFLGBIT(source))
82 XFS_SB_VERSION_ADDEXTFLGBIT(dest);
83
84 /*
85 * these are all supposed to be zero or will get reset anyway
86 */
87 dest->sb_icount = 0;
88 dest->sb_ifree = 0;
89 dest->sb_fdblocks = 0;
90 dest->sb_frextents = 0;
91
92 bzero(source->sb_fname, 12);
93}
94
95#define BSIZE (1024 * 1024)
96
97/*
98 * find a secondary superblock, copy it into the sb buffer
99 */
100int
101find_secondary_sb(xfs_sb_t *rsb)
102{
103 xfs_off_t off;
104 xfs_sb_t *sb;
105 xfs_sb_t bufsb;
106 char *c_bufsb;
107 int done;
108 int i;
109 int dirty;
110 int retval;
111 int bsize;
112
113 do_warn("\nattempting to find secondary superblock...\n");
114
115 sb = (xfs_sb_t *) memalign(MEM_ALIGN, BSIZE);
116 if (!sb) {
117 do_error(
118 "error finding secondary superblock -- failed to memalign buffer\n");
119 exit(1);
120 }
121
122 bzero(&bufsb, sizeof(xfs_sb_t));
123 retval = 0;
124 dirty = 0;
125 bsize = 0;
126
127 /*
128 * skip first sector since we know that's bad
129 */
130 for (done = 0, off = XFS_AG_MIN_BYTES; !done ; off += bsize) {
131 /*
132 * read disk 1 MByte at a time.
133 */
134 if (lseek64(fs_fd, off, SEEK_SET) != off) {
135 done = 1;
136 }
137
138 if (!done && (bsize = read(fs_fd, sb, BSIZE)) == 0) {
139 done = 1;
140 }
141
142 do_warn(".");
143
144 /*
145 * check the buffer 512 bytes at a time since
146 * we don't know how big the sectors really are.
147 */
148 for (i = 0; !done && i < bsize; i += BBSIZE) {
149 c_bufsb = (char *) sb + i;
150 libxfs_xlate_sb(c_bufsb, &bufsb, 1, ARCH_CONVERT,
151 XFS_SB_ALL_BITS);
152
153 if (verify_sb(&bufsb, 0) != XR_OK)
154 continue;
155
156 do_warn("found candidate secondary superblock...\n");
157
158 /*
159 * found one. now verify it by looking
160 * for other secondaries.
161 */
162 bcopy(&bufsb, rsb, bufsb.sb_sectsize);
163 rsb->sb_inprogress = 0;
164 clear_sunit = 1;
165
166 if (verify_set_primary_sb(rsb, 0, &dirty) == XR_OK) {
167 do_warn("verified secondary superblock...\n");
168 done = 1;
169 retval = 1;
170 } else {
171 do_warn(
172 "unable to verify superblock, continuing...\n");
173 }
174 }
175 }
176
177 free(sb);
178 return(retval);
179}
180
181/*
182 * calculate what inode alignment field ought to be
183 * based on internal superblock info
184 */
185int
186calc_ino_align(xfs_sb_t *sb)
187{
188 xfs_extlen_t align;
189
190 align = XFS_INODE_BIG_CLUSTER_SIZE >> sb->sb_blocklog;
191
192 return(align);
193}
194
195/*
196 * verify a superblock -- does not verify root inode #
197 * can only check that geometry info is internally
198 * consistent. because of growfs, that's no guarantee
199 * of correctness (e.g. geometry may have changed)
200 *
201 * fields verified or consistency checked:
202 *
203 * sb_magicnum
204 *
205 * sb_versionnum
206 *
207 * sb_inprogress
208 *
209 * sb_blocksize (as a group)
210 * sb_blocklog
211 *
212 * geometry info - sb_dblocks (as a group)
213 * sb_agcount
214 * sb_agblocks
215 * sb_agblklog
216 *
217 * inode info - sb_inodesize (x-checked with geo info)
218 * sb_inopblock
219 *
220 * sector size info -
221 * sb_sectsize
222 * sb_sectlog
223 *
224 * not checked here -
225 * sb_rootino
226 * sb_fname
227 * sb_fpack
228 * sb_logstart
229 * sb_uuid
230 *
231 * ALL real-time fields
232 * final 4 summary counters
233 */
234
235int
236verify_sb(xfs_sb_t *sb, int is_primary_sb)
237{
238 __uint32_t bsize;
239 xfs_extlen_t align;
240 int i;
241
242 /* check magic number and version number */
243
244 if (sb->sb_magicnum != XFS_SB_MAGIC)
245 return(XR_BAD_MAGIC);
246
247 if (!XFS_SB_GOOD_VERSION(sb))
248 return(XR_BAD_VERSION);
249
250 /* does sb think mkfs really finished ? */
251
252 if (is_primary_sb && sb->sb_inprogress == 1)
253 return(XR_BAD_INPROGRESS);
254
255 /* check to make sure blocksize is legal 2^N, 9 <= N <= 16 */
256
257 if (sb->sb_blocksize == 0)
258 return(XR_BAD_BLOCKSIZE);
259
260 bsize = 1;
261
262 for (i = 0; bsize < sb->sb_blocksize && i < 32; i++) {
263 bsize <<= 1;
264 }
265
266 if (i < XR_LOG2BSIZE_MIN || i > XR_LOG2BSIZE_MAX)
267 return(XR_BAD_BLOCKSIZE);
268
269 /* check sb blocksize field against sb blocklog field */
270
271 if (i != sb->sb_blocklog)
272 return(XR_BAD_BLOCKLOG);
273
274 /* sanity check ag count, size fields against data size field */
275
276 if (sb->sb_dblocks == 0 ||
277 sb->sb_dblocks > sb->sb_agcount * sb->sb_agblocks ||
278 sb->sb_dblocks < (sb->sb_agcount - 1)
279 * sb->sb_agblocks + XFS_MIN_AG_BLOCKS)
280 return(XR_BAD_FS_SIZE_DATA);
281
282 if (sb->sb_agblklog != (__uint8_t)libxfs_log2_roundup(sb->sb_agblocks))
283 return(XR_BAD_FS_SIZE_DATA);
284
285 if (sb->sb_inodesize < XFS_DINODE_MIN_SIZE ||
286 sb->sb_inodesize > XFS_DINODE_MAX_SIZE ||
287 sb->sb_inopblock != howmany(sb->sb_blocksize,sb->sb_inodesize))
288 return(XR_BAD_INO_SIZE_DATA);
289
290 /* check sector size against log(sector size) field */
291
292 bsize = 1;
293
294 for (i = 0; bsize < sb->sb_sectsize && i < 15; i++) {
295 bsize <<= 1;
296 }
297
298 if (sb->sb_sectsize == 0 || i == 16 ||
299 sb->sb_sectsize != (1 << i))
300 return(XR_BAD_SECT_SIZE_DATA);
301
302 /*
303 * real-time extent size is always set
304 */
305 if (sb->sb_rextsize * sb->sb_blocksize > XFS_MAX_RTEXTSIZE)
306 return(XR_BAD_RT_GEO_DATA);
307
308 if (sb->sb_rextsize * sb->sb_blocksize < XFS_MIN_RTEXTSIZE)
309 return(XR_BAD_RT_GEO_DATA);
310
311 if (sb->sb_rblocks == 0) {
312 if (sb->sb_rextents != 0)
313 return(XR_BAD_RT_GEO_DATA);
314
315 if (sb->sb_rbmblocks != 0)
316 return(XR_BAD_RT_GEO_DATA);
317
318 if (sb->sb_rextslog != 0)
319 return(XR_BAD_RT_GEO_DATA);
320
321 if (sb->sb_frextents != 0)
322 return(XR_BAD_RT_GEO_DATA);
323 } else {
324 /*
325 * if we have a real-time partition, sanity-check geometry
326 */
327 if (sb->sb_rblocks / sb->sb_rextsize != sb->sb_rextents)
328 return(XR_BAD_RT_GEO_DATA);
329
330 if (sb->sb_rextslog !=
331 libxfs_highbit32((unsigned int)sb->sb_rextents))
332 return(XR_BAD_RT_GEO_DATA);
333
334 if (sb->sb_rbmblocks != (xfs_extlen_t) howmany(sb->sb_rextents,
335 NBBY * sb->sb_blocksize))
336 return(XR_BAD_RT_GEO_DATA);
337 }
338
339 /*
340 * verify correctness of inode alignment if it's there
341 */
342 if (XFS_SB_VERSION_HASALIGN(sb)) {
343 align = calc_ino_align(sb);
344
345 if (align != sb->sb_inoalignmt)
346 return(XR_BAD_INO_ALIGN);
347 }
348
349 /*
350 * verify max. % of inodes (sb_imax_pct)
351 */
352 if (sb->sb_imax_pct > 100)
353 return(XR_BAD_INO_MAX_PCT);
354
355 /*
356 * verify stripe alignment fields if present
357 */
358 if (XFS_SB_VERSION_HASDALIGN(sb)) {
359 if ((!sb->sb_unit && sb->sb_width) ||
360 (sb->sb_unit && sb->sb_agblocks % sb->sb_unit))
361 return(XR_BAD_SB_UNIT);
362 if ((sb->sb_unit && !sb->sb_width) ||
363 (sb->sb_width && sb->sb_unit && sb->sb_width % sb->sb_unit))
364 return(XR_BAD_SB_WIDTH);
365 }
366
367 /*
368 * if shared bit is set, verify that the version number is sane
369 */
370 if (XFS_SB_VERSION_HASSHARED(sb)) {
371 if (sb->sb_shared_vn > XFS_SB_MAX_SHARED_VN)
372 return(XR_BAD_SVN);
373 }
374
375 /*
376 * mkfs's that stamped a feature bit besides the ones in the
377 * mask below could leave garbage in the secondary superblock
378 * sectors. Anything stamping the shared fs bit or better into
379 * the secondaries is ok and should generate clean secondary
380 * superblock sectors.
381 *
382 * check primary and clean secondary superblocks more strictly
383 */
384 if (is_primary_sb || sb->sb_versionnum & XR_PART_SECSB_VNMASK) {
385 /*
386 * return errors if shared vn or alignment fields
387 * are set without their feature bits being set
388 */
389 if (!pre_65_beta && sb->sb_versionnum & XR_PART_SECSB_VNMASK ||
390 pre_65_beta && sb->sb_versionnum & XR_ALPHA_SECSB_VNMASK) {
391 /*
392 * shared version # and inode alignment fields
393 * should be valid
394 */
395 if (sb->sb_shared_vn && !XFS_SB_VERSION_HASSHARED(sb))
396 return(XR_BAD_SVN);
397 if (sb->sb_inoalignmt && !XFS_SB_VERSION_HASALIGN(sb))
398 return(XR_BAD_INO_ALIGN);
399 }
400 if ((!pre_65_beta &&
401 (sb->sb_versionnum & XR_GOOD_SECSB_VNMASK)) ||
402 (pre_65_beta &&
403 (sb->sb_versionnum & XFS_SB_VERSION_DALIGNBIT))) {
404 /*
405 * stripe alignment values should be valid
406 */
407 if (sb->sb_unit && !XFS_SB_VERSION_HASDALIGN(sb))
408 return(XR_BAD_SB_UNIT);
409 if (sb->sb_width && !XFS_SB_VERSION_HASDALIGN(sb))
410 return(XR_BAD_SB_WIDTH);
411 }
412
413#if 0
414 /*
415 * checks involving later superblock fields get added here...
416 */
417 if (sb->sb_versionnum & XR_GOOD_SECSB_VNMASK) {
418 }
419#endif
420 }
421
422 return(XR_OK);
423}
424
425void
426write_primary_sb(xfs_sb_t *sbp, int size)
427{
428 void *buf;
429
430 if (no_modify)
431 return;
432
433 if ((buf = calloc(size, 1)) == NULL) {
434 do_error("failed to malloc superblock buffer\n");
435 return;
436 }
437
438 if (lseek64(fs_fd, 0LL, SEEK_SET) != 0LL) {
439 free(buf);
440 do_error("couldn't seek to offset 0 in filesystem\n");
441 }
442
443 libxfs_xlate_sb(buf, sbp, -1, ARCH_CONVERT, XFS_SB_ALL_BITS);
444
445 if (write(fs_fd, buf, size) != size) {
446 free(buf);
447 do_error("primary superblock write failed!\n");
448 }
449
450 free(buf);
451}
452
453/*
454 * get a possible superblock -- don't check for internal consistency
455 */
456int
457get_sb(xfs_sb_t *sbp, xfs_off_t off, int size, xfs_agnumber_t agno)
458{
459 int error, rval;
460 void *buf;
461
462 if ((buf = calloc(size, 1)) == NULL) {
463 do_error(
464 "error reading superblock %u -- failed to malloc buffer\n",
465 agno, off);
466 exit(1);
467 }
468
469 /* try and read it first */
470
471 if (lseek64(fs_fd, off, SEEK_SET) != off) {
472 do_warn(
473 "error reading superblock %u -- seek to offset %lld failed\n",
474 agno, off);
475 return(XR_EOF);
476 }
477
478 if ((rval = read(fs_fd, buf, size)) != size) {
479 error = errno;
480 do_warn(
481"superblock read failed, offset %lld, size %d, ag %u, rval %d\n",
482 off, size, rval, agno);
483 do_error("%s\n", strerror(error));
484 }
485 libxfs_xlate_sb(buf, sbp, 1, ARCH_CONVERT, XFS_SB_ALL_BITS);
486 free(buf);
487
488 return (verify_sb(sbp, 0));
489}
490
491#if 0
492int
493check_growfs(xfs_off_t off, int bufnum, xfs_agnumber_t agnum)
494{
495 int rval;
496
497 ASSERT(bufnum < NUM_SBS);
498
499 /* try and read it first */
500
501 if (lseek64(fs_fd, off, SEEK_SET) != off)
502 return(XR_EOF);
503
504 if ((rval = read(fs_fd, sb_bufs[bufnum], sbbuf_size)) != sbbuf_size) {
505 /*
506 * we didn't get a full block so the filesystem
507 * could not have been grown. return a non-XR_OK
508 * result code.
509 */
510 return(XR_EOF);
511 }
512
513 return(get_sb(off, bufnum, agnum));
514}
515#endif
516/* returns element on list with highest reference count */
517
518fs_geo_list_t *
519get_best_geo(fs_geo_list_t *list)
520{
521 int cnt = 0;
522 fs_geo_list_t *current, *rval = NULL;
523
524 current = list;
525
526 while (current != NULL) {
527 if (current->refs > cnt) {
528 rval = current;
529 cnt = current->refs;
530 }
531 current = current->next;
532 }
533
534 return(rval);
535}
536
537/* adds geometry info to linked list. returns (sometimes new) head of list */
538
539fs_geo_list_t *
540add_geo(fs_geo_list_t *list, fs_geometry_t *geo_p, int index)
541{
542 fs_geo_list_t *current = list;
543
544 while (current != NULL) {
545 if (memcmp(geo_p, &current->geo, sizeof(fs_geometry_t)) == 0) {
546 current->refs++;
547 return(list);
548 }
549
550 current = current->next;
551 }
552
553 if ((current = malloc(sizeof(fs_geo_list_t))) == NULL) {
554 do_error("couldn't malloc geometry structure\n");
555 exit(1);
556 }
557
558 current->geo = *geo_p;
559 current->refs = 1;
560 current->next = list;
561 current->index = index;
562
563 return(current);
564}
565
566void
567free_geo(fs_geo_list_t *list)
568{
569 fs_geo_list_t *next;
570 fs_geo_list_t *current;
571
572 current = list;
573
574 for (current = list; current != NULL; current = next) {
575 next = current->next;
576 free(current);
577 }
578}
579
580void
581get_sb_geometry(fs_geometry_t *geo, xfs_sb_t *sbp)
582{
583 bzero(geo, sizeof(fs_geometry_t));
584
585 /*
586 * blindly set fields that we know are always good
587 */
588 geo->sb_blocksize = sbp->sb_blocksize;
589 geo->sb_dblocks = sbp->sb_dblocks;
590 geo->sb_rblocks = sbp->sb_rblocks;
591 geo->sb_rextents = sbp->sb_rextents;
592 geo->sb_logstart = sbp->sb_logstart;
593 geo->sb_rextsize = sbp->sb_rextsize;
594 geo->sb_agblocks = sbp->sb_agblocks;
595 geo->sb_agcount = sbp->sb_agcount;
596 geo->sb_rbmblocks = sbp->sb_rbmblocks;
597 geo->sb_logblocks = sbp->sb_logblocks;
598 geo->sb_sectsize = sbp->sb_sectsize;
599 geo->sb_inodesize = sbp->sb_inodesize;
600
601 if (XFS_SB_VERSION_HASALIGN(sbp))
602 geo->sb_ialignbit = 1;
603
604 if (XFS_SB_VERSION_HASSHARED(sbp) ||
605 sbp->sb_versionnum & XR_PART_SECSB_VNMASK)
606 geo->sb_sharedbit = 1;
607
608 if (XFS_SB_VERSION_HASDALIGN(sbp))
609 geo->sb_salignbit = 1;
610
611 if (XFS_SB_VERSION_HASEXTFLGBIT(sbp))
612 geo->sb_extflgbit = 1;
613
614 /*
615 * protect against pre-6.5 mkfs-generated garbaged
616 * fields in the secondary superblocks. pay attention
617 * to those fields if and only if their corresponding
618 * feature bits are set in the feature bits of the
619 * version number or we can deduce from the version bits
620 * that are set that our field was properly initialized
621 * because a field after the field we care about was
622 * properly initialized as well.
623 */
624
625 /*
626 * inode alignment field lives before the data alignment field
627 */
628 if (!pre_65_beta && sbp->sb_versionnum & XR_PART_SECSB_VNMASK ||
629 pre_65_beta && sbp->sb_versionnum & XR_ALPHA_SECSB_VNMASK)
630 geo->sb_inoalignmt = sbp->sb_inoalignmt;
631
632 if (!pre_65_beta && sbp->sb_versionnum & XR_GOOD_SECSB_VNMASK ||
633 pre_65_beta && XFS_SB_VERSION_HASDALIGN(sbp)) {
634 geo->sb_unit = sbp->sb_unit;
635 geo->sb_width = sbp->sb_width;
636 }
637
638 /*
639 * shared vn always set if either ino or data alignment is on
640 * since that field lives between the quota and inode alignment
641 * fields
642 */
643 if (sbp->sb_versionnum & XR_PART_SECSB_VNMASK)
644 geo->sb_shared_vn = sbp->sb_shared_vn;
645
646 /*
647 * superblock fields located after sb_widthfields get set
648 * into the geometry structure only if we can determine
649 * from the features enabled in this superblock whether
650 * or not the sector was bzero'd at mkfs time.
651 */
652 if (!pre_65_beta && sbp->sb_versionnum & XR_GOOD_SECSB_VNMASK ||
653 pre_65_beta && sbp->sb_versionnum & XR_ALPHA_SECSB_VNMASK) {
654 geo->sb_fully_zeroed = 1;
655 }
656}
657
658/*
659 * the way to verify that a primary sb is consistent with the
660 * filesystem is find the secondaries given the info in the
661 * primary and compare the geometries in the secondaries against
662 * the geometry indicated by the primary.
663 *
664 * returns 1 if bad, 0 if ok
665 */
666int
667verify_set_primary_sb(xfs_sb_t *rsb,
668 int sb_index,
669 int *sb_modified)
670{
671 xfs_off_t off;
672 fs_geometry_t geo;
673 xfs_sb_t *sb;
674 fs_geo_list_t *list;
675 fs_geo_list_t *current;
676 char *checked;
677 xfs_agnumber_t agno;
678 int num_sbs;
679 int skip;
680 int size;
681 int num_ok;
682 int retval;
683 int round;
684
685 /*
686 * select the number of secondaries to try for
687 */
688 num_sbs = MIN(NUM_SBS, rsb->sb_agcount);
689 skip = howmany(num_sbs, rsb->sb_agcount);
690 size = NUM_AGH_SECTS * rsb->sb_sectsize;
691 retval = 0;
692 list = NULL;
693 num_ok = 0;
694 *sb_modified = 0;
695
696 sb = (xfs_sb_t *) alloc_ag_buf(size);
697 checked = calloc(rsb->sb_agcount, sizeof(char));
698 if (!checked) {
699 do_error("calloc failed in verify_set_primary_sb\n");
700 exit(1);
701 }
702
703 /*
704 * put the primary sb geometry info onto the geometry list
705 */
706 checked[sb_index] = 1;
707 get_sb_geometry(&geo, rsb);
708 list = add_geo(list, &geo, sb_index);
709
710 /*
711 * grab N secondaries. check them off as we get them
712 * so we only process each one once
713 */
714 for (round = 0; round < skip; round++) {
715 for (agno = round; agno < rsb->sb_agcount; agno += skip) {
716 if (checked[agno])
717 continue;
718
719 off = (xfs_off_t)agno * rsb->sb_agblocks << rsb->sb_blocklog;
720
721 checked[agno] = 1;
722
723 if (get_sb(sb, off, size, agno) == XR_EOF) {
724 retval = 1;
725 goto out;
726 }
727
728 if (verify_sb(sb, 0) == XR_OK) {
729 /*
730 * save away geometry info.
731 * don't bother checking the sb
732 * against the agi/agf as the odds
733 * of the sb being corrupted in a way
734 * that it is internally consistent
735 * but not consistent with the rest
736 * of the filesystem is really really low.
737 */
738 get_sb_geometry(&geo, sb);
739 list = add_geo(list, &geo, agno);
740 num_ok++;
741 }
742 }
743 }
744
745 /*
746 * see if we have enough superblocks to bother with
747 */
748 if (num_ok < num_sbs / 2)
749 return(XR_INSUFF_SEC_SB);
750
751 current = get_best_geo(list);
752
753 /*
754 * check that enough sbs agree that we're willing to
755 * go with this geometry. if not, print out the
756 * geometry and a message about the force option.
757 */
758 switch (num_sbs) {
759 case 2:
760 /*
761 * all them have to be right. if not, report geometry
762 * and get out unless force option is in effect (-F)
763 */
764 if (current->refs != 2) {
765 if (!force_geo) {
766 do_warn("Only two AGs detected and they do not match - cannot proceed.\n");
767 exit(1);
768 }
769 }
770 break;
771 case 1:
772 /*
773 * just report the geometry info and get out.
774 * refuse to run further unless the force (-F)
775 * option is in effect.
776 */
777 if (!force_geo) {
778 do_warn("Only one AG detected - cannot proceed.\n");
779 exit(1);
780 }
781 default:
782 /*
783 * at least half of the probed superblocks have
784 * to agree. if they don't, this fs is probably
785 * too far gone anyway considering the fact that
786 * XFS normally doesn't alter the secondary superblocks.
787 */
788 if (current->refs < num_sbs / 2) {
789 do_warn("Not enough matching superblocks - cannot proceed.\n");
790 exit(1);
791 }
792 }
793
794 /*
795 * set the geometry into primary superblock if necessary.
796 */
797
798 if (current->index != sb_index) {
799 *sb_modified = 1;
800 off = current->index * current->geo.sb_agblocks
801 * current->geo.sb_blocksize;
802 if (get_sb(sb, off, current->geo.sb_sectsize,
803 current->index) != XR_OK)
804 do_error("could not read superblock\n");
805
806 copy_sb(sb, rsb);
807
808 /*
809 * turn off inprogress bit since this is the primary.
810 * also save away values that we need to ensure are
811 * consistent in the other secondaries.
812 */
813 rsb->sb_inprogress = 0;
814 sb_inoalignmt = sb->sb_inoalignmt;
815 sb_unit = sb->sb_unit;
816 sb_width = sb->sb_width;
817 }
818
819 free_geo(list);
820out:
821 free(sb);
822 free(checked);
823 return(retval);
824}