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