]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/agheader.c
xfs_repair: don't log inode problems without printing resolution
[thirdparty/xfsprogs-dev.git] / repair / agheader.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
da23017d
NS
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
2bd0ea18
NS
5 */
6
6b803e5a 7#include "libxfs.h"
2bd0ea18
NS
8#include "globals.h"
9#include "agheader.h"
10#include "protos.h"
11#include "err_protos.h"
12
e0607266
DC
13/*
14 * XXX (dgc): What is the point of all the check and repair here when phase 5
15 * recreates the AGF/AGI/AGFL completely from scratch?
16 */
17
8b8a6b02 18static int
2bd0ea18
NS
19verify_set_agf(xfs_mount_t *mp, xfs_agf_t *agf, xfs_agnumber_t i)
20{
5a35bf2c 21 xfs_rfsblock_t agblocks;
2bd0ea18
NS
22 int retval = 0;
23
24 /* check common fields */
25
5e656dbb 26 if (be32_to_cpu(agf->agf_magicnum) != XFS_AGF_MAGIC) {
2bd0ea18 27 retval = XR_AG_AGF;
507f4e33 28 do_warn(_("bad magic # 0x%x for agf %d\n"),
5e656dbb 29 be32_to_cpu(agf->agf_magicnum), i);
2bd0ea18
NS
30
31 if (!no_modify)
5e656dbb 32 agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
2bd0ea18
NS
33 }
34
5e656dbb 35 if (!XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum))) {
2bd0ea18 36 retval = XR_AG_AGF;
507f4e33 37 do_warn(_("bad version # %d for agf %d\n"),
5e656dbb 38 be32_to_cpu(agf->agf_versionnum), i);
2bd0ea18
NS
39
40 if (!no_modify)
5e656dbb 41 agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
2bd0ea18
NS
42 }
43
5e656dbb 44 if (be32_to_cpu(agf->agf_seqno) != i) {
2bd0ea18 45 retval = XR_AG_AGF;
507f4e33 46 do_warn(_("bad sequence # %d for agf %d\n"),
5e656dbb 47 be32_to_cpu(agf->agf_seqno), i);
2bd0ea18
NS
48
49 if (!no_modify)
5e656dbb 50 agf->agf_seqno = cpu_to_be32(i);
2bd0ea18
NS
51 }
52
5e656dbb 53 if (be32_to_cpu(agf->agf_length) != mp->m_sb.sb_agblocks) {
2bd0ea18
NS
54 if (i != mp->m_sb.sb_agcount - 1) {
55 retval = XR_AG_AGF;
507f4e33 56 do_warn(_("bad length %d for agf %d, should be %d\n"),
5e656dbb 57 be32_to_cpu(agf->agf_length), i,
507f4e33 58 mp->m_sb.sb_agblocks);
2bd0ea18 59 if (!no_modify)
f8149110 60 agf->agf_length =
5e656dbb 61 cpu_to_be32(mp->m_sb.sb_agblocks);
2bd0ea18
NS
62 } else {
63 agblocks = mp->m_sb.sb_dblocks -
5a35bf2c 64 (xfs_rfsblock_t) mp->m_sb.sb_agblocks * i;
2bd0ea18 65
5e656dbb 66 if (be32_to_cpu(agf->agf_length) != agblocks) {
2bd0ea18
NS
67 retval = XR_AG_AGF;
68 do_warn(
5d1b7f0f 69 _("bad length %d for agf %d, should be %" PRIu64 "\n"),
5e656dbb 70 be32_to_cpu(agf->agf_length),
507f4e33 71 i, agblocks);
2bd0ea18 72 if (!no_modify)
5e656dbb 73 agf->agf_length = cpu_to_be32(agblocks);
2bd0ea18
NS
74 }
75 }
76 }
77
78 /*
79 * check first/last AGF fields. if need be, lose the free
80 * space in the AGFL, we'll reclaim it later.
81 */
b8165508
DC
82 if (be32_to_cpu(agf->agf_flfirst) >= libxfs_agfl_size(mp)) {
83 do_warn(_("flfirst %d in agf %d too large (max = %u)\n"),
5d1b7f0f 84 be32_to_cpu(agf->agf_flfirst),
b8165508 85 i, libxfs_agfl_size(mp) - 1);
2bd0ea18 86 if (!no_modify)
5e656dbb 87 agf->agf_flfirst = cpu_to_be32(0);
2bd0ea18
NS
88 }
89
b8165508
DC
90 if (be32_to_cpu(agf->agf_fllast) >= libxfs_agfl_size(mp)) {
91 do_warn(_("fllast %d in agf %d too large (max = %u)\n"),
5d1b7f0f 92 be32_to_cpu(agf->agf_fllast),
b8165508 93 i, libxfs_agfl_size(mp) - 1);
2bd0ea18 94 if (!no_modify)
5e656dbb 95 agf->agf_fllast = cpu_to_be32(0);
2bd0ea18
NS
96 }
97
98 /* don't check freespace btrees -- will be checked by caller */
99
2660e653 100 if (!xfs_has_crc(mp))
e0607266
DC
101 return retval;
102
9c4e12fb 103 if (platform_uuid_compare(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid)) {
e0607266
DC
104 char uu[64];
105
106 retval = XR_AG_AGF;
107 platform_uuid_unparse(&agf->agf_uuid, uu);
108 do_warn(_("bad uuid %s for agf %d\n"), uu, i);
109
110 if (!no_modify)
9c4e12fb
ES
111 platform_uuid_copy(&agf->agf_uuid,
112 &mp->m_sb.sb_meta_uuid);
e0607266
DC
113 }
114 return retval;
2bd0ea18
NS
115}
116
8b8a6b02 117static int
5e656dbb 118verify_set_agi(xfs_mount_t *mp, xfs_agi_t *agi, xfs_agnumber_t agno)
2bd0ea18 119{
5a35bf2c 120 xfs_rfsblock_t agblocks;
2bd0ea18
NS
121 int retval = 0;
122
123 /* check common fields */
124
5e656dbb 125 if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) {
2bd0ea18 126 retval = XR_AG_AGI;
507f4e33 127 do_warn(_("bad magic # 0x%x for agi %d\n"),
5e656dbb 128 be32_to_cpu(agi->agi_magicnum), agno);
2bd0ea18
NS
129
130 if (!no_modify)
5e656dbb 131 agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
2bd0ea18
NS
132 }
133
5e656dbb 134 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum))) {
2bd0ea18 135 retval = XR_AG_AGI;
507f4e33 136 do_warn(_("bad version # %d for agi %d\n"),
5e656dbb 137 be32_to_cpu(agi->agi_versionnum), agno);
2bd0ea18
NS
138
139 if (!no_modify)
5e656dbb 140 agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
2bd0ea18
NS
141 }
142
5e656dbb 143 if (be32_to_cpu(agi->agi_seqno) != agno) {
2bd0ea18 144 retval = XR_AG_AGI;
507f4e33 145 do_warn(_("bad sequence # %d for agi %d\n"),
5e656dbb 146 be32_to_cpu(agi->agi_seqno), agno);
2bd0ea18
NS
147
148 if (!no_modify)
5e656dbb 149 agi->agi_seqno = cpu_to_be32(agno);
2bd0ea18
NS
150 }
151
5e656dbb
BN
152 if (be32_to_cpu(agi->agi_length) != mp->m_sb.sb_agblocks) {
153 if (agno != mp->m_sb.sb_agcount - 1) {
2bd0ea18 154 retval = XR_AG_AGI;
507f4e33 155 do_warn(_("bad length # %d for agi %d, should be %d\n"),
5e656dbb 156 be32_to_cpu(agi->agi_length), agno,
507f4e33 157 mp->m_sb.sb_agblocks);
2bd0ea18 158 if (!no_modify)
f8149110 159 agi->agi_length =
5e656dbb 160 cpu_to_be32(mp->m_sb.sb_agblocks);
2bd0ea18
NS
161 } else {
162 agblocks = mp->m_sb.sb_dblocks -
5a35bf2c 163 (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno;
2bd0ea18 164
5e656dbb 165 if (be32_to_cpu(agi->agi_length) != agblocks) {
2bd0ea18
NS
166 retval = XR_AG_AGI;
167 do_warn(
5d1b7f0f 168 _("bad length # %d for agi %d, should be %" PRIu64 "\n"),
5e656dbb
BN
169 be32_to_cpu(agi->agi_length),
170 agno, agblocks);
2bd0ea18 171 if (!no_modify)
5e656dbb 172 agi->agi_length = cpu_to_be32(agblocks);
2bd0ea18
NS
173 }
174 }
175 }
176
177 /* don't check inode btree -- will be checked by caller */
178
2660e653 179 if (!xfs_has_crc(mp))
e0607266
DC
180 return retval;
181
9c4e12fb 182 if (platform_uuid_compare(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid)) {
e0607266
DC
183 char uu[64];
184
185 retval = XR_AG_AGI;
186 platform_uuid_unparse(&agi->agi_uuid, uu);
187 do_warn(_("bad uuid %s for agi %d\n"), uu, agno);
188
189 if (!no_modify)
9c4e12fb
ES
190 platform_uuid_copy(&agi->agi_uuid,
191 &mp->m_sb.sb_meta_uuid);
e0607266
DC
192 }
193
194 return retval;
2bd0ea18
NS
195}
196
197/*
198 * superblock comparison - compare arbitrary superblock with
199 * filesystem mount-point superblock
200 *
201 * the verified fields include id and geometry.
8b8a6b02 202 *
2bd0ea18
NS
203 * the inprogress fields, version numbers, and counters
204 * are allowed to differ as well as all fields after the
dab9b8d6 205 * counters to cope with the pre-6.5 mkfs non-zeroed
2bd0ea18
NS
206 * secondary superblock sectors.
207 */
8b8a6b02 208static int
2bd0ea18
NS
209compare_sb(xfs_mount_t *mp, xfs_sb_t *sb)
210{
211 fs_geometry_t fs_geo, sb_geo;
212
213 get_sb_geometry(&fs_geo, &mp->m_sb);
214 get_sb_geometry(&sb_geo, sb);
215
216 if (memcmp(&fs_geo, &sb_geo,
217 (char *) &fs_geo.sb_shared_vn - (char *) &fs_geo))
218 return(XR_SB_GEO_MISMATCH);
219
220 return(XR_OK);
221}
222
ddba9088
DW
223/*
224 * If the fs feature bits on a secondary superblock don't match the
225 * primary, we need to update them.
226 */
227static inline int
228check_v5_feature_mismatch(
229 struct xfs_mount *mp,
230 xfs_agnumber_t agno,
231 struct xfs_sb *sb)
232{
233 bool dirty = false;
234
235 if (!xfs_has_crc(mp) || agno == 0)
236 return 0;
237
238 if (mp->m_sb.sb_features_compat != sb->sb_features_compat) {
239 if (no_modify) {
240 do_warn(
241 _("would fix compat feature mismatch in AG %u super, 0x%x != 0x%x\n"),
242 agno, mp->m_sb.sb_features_compat,
243 sb->sb_features_compat);
244 } else {
245 do_warn(
246 _("will fix compat feature mismatch in AG %u super, 0x%x != 0x%x\n"),
247 agno, mp->m_sb.sb_features_compat,
248 sb->sb_features_compat);
249 dirty = true;
250 }
251 }
252
253 /*
254 * Ignore XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR becauses the repair upgrade
255 * path sets it only on the primary while upgrading.
256 */
257 if ((mp->m_sb.sb_features_incompat ^ sb->sb_features_incompat) &
258 ~XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR) {
259 if (no_modify) {
260 do_warn(
261 _("would fix incompat feature mismatch in AG %u super, 0x%x != 0x%x\n"),
262 agno, mp->m_sb.sb_features_incompat,
263 sb->sb_features_incompat);
264 } else {
265 do_warn(
266 _("will fix incompat feature mismatch in AG %u super, 0x%x != 0x%x\n"),
267 agno, mp->m_sb.sb_features_incompat,
268 sb->sb_features_incompat);
269 dirty = true;
270 }
271 }
272
273 if (mp->m_sb.sb_features_ro_compat != sb->sb_features_ro_compat) {
274 if (no_modify) {
275 do_warn(
276 _("would fix ro compat feature mismatch in AG %u super, 0x%x != 0x%x\n"),
277 agno, mp->m_sb.sb_features_ro_compat,
278 sb->sb_features_ro_compat);
279 } else {
280 do_warn(
281 _("will fix ro compat feature mismatch in AG %u super, 0x%x != 0x%x\n"),
282 agno, mp->m_sb.sb_features_ro_compat,
283 sb->sb_features_ro_compat);
284 dirty = true;
285 }
286 }
287
84c5f08f
DW
288 /*
289 * Log incompat feature bits are set and cleared from the primary super
290 * as needed to protect against log replay on old kernels finding log
291 * records that they cannot handle. Secondary sb resyncs performed as
292 * part of a geometry update to the primary sb (e.g. growfs, label/uuid
293 * changes) will copy the log incompat feature bits, but it's not a
294 * corruption for a secondary to have a bit set that is clear in the
295 * primary super.
296 */
ddba9088
DW
297 if (mp->m_sb.sb_features_log_incompat != sb->sb_features_log_incompat) {
298 if (no_modify) {
84c5f08f
DW
299 do_log(
300 _("would sync log incompat feature in AG %u super, 0x%x != 0x%x\n"),
ddba9088
DW
301 agno, mp->m_sb.sb_features_log_incompat,
302 sb->sb_features_log_incompat);
303 } else {
304 do_warn(
84c5f08f 305 _("will sync log incompat feature in AG %u super, 0x%x != 0x%x\n"),
ddba9088
DW
306 agno, mp->m_sb.sb_features_log_incompat,
307 sb->sb_features_log_incompat);
308 dirty = true;
309 }
310 }
311
312 if (!dirty)
313 return 0;
314
315 sb->sb_features_compat = mp->m_sb.sb_features_compat;
316 sb->sb_features_ro_compat = mp->m_sb.sb_features_ro_compat;
317 sb->sb_features_incompat = mp->m_sb.sb_features_incompat;
318 sb->sb_features_log_incompat = mp->m_sb.sb_features_log_incompat;
319 return XR_AG_SB_SEC;
320}
321
2bd0ea18 322/*
bcedcddf
NS
323 * Possible fields that may have been set at mkfs time,
324 * sb_inoalignmt, sb_unit, sb_width and sb_dirblklog.
325 * The quota inode fields in the secondaries should be zero.
2bd0ea18
NS
326 * Likewise, the sb_flags and sb_shared_vn should also be
327 * zero and the shared version bit should be cleared for
328 * current mkfs's.
329 *
9440d84d
NS
330 * And everything else in the buffer beyond either sb_width,
331 * sb_dirblklog (v2 dirs), or sb_logsectsize can be zeroed.
332 *
333 * Note: contrary to the name, this routine is called for all
334 * superblocks, not just the secondary superblocks.
2bd0ea18 335 */
8b8a6b02 336static int
9c4e12fb 337secondary_sb_whack(
d085fb48
DC
338 struct xfs_mount *mp,
339 struct xfs_buf *sbuf,
340 struct xfs_sb *sb,
341 xfs_agnumber_t i)
2bd0ea18 342{
d6522f1d 343 struct xfs_dsb *dsb = sbuf->b_addr;
d085fb48
DC
344 int do_bzero = 0;
345 int size;
346 char *ip;
f6ebe7c7 347 int rval = 0;
2110aea0 348 uuid_t tmpuuid;
2bd0ea18
NS
349
350 rval = do_bzero = 0;
351
352 /*
cbd7508d
ES
353 * Check for garbage beyond the last valid field.
354 * Use field addresses instead so this code will still
355 * work against older filesystems when the superblock
356 * gets rev'ed again with new fields appended.
357 *
358 * size is the size of data which is valid for this sb.
2bd0ea18 359 */
9c4e12fb
ES
360 if (xfs_sb_version_hasmetauuid(sb))
361 size = offsetof(xfs_sb_t, sb_meta_uuid)
362 + sizeof(sb->sb_meta_uuid);
363 else if (xfs_sb_version_hascrc(sb))
cbd7508d
ES
364 size = offsetof(xfs_sb_t, sb_lsn)
365 + sizeof(sb->sb_lsn);
366 else if (xfs_sb_version_hasmorebits(sb))
367 size = offsetof(xfs_sb_t, sb_bad_features2)
368 + sizeof(sb->sb_bad_features2);
369 else if (xfs_sb_version_haslogv2(sb))
370 size = offsetof(xfs_sb_t, sb_logsunit)
371 + sizeof(sb->sb_logsunit);
372 else if (xfs_sb_version_hassector(sb))
373 size = offsetof(xfs_sb_t, sb_logsectsize)
374 + sizeof(sb->sb_logsectsize);
5f6f3660 375 else /* only support dirv2 or more recent */
cbd7508d
ES
376 size = offsetof(xfs_sb_t, sb_dirblklog)
377 + sizeof(sb->sb_dirblklog);
cbd7508d
ES
378
379 /* Check the buffer we read from disk for garbage outside size */
04338619
CM
380 for (ip = (char *)sbuf->b_addr + size;
381 ip < (char *)sbuf->b_addr + mp->m_sb.sb_sectsize;
cbd7508d
ES
382 ip++) {
383 if (*ip) {
384 do_bzero = 1;
385 break;
2bd0ea18
NS
386 }
387 }
cbd7508d
ES
388 if (do_bzero) {
389 rval |= XR_AG_SB_SEC;
390 if (!no_modify) {
391 do_warn(
392 _("zeroing unused portion of %s superblock (AG #%u)\n"),
393 !i ? _("primary") : _("secondary"), i);
394 /*
395 * zero both the in-memory sb and the disk buffer,
396 * because the former was read from disk and
397 * may contain newer version fields that shouldn't
398 * be set, and the latter is never updated past
399 * the last field - just zap them both.
400 */
2110aea0 401 memcpy(&tmpuuid, &sb->sb_meta_uuid, sizeof(uuid_t));
ee6cd73e 402 memset((void *)((intptr_t)sb + size), 0,
cbd7508d 403 mp->m_sb.sb_sectsize - size);
04338619 404 memset((char *)sbuf->b_addr + size, 0,
cbd7508d 405 mp->m_sb.sb_sectsize - size);
2110aea0
DW
406 /* Preserve meta_uuid so we don't fail uuid checks */
407 memcpy(&sb->sb_meta_uuid, &tmpuuid, sizeof(uuid_t));
cbd7508d
ES
408 } else
409 do_warn(
410 _("would zero unused portion of %s superblock (AG #%u)\n"),
411 !i ? _("primary") : _("secondary"), i);
412 }
2bd0ea18
NS
413
414 /*
415 * now look for the fields we can manipulate directly.
dab9b8d6 416 * if we did a zero and that zero could have included
2bd0ea18
NS
417 * the field in question, just silently reset it. otherwise,
418 * complain.
419 *
420 * for now, just zero the flags field since only
421 * the readonly flag is used
422 */
423 if (sb->sb_flags) {
424 if (!no_modify)
425 sb->sb_flags = 0;
5f6f3660 426 if (!do_bzero) {
2bd0ea18 427 rval |= XR_AG_SB;
507f4e33 428 do_warn(_("bad flags field in superblock %d\n"), i);
2bd0ea18
NS
429 } else
430 rval |= XR_AG_SB_SEC;
431 }
432
433 /*
d085fb48
DC
434 * quota inodes and flags in secondary superblocks are never set by
435 * mkfs. However, they could be set in a secondary if a fs with quotas
436 * was growfs'ed since growfs copies the new primary into the
437 * secondaries.
438 *
439 * Also, the in-core inode flags now have different meaning to the
440 * on-disk flags, and so libxfs_sb_to_disk cannot directly write the
441 * sb_gquotino/sb_pquotino fields without specific sb_qflags being set.
442 * Hence we need to zero those fields directly in the sb buffer here.
2bd0ea18 443 */
d085fb48
DC
444
445 if (sb->sb_inprogress == 1 && sb->sb_uquotino != NULLFSINO) {
2bd0ea18
NS
446 if (!no_modify)
447 sb->sb_uquotino = 0;
5f6f3660 448 if (!do_bzero) {
2bd0ea18
NS
449 rval |= XR_AG_SB;
450 do_warn(
507f4e33 451 _("non-null user quota inode field in superblock %d\n"),
2bd0ea18 452 i);
507f4e33 453
2bd0ea18
NS
454 } else
455 rval |= XR_AG_SB_SEC;
456 }
457
d085fb48
DC
458 if (sb->sb_inprogress == 1 && sb->sb_gquotino != NULLFSINO) {
459 if (!no_modify) {
b36eef04 460 sb->sb_gquotino = 0;
d085fb48
DC
461 dsb->sb_gquotino = 0;
462 }
5f6f3660 463 if (!do_bzero) {
2bd0ea18
NS
464 rval |= XR_AG_SB;
465 do_warn(
507f4e33 466 _("non-null group quota inode field in superblock %d\n"),
2bd0ea18 467 i);
507f4e33 468
2bd0ea18
NS
469 } else
470 rval |= XR_AG_SB_SEC;
471 }
472
fa8fb25a
BF
473 /*
474 * Note that sb_pquotino is not considered a valid sb field for pre-v5
475 * superblocks. If it is anything other than 0 it is considered garbage
476 * data beyond the valid sb and explicitly zeroed above.
477 */
2660e653 478 if (xfs_has_pquotino(mp) &&
fa8fb25a 479 sb->sb_inprogress == 1 && sb->sb_pquotino != NULLFSINO) {
d085fb48 480 if (!no_modify) {
0340d706 481 sb->sb_pquotino = 0;
d085fb48
DC
482 dsb->sb_pquotino = 0;
483 }
5f6f3660 484 if (!do_bzero) {
0340d706
CS
485 rval |= XR_AG_SB;
486 do_warn(
487 _("non-null project quota inode field in superblock %d\n"),
488 i);
489
490 } else
491 rval |= XR_AG_SB_SEC;
492 }
493
2bd0ea18
NS
494 if (sb->sb_inprogress == 1 && sb->sb_qflags) {
495 if (!no_modify)
496 sb->sb_qflags = 0;
5f6f3660 497 if (!do_bzero) {
2bd0ea18 498 rval |= XR_AG_SB;
507f4e33
NS
499 do_warn(_("non-null quota flags in superblock %d\n"),
500 i);
2bd0ea18
NS
501 } else
502 rval |= XR_AG_SB_SEC;
503 }
504
505 /*
506 * if the secondaries agree on a stripe unit/width or inode
507 * alignment, those fields ought to be valid since they are
508 * written at mkfs time (and the corresponding sb version bits
509 * are set).
510 */
5e656dbb 511 if (!xfs_sb_version_hasalign(sb) && sb->sb_inoalignmt != 0) {
2bd0ea18
NS
512 if (!no_modify)
513 sb->sb_inoalignmt = 0;
5f6f3660 514 if (!do_bzero) {
2bd0ea18 515 rval |= XR_AG_SB;
507f4e33
NS
516 do_warn(
517 _("bad inode alignment field in superblock %d\n"),
2bd0ea18
NS
518 i);
519 } else
520 rval |= XR_AG_SB_SEC;
521 }
522
5e656dbb 523 if (!xfs_sb_version_hasdalign(sb) &&
2bd0ea18
NS
524 (sb->sb_unit != 0 || sb->sb_width != 0)) {
525 if (!no_modify)
526 sb->sb_unit = sb->sb_width = 0;
5f6f3660 527 if (!do_bzero) {
2bd0ea18
NS
528 rval |= XR_AG_SB;
529 do_warn(
507f4e33
NS
530 _("bad stripe unit/width fields in superblock %d\n"),
531 i);
532 } else
533 rval |= XR_AG_SB_SEC;
534 }
535
5e656dbb 536 if (!xfs_sb_version_hassector(sb) &&
507f4e33
NS
537 (sb->sb_sectsize != BBSIZE || sb->sb_sectlog != BBSHIFT ||
538 sb->sb_logsectsize != 0 || sb->sb_logsectlog != 0)) {
539 if (!no_modify) {
540 sb->sb_sectsize = BBSIZE;
541 sb->sb_sectlog = BBSHIFT;
542 sb->sb_logsectsize = 0;
543 sb->sb_logsectlog = 0;
544 }
5f6f3660 545 if (!do_bzero) {
507f4e33
NS
546 rval |= XR_AG_SB;
547 do_warn(
548 _("bad log/data device sector size fields in superblock %d\n"),
2bd0ea18
NS
549 i);
550 } else
551 rval |= XR_AG_SB_SEC;
552 }
553
ddba9088
DW
554 rval |= check_v5_feature_mismatch(mp, i, sb);
555
a7348c58
DW
556 if (xfs_sb_version_needsrepair(sb)) {
557 if (i == 0) {
558 if (!no_modify)
559 do_warn(
560 _("clearing needsrepair flag and regenerating metadata\n"));
561 else
562 do_warn(
563 _("would clear needsrepair flag and regenerate metadata\n"));
fa0f9232
DW
564 /*
565 * If needsrepair is set on the primary super, there's
566 * a possibility that repair crashed during an upgrade.
567 * Set features_changed to ensure that the secondary
568 * supers are rewritten with the new feature bits once
569 * we've finished the upgrade.
570 */
571 features_changed = true;
a7348c58
DW
572 } else {
573 /*
574 * Quietly clear needsrepair on the secondary supers as
575 * part of ensuring them. If needsrepair is set on the
576 * primary, it will be cleared at the end of repair
577 * once we've flushed all other dirty blocks to disk.
578 */
579 sb->sb_features_incompat &=
580 ~XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
581 rval |= XR_AG_SB_SEC;
582 }
583 }
584
2bd0ea18
NS
585 return(rval);
586}
587
588/*
589 * verify and reset the ag header if required.
590 *
591 * lower 4 bits of rval are set depending on what got modified.
592 * (see agheader.h for more details)
593 *
594 * NOTE -- this routine does not tell the user that it has
595 * altered things. Rather, it is up to the caller to do so
596 * using the bits encoded into the return value.
597 */
598
599int
167137fe 600verify_set_agheader(xfs_mount_t *mp, struct xfs_buf *sbuf, xfs_sb_t *sb,
2bd0ea18
NS
601 xfs_agf_t *agf, xfs_agi_t *agi, xfs_agnumber_t i)
602{
603 int rval = 0;
604 int status = XR_OK;
605 int status_sb = XR_OK;
606
88f364a9 607 status = verify_sb(sbuf->b_addr, sb, (i == 0));
2bd0ea18
NS
608
609 if (status != XR_OK) {
507f4e33 610 do_warn(_("bad on-disk superblock %d - %s\n"),
2bd0ea18
NS
611 i, err_string(status));
612 }
613
614 status_sb = compare_sb(mp, sb);
615
616 if (status_sb != XR_OK) {
507f4e33 617 do_warn(_("primary/secondary superblock %d conflict - %s\n"),
2bd0ea18
NS
618 i, err_string(status_sb));
619 }
620
621 if (status != XR_OK || status_sb != XR_OK) {
622 if (!no_modify) {
623 *sb = mp->m_sb;
624
625 /*
626 * clear the more transient fields
627 */
628 sb->sb_inprogress = 1;
629
630 sb->sb_icount = 0;
631 sb->sb_ifree = 0;
632 sb->sb_fdblocks = 0;
633 sb->sb_frextents = 0;
634
635 sb->sb_qflags = 0;
636 }
637
638 rval |= XR_AG_SB;
639 }
640
9c4e12fb 641 rval |= secondary_sb_whack(mp, sbuf, sb, i);
2bd0ea18
NS
642
643 rval |= verify_set_agf(mp, agf, i);
644 rval |= verify_set_agi(mp, agi, i);
645
646 return(rval);
647}