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