]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/agheader.c
xfs_scrub: don't complain about different normalization
[thirdparty/xfsprogs-dev.git] / repair / agheader.c
CommitLineData
2bd0ea18 1/*
da23017d
NS
2 * Copyright (c) 2000-2001,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
6b803e5a 19#include "libxfs.h"
2bd0ea18
NS
20#include "globals.h"
21#include "agheader.h"
22#include "protos.h"
23#include "err_protos.h"
24
e0607266
DC
25/*
26 * XXX (dgc): What is the point of all the check and repair here when phase 5
27 * recreates the AGF/AGI/AGFL completely from scratch?
28 */
29
8b8a6b02 30static int
2bd0ea18
NS
31verify_set_agf(xfs_mount_t *mp, xfs_agf_t *agf, xfs_agnumber_t i)
32{
5a35bf2c 33 xfs_rfsblock_t agblocks;
2bd0ea18
NS
34 int retval = 0;
35
36 /* check common fields */
37
5e656dbb 38 if (be32_to_cpu(agf->agf_magicnum) != XFS_AGF_MAGIC) {
2bd0ea18 39 retval = XR_AG_AGF;
507f4e33 40 do_warn(_("bad magic # 0x%x for agf %d\n"),
5e656dbb 41 be32_to_cpu(agf->agf_magicnum), i);
2bd0ea18
NS
42
43 if (!no_modify)
5e656dbb 44 agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
2bd0ea18
NS
45 }
46
5e656dbb 47 if (!XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum))) {
2bd0ea18 48 retval = XR_AG_AGF;
507f4e33 49 do_warn(_("bad version # %d for agf %d\n"),
5e656dbb 50 be32_to_cpu(agf->agf_versionnum), i);
2bd0ea18
NS
51
52 if (!no_modify)
5e656dbb 53 agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
2bd0ea18
NS
54 }
55
5e656dbb 56 if (be32_to_cpu(agf->agf_seqno) != i) {
2bd0ea18 57 retval = XR_AG_AGF;
507f4e33 58 do_warn(_("bad sequence # %d for agf %d\n"),
5e656dbb 59 be32_to_cpu(agf->agf_seqno), i);
2bd0ea18
NS
60
61 if (!no_modify)
5e656dbb 62 agf->agf_seqno = cpu_to_be32(i);
2bd0ea18
NS
63 }
64
5e656dbb 65 if (be32_to_cpu(agf->agf_length) != mp->m_sb.sb_agblocks) {
2bd0ea18
NS
66 if (i != mp->m_sb.sb_agcount - 1) {
67 retval = XR_AG_AGF;
507f4e33 68 do_warn(_("bad length %d for agf %d, should be %d\n"),
5e656dbb 69 be32_to_cpu(agf->agf_length), i,
507f4e33 70 mp->m_sb.sb_agblocks);
2bd0ea18 71 if (!no_modify)
f8149110 72 agf->agf_length =
5e656dbb 73 cpu_to_be32(mp->m_sb.sb_agblocks);
2bd0ea18
NS
74 } else {
75 agblocks = mp->m_sb.sb_dblocks -
5a35bf2c 76 (xfs_rfsblock_t) mp->m_sb.sb_agblocks * i;
2bd0ea18 77
5e656dbb 78 if (be32_to_cpu(agf->agf_length) != agblocks) {
2bd0ea18
NS
79 retval = XR_AG_AGF;
80 do_warn(
5d1b7f0f 81 _("bad length %d for agf %d, should be %" PRIu64 "\n"),
5e656dbb 82 be32_to_cpu(agf->agf_length),
507f4e33 83 i, agblocks);
2bd0ea18 84 if (!no_modify)
5e656dbb 85 agf->agf_length = cpu_to_be32(agblocks);
2bd0ea18
NS
86 }
87 }
88 }
89
90 /*
91 * check first/last AGF fields. if need be, lose the free
92 * space in the AGFL, we'll reclaim it later.
93 */
5e656dbb 94 if (be32_to_cpu(agf->agf_flfirst) >= XFS_AGFL_SIZE(mp)) {
5d1b7f0f
CH
95 do_warn(_("flfirst %d in agf %d too large (max = %zu)\n"),
96 be32_to_cpu(agf->agf_flfirst),
6aa32b47 97 i, XFS_AGFL_SIZE(mp) - 1);
2bd0ea18 98 if (!no_modify)
5e656dbb 99 agf->agf_flfirst = cpu_to_be32(0);
2bd0ea18
NS
100 }
101
5e656dbb 102 if (be32_to_cpu(agf->agf_fllast) >= XFS_AGFL_SIZE(mp)) {
5d1b7f0f
CH
103 do_warn(_("fllast %d in agf %d too large (max = %zu)\n"),
104 be32_to_cpu(agf->agf_fllast),
6aa32b47 105 i, XFS_AGFL_SIZE(mp) - 1);
2bd0ea18 106 if (!no_modify)
5e656dbb 107 agf->agf_fllast = cpu_to_be32(0);
2bd0ea18
NS
108 }
109
110 /* don't check freespace btrees -- will be checked by caller */
111
e0607266
DC
112 if (!xfs_sb_version_hascrc(&mp->m_sb))
113 return retval;
114
9c4e12fb 115 if (platform_uuid_compare(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid)) {
e0607266
DC
116 char uu[64];
117
118 retval = XR_AG_AGF;
119 platform_uuid_unparse(&agf->agf_uuid, uu);
120 do_warn(_("bad uuid %s for agf %d\n"), uu, i);
121
122 if (!no_modify)
9c4e12fb
ES
123 platform_uuid_copy(&agf->agf_uuid,
124 &mp->m_sb.sb_meta_uuid);
e0607266
DC
125 }
126 return retval;
2bd0ea18
NS
127}
128
8b8a6b02 129static int
5e656dbb 130verify_set_agi(xfs_mount_t *mp, xfs_agi_t *agi, xfs_agnumber_t agno)
2bd0ea18 131{
5a35bf2c 132 xfs_rfsblock_t agblocks;
2bd0ea18
NS
133 int retval = 0;
134
135 /* check common fields */
136
5e656dbb 137 if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) {
2bd0ea18 138 retval = XR_AG_AGI;
507f4e33 139 do_warn(_("bad magic # 0x%x for agi %d\n"),
5e656dbb 140 be32_to_cpu(agi->agi_magicnum), agno);
2bd0ea18
NS
141
142 if (!no_modify)
5e656dbb 143 agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
2bd0ea18
NS
144 }
145
5e656dbb 146 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum))) {
2bd0ea18 147 retval = XR_AG_AGI;
507f4e33 148 do_warn(_("bad version # %d for agi %d\n"),
5e656dbb 149 be32_to_cpu(agi->agi_versionnum), agno);
2bd0ea18
NS
150
151 if (!no_modify)
5e656dbb 152 agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
2bd0ea18
NS
153 }
154
5e656dbb 155 if (be32_to_cpu(agi->agi_seqno) != agno) {
2bd0ea18 156 retval = XR_AG_AGI;
507f4e33 157 do_warn(_("bad sequence # %d for agi %d\n"),
5e656dbb 158 be32_to_cpu(agi->agi_seqno), agno);
2bd0ea18
NS
159
160 if (!no_modify)
5e656dbb 161 agi->agi_seqno = cpu_to_be32(agno);
2bd0ea18
NS
162 }
163
5e656dbb
BN
164 if (be32_to_cpu(agi->agi_length) != mp->m_sb.sb_agblocks) {
165 if (agno != mp->m_sb.sb_agcount - 1) {
2bd0ea18 166 retval = XR_AG_AGI;
507f4e33 167 do_warn(_("bad length # %d for agi %d, should be %d\n"),
5e656dbb 168 be32_to_cpu(agi->agi_length), agno,
507f4e33 169 mp->m_sb.sb_agblocks);
2bd0ea18 170 if (!no_modify)
f8149110 171 agi->agi_length =
5e656dbb 172 cpu_to_be32(mp->m_sb.sb_agblocks);
2bd0ea18
NS
173 } else {
174 agblocks = mp->m_sb.sb_dblocks -
5a35bf2c 175 (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno;
2bd0ea18 176
5e656dbb 177 if (be32_to_cpu(agi->agi_length) != agblocks) {
2bd0ea18
NS
178 retval = XR_AG_AGI;
179 do_warn(
5d1b7f0f 180 _("bad length # %d for agi %d, should be %" PRIu64 "\n"),
5e656dbb
BN
181 be32_to_cpu(agi->agi_length),
182 agno, agblocks);
2bd0ea18 183 if (!no_modify)
5e656dbb 184 agi->agi_length = cpu_to_be32(agblocks);
2bd0ea18
NS
185 }
186 }
187 }
188
189 /* don't check inode btree -- will be checked by caller */
190
e0607266
DC
191 if (!xfs_sb_version_hascrc(&mp->m_sb))
192 return retval;
193
9c4e12fb 194 if (platform_uuid_compare(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid)) {
e0607266
DC
195 char uu[64];
196
197 retval = XR_AG_AGI;
198 platform_uuid_unparse(&agi->agi_uuid, uu);
199 do_warn(_("bad uuid %s for agi %d\n"), uu, agno);
200
201 if (!no_modify)
9c4e12fb
ES
202 platform_uuid_copy(&agi->agi_uuid,
203 &mp->m_sb.sb_meta_uuid);
e0607266
DC
204 }
205
206 return retval;
2bd0ea18
NS
207}
208
209/*
210 * superblock comparison - compare arbitrary superblock with
211 * filesystem mount-point superblock
212 *
213 * the verified fields include id and geometry.
8b8a6b02 214 *
2bd0ea18
NS
215 * the inprogress fields, version numbers, and counters
216 * are allowed to differ as well as all fields after the
dab9b8d6 217 * counters to cope with the pre-6.5 mkfs non-zeroed
2bd0ea18
NS
218 * secondary superblock sectors.
219 */
8b8a6b02 220static int
2bd0ea18
NS
221compare_sb(xfs_mount_t *mp, xfs_sb_t *sb)
222{
223 fs_geometry_t fs_geo, sb_geo;
224
225 get_sb_geometry(&fs_geo, &mp->m_sb);
226 get_sb_geometry(&sb_geo, sb);
227
228 if (memcmp(&fs_geo, &sb_geo,
229 (char *) &fs_geo.sb_shared_vn - (char *) &fs_geo))
230 return(XR_SB_GEO_MISMATCH);
231
232 return(XR_OK);
233}
234
235/*
bcedcddf
NS
236 * Possible fields that may have been set at mkfs time,
237 * sb_inoalignmt, sb_unit, sb_width and sb_dirblklog.
238 * The quota inode fields in the secondaries should be zero.
2bd0ea18
NS
239 * Likewise, the sb_flags and sb_shared_vn should also be
240 * zero and the shared version bit should be cleared for
241 * current mkfs's.
242 *
9440d84d
NS
243 * And everything else in the buffer beyond either sb_width,
244 * sb_dirblklog (v2 dirs), or sb_logsectsize can be zeroed.
245 *
246 * Note: contrary to the name, this routine is called for all
247 * superblocks, not just the secondary superblocks.
2bd0ea18 248 */
8b8a6b02 249static int
9c4e12fb 250secondary_sb_whack(
d085fb48
DC
251 struct xfs_mount *mp,
252 struct xfs_buf *sbuf,
253 struct xfs_sb *sb,
254 xfs_agnumber_t i)
2bd0ea18 255{
d085fb48
DC
256 struct xfs_dsb *dsb = XFS_BUF_TO_SBP(sbuf);
257 int do_bzero = 0;
258 int size;
259 char *ip;
260 int rval = 0;;
2110aea0 261 uuid_t tmpuuid;
2bd0ea18
NS
262
263 rval = do_bzero = 0;
264
265 /*
cbd7508d
ES
266 * Check for garbage beyond the last valid field.
267 * Use field addresses instead so this code will still
268 * work against older filesystems when the superblock
269 * gets rev'ed again with new fields appended.
270 *
271 * size is the size of data which is valid for this sb.
2bd0ea18 272 */
9c4e12fb
ES
273 if (xfs_sb_version_hasmetauuid(sb))
274 size = offsetof(xfs_sb_t, sb_meta_uuid)
275 + sizeof(sb->sb_meta_uuid);
276 else if (xfs_sb_version_hascrc(sb))
cbd7508d
ES
277 size = offsetof(xfs_sb_t, sb_lsn)
278 + sizeof(sb->sb_lsn);
279 else if (xfs_sb_version_hasmorebits(sb))
280 size = offsetof(xfs_sb_t, sb_bad_features2)
281 + sizeof(sb->sb_bad_features2);
282 else if (xfs_sb_version_haslogv2(sb))
283 size = offsetof(xfs_sb_t, sb_logsunit)
284 + sizeof(sb->sb_logsunit);
285 else if (xfs_sb_version_hassector(sb))
286 size = offsetof(xfs_sb_t, sb_logsectsize)
287 + sizeof(sb->sb_logsectsize);
5f6f3660 288 else /* only support dirv2 or more recent */
cbd7508d
ES
289 size = offsetof(xfs_sb_t, sb_dirblklog)
290 + sizeof(sb->sb_dirblklog);
cbd7508d
ES
291
292 /* Check the buffer we read from disk for garbage outside size */
293 for (ip = XFS_BUF_PTR(sbuf) + size;
294 ip < XFS_BUF_PTR(sbuf) + mp->m_sb.sb_sectsize;
295 ip++) {
296 if (*ip) {
297 do_bzero = 1;
298 break;
2bd0ea18
NS
299 }
300 }
cbd7508d
ES
301 if (do_bzero) {
302 rval |= XR_AG_SB_SEC;
303 if (!no_modify) {
304 do_warn(
305 _("zeroing unused portion of %s superblock (AG #%u)\n"),
306 !i ? _("primary") : _("secondary"), i);
307 /*
308 * zero both the in-memory sb and the disk buffer,
309 * because the former was read from disk and
310 * may contain newer version fields that shouldn't
311 * be set, and the latter is never updated past
312 * the last field - just zap them both.
313 */
2110aea0 314 memcpy(&tmpuuid, &sb->sb_meta_uuid, sizeof(uuid_t));
ee6cd73e 315 memset((void *)((intptr_t)sb + size), 0,
cbd7508d
ES
316 mp->m_sb.sb_sectsize - size);
317 memset(XFS_BUF_PTR(sbuf) + size, 0,
318 mp->m_sb.sb_sectsize - size);
2110aea0
DW
319 /* Preserve meta_uuid so we don't fail uuid checks */
320 memcpy(&sb->sb_meta_uuid, &tmpuuid, sizeof(uuid_t));
cbd7508d
ES
321 } else
322 do_warn(
323 _("would zero unused portion of %s superblock (AG #%u)\n"),
324 !i ? _("primary") : _("secondary"), i);
325 }
2bd0ea18
NS
326
327 /*
328 * now look for the fields we can manipulate directly.
dab9b8d6 329 * if we did a zero and that zero could have included
2bd0ea18
NS
330 * the field in question, just silently reset it. otherwise,
331 * complain.
332 *
333 * for now, just zero the flags field since only
334 * the readonly flag is used
335 */
336 if (sb->sb_flags) {
337 if (!no_modify)
338 sb->sb_flags = 0;
5f6f3660 339 if (!do_bzero) {
2bd0ea18 340 rval |= XR_AG_SB;
507f4e33 341 do_warn(_("bad flags field in superblock %d\n"), i);
2bd0ea18
NS
342 } else
343 rval |= XR_AG_SB_SEC;
344 }
345
346 /*
d085fb48
DC
347 * quota inodes and flags in secondary superblocks are never set by
348 * mkfs. However, they could be set in a secondary if a fs with quotas
349 * was growfs'ed since growfs copies the new primary into the
350 * secondaries.
351 *
352 * Also, the in-core inode flags now have different meaning to the
353 * on-disk flags, and so libxfs_sb_to_disk cannot directly write the
354 * sb_gquotino/sb_pquotino fields without specific sb_qflags being set.
355 * Hence we need to zero those fields directly in the sb buffer here.
2bd0ea18 356 */
d085fb48
DC
357
358 if (sb->sb_inprogress == 1 && sb->sb_uquotino != NULLFSINO) {
2bd0ea18
NS
359 if (!no_modify)
360 sb->sb_uquotino = 0;
5f6f3660 361 if (!do_bzero) {
2bd0ea18
NS
362 rval |= XR_AG_SB;
363 do_warn(
507f4e33 364 _("non-null user quota inode field in superblock %d\n"),
2bd0ea18 365 i);
507f4e33 366
2bd0ea18
NS
367 } else
368 rval |= XR_AG_SB_SEC;
369 }
370
d085fb48
DC
371 if (sb->sb_inprogress == 1 && sb->sb_gquotino != NULLFSINO) {
372 if (!no_modify) {
b36eef04 373 sb->sb_gquotino = 0;
d085fb48
DC
374 dsb->sb_gquotino = 0;
375 }
5f6f3660 376 if (!do_bzero) {
2bd0ea18
NS
377 rval |= XR_AG_SB;
378 do_warn(
507f4e33 379 _("non-null group quota inode field in superblock %d\n"),
2bd0ea18 380 i);
507f4e33 381
2bd0ea18
NS
382 } else
383 rval |= XR_AG_SB_SEC;
384 }
385
fa8fb25a
BF
386 /*
387 * Note that sb_pquotino is not considered a valid sb field for pre-v5
388 * superblocks. If it is anything other than 0 it is considered garbage
389 * data beyond the valid sb and explicitly zeroed above.
390 */
391 if (xfs_sb_version_has_pquotino(&mp->m_sb) &&
392 sb->sb_inprogress == 1 && sb->sb_pquotino != NULLFSINO) {
d085fb48 393 if (!no_modify) {
0340d706 394 sb->sb_pquotino = 0;
d085fb48
DC
395 dsb->sb_pquotino = 0;
396 }
5f6f3660 397 if (!do_bzero) {
0340d706
CS
398 rval |= XR_AG_SB;
399 do_warn(
400 _("non-null project quota inode field in superblock %d\n"),
401 i);
402
403 } else
404 rval |= XR_AG_SB_SEC;
405 }
406
2bd0ea18
NS
407 if (sb->sb_inprogress == 1 && sb->sb_qflags) {
408 if (!no_modify)
409 sb->sb_qflags = 0;
5f6f3660 410 if (!do_bzero) {
2bd0ea18 411 rval |= XR_AG_SB;
507f4e33
NS
412 do_warn(_("non-null quota flags in superblock %d\n"),
413 i);
2bd0ea18
NS
414 } else
415 rval |= XR_AG_SB_SEC;
416 }
417
418 /*
419 * if the secondaries agree on a stripe unit/width or inode
420 * alignment, those fields ought to be valid since they are
421 * written at mkfs time (and the corresponding sb version bits
422 * are set).
423 */
5e656dbb 424 if (!xfs_sb_version_hasalign(sb) && sb->sb_inoalignmt != 0) {
2bd0ea18
NS
425 if (!no_modify)
426 sb->sb_inoalignmt = 0;
5f6f3660 427 if (!do_bzero) {
2bd0ea18 428 rval |= XR_AG_SB;
507f4e33
NS
429 do_warn(
430 _("bad inode alignment field in superblock %d\n"),
2bd0ea18
NS
431 i);
432 } else
433 rval |= XR_AG_SB_SEC;
434 }
435
5e656dbb 436 if (!xfs_sb_version_hasdalign(sb) &&
2bd0ea18
NS
437 (sb->sb_unit != 0 || sb->sb_width != 0)) {
438 if (!no_modify)
439 sb->sb_unit = sb->sb_width = 0;
5f6f3660 440 if (!do_bzero) {
2bd0ea18
NS
441 rval |= XR_AG_SB;
442 do_warn(
507f4e33
NS
443 _("bad stripe unit/width fields in superblock %d\n"),
444 i);
445 } else
446 rval |= XR_AG_SB_SEC;
447 }
448
5e656dbb 449 if (!xfs_sb_version_hassector(sb) &&
507f4e33
NS
450 (sb->sb_sectsize != BBSIZE || sb->sb_sectlog != BBSHIFT ||
451 sb->sb_logsectsize != 0 || sb->sb_logsectlog != 0)) {
452 if (!no_modify) {
453 sb->sb_sectsize = BBSIZE;
454 sb->sb_sectlog = BBSHIFT;
455 sb->sb_logsectsize = 0;
456 sb->sb_logsectlog = 0;
457 }
5f6f3660 458 if (!do_bzero) {
507f4e33
NS
459 rval |= XR_AG_SB;
460 do_warn(
461 _("bad log/data device sector size fields in superblock %d\n"),
2bd0ea18
NS
462 i);
463 } else
464 rval |= XR_AG_SB_SEC;
465 }
466
467 return(rval);
468}
469
470/*
471 * verify and reset the ag header if required.
472 *
473 * lower 4 bits of rval are set depending on what got modified.
474 * (see agheader.h for more details)
475 *
476 * NOTE -- this routine does not tell the user that it has
477 * altered things. Rather, it is up to the caller to do so
478 * using the bits encoded into the return value.
479 */
480
481int
482verify_set_agheader(xfs_mount_t *mp, xfs_buf_t *sbuf, xfs_sb_t *sb,
483 xfs_agf_t *agf, xfs_agi_t *agi, xfs_agnumber_t i)
484{
485 int rval = 0;
486 int status = XR_OK;
487 int status_sb = XR_OK;
488
88f364a9 489 status = verify_sb(sbuf->b_addr, sb, (i == 0));
2bd0ea18
NS
490
491 if (status != XR_OK) {
507f4e33 492 do_warn(_("bad on-disk superblock %d - %s\n"),
2bd0ea18
NS
493 i, err_string(status));
494 }
495
496 status_sb = compare_sb(mp, sb);
497
498 if (status_sb != XR_OK) {
507f4e33 499 do_warn(_("primary/secondary superblock %d conflict - %s\n"),
2bd0ea18
NS
500 i, err_string(status_sb));
501 }
502
503 if (status != XR_OK || status_sb != XR_OK) {
504 if (!no_modify) {
505 *sb = mp->m_sb;
506
507 /*
508 * clear the more transient fields
509 */
510 sb->sb_inprogress = 1;
511
512 sb->sb_icount = 0;
513 sb->sb_ifree = 0;
514 sb->sb_fdblocks = 0;
515 sb->sb_frextents = 0;
516
517 sb->sb_qflags = 0;
518 }
519
520 rval |= XR_AG_SB;
521 }
522
9c4e12fb 523 rval |= secondary_sb_whack(mp, sbuf, sb, i);
2bd0ea18
NS
524
525 rval |= verify_set_agf(mp, agf, i);
526 rval |= verify_set_agi(mp, agi, i);
527
528 return(rval);
529}