]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/agheader.c
xfs_repair: check the ftype of dot and dotdot directory entries
[thirdparty/xfsprogs-dev.git] / repair / agheader.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6
7 #include "libxfs.h"
8 #include "globals.h"
9 #include "agheader.h"
10 #include "protos.h"
11 #include "err_protos.h"
12
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
18 static int
19 verify_set_agf(xfs_mount_t *mp, xfs_agf_t *agf, xfs_agnumber_t i)
20 {
21 xfs_rfsblock_t agblocks;
22 int retval = 0;
23
24 /* check common fields */
25
26 if (be32_to_cpu(agf->agf_magicnum) != XFS_AGF_MAGIC) {
27 retval = XR_AG_AGF;
28 do_warn(_("bad magic # 0x%x for agf %d\n"),
29 be32_to_cpu(agf->agf_magicnum), i);
30
31 if (!no_modify)
32 agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
33 }
34
35 if (!XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum))) {
36 retval = XR_AG_AGF;
37 do_warn(_("bad version # %d for agf %d\n"),
38 be32_to_cpu(agf->agf_versionnum), i);
39
40 if (!no_modify)
41 agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
42 }
43
44 if (be32_to_cpu(agf->agf_seqno) != i) {
45 retval = XR_AG_AGF;
46 do_warn(_("bad sequence # %d for agf %d\n"),
47 be32_to_cpu(agf->agf_seqno), i);
48
49 if (!no_modify)
50 agf->agf_seqno = cpu_to_be32(i);
51 }
52
53 if (be32_to_cpu(agf->agf_length) != mp->m_sb.sb_agblocks) {
54 if (i != mp->m_sb.sb_agcount - 1) {
55 retval = XR_AG_AGF;
56 do_warn(_("bad length %d for agf %d, should be %d\n"),
57 be32_to_cpu(agf->agf_length), i,
58 mp->m_sb.sb_agblocks);
59 if (!no_modify)
60 agf->agf_length =
61 cpu_to_be32(mp->m_sb.sb_agblocks);
62 } else {
63 agblocks = mp->m_sb.sb_dblocks -
64 (xfs_rfsblock_t) mp->m_sb.sb_agblocks * i;
65
66 if (be32_to_cpu(agf->agf_length) != agblocks) {
67 retval = XR_AG_AGF;
68 do_warn(
69 _("bad length %d for agf %d, should be %" PRIu64 "\n"),
70 be32_to_cpu(agf->agf_length),
71 i, agblocks);
72 if (!no_modify)
73 agf->agf_length = cpu_to_be32(agblocks);
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 */
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"),
84 be32_to_cpu(agf->agf_flfirst),
85 i, libxfs_agfl_size(mp) - 1);
86 if (!no_modify)
87 agf->agf_flfirst = cpu_to_be32(0);
88 }
89
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"),
92 be32_to_cpu(agf->agf_fllast),
93 i, libxfs_agfl_size(mp) - 1);
94 if (!no_modify)
95 agf->agf_fllast = cpu_to_be32(0);
96 }
97
98 /* don't check freespace btrees -- will be checked by caller */
99
100 if (!xfs_has_crc(mp))
101 return retval;
102
103 if (platform_uuid_compare(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid)) {
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)
111 platform_uuid_copy(&agf->agf_uuid,
112 &mp->m_sb.sb_meta_uuid);
113 }
114 return retval;
115 }
116
117 static int
118 verify_set_agi(xfs_mount_t *mp, xfs_agi_t *agi, xfs_agnumber_t agno)
119 {
120 xfs_rfsblock_t agblocks;
121 int retval = 0;
122
123 /* check common fields */
124
125 if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) {
126 retval = XR_AG_AGI;
127 do_warn(_("bad magic # 0x%x for agi %d\n"),
128 be32_to_cpu(agi->agi_magicnum), agno);
129
130 if (!no_modify)
131 agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
132 }
133
134 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum))) {
135 retval = XR_AG_AGI;
136 do_warn(_("bad version # %d for agi %d\n"),
137 be32_to_cpu(agi->agi_versionnum), agno);
138
139 if (!no_modify)
140 agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
141 }
142
143 if (be32_to_cpu(agi->agi_seqno) != agno) {
144 retval = XR_AG_AGI;
145 do_warn(_("bad sequence # %d for agi %d\n"),
146 be32_to_cpu(agi->agi_seqno), agno);
147
148 if (!no_modify)
149 agi->agi_seqno = cpu_to_be32(agno);
150 }
151
152 if (be32_to_cpu(agi->agi_length) != mp->m_sb.sb_agblocks) {
153 if (agno != mp->m_sb.sb_agcount - 1) {
154 retval = XR_AG_AGI;
155 do_warn(_("bad length # %d for agi %d, should be %d\n"),
156 be32_to_cpu(agi->agi_length), agno,
157 mp->m_sb.sb_agblocks);
158 if (!no_modify)
159 agi->agi_length =
160 cpu_to_be32(mp->m_sb.sb_agblocks);
161 } else {
162 agblocks = mp->m_sb.sb_dblocks -
163 (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno;
164
165 if (be32_to_cpu(agi->agi_length) != agblocks) {
166 retval = XR_AG_AGI;
167 do_warn(
168 _("bad length # %d for agi %d, should be %" PRIu64 "\n"),
169 be32_to_cpu(agi->agi_length),
170 agno, agblocks);
171 if (!no_modify)
172 agi->agi_length = cpu_to_be32(agblocks);
173 }
174 }
175 }
176
177 /* don't check inode btree -- will be checked by caller */
178
179 if (!xfs_has_crc(mp))
180 return retval;
181
182 if (platform_uuid_compare(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid)) {
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)
190 platform_uuid_copy(&agi->agi_uuid,
191 &mp->m_sb.sb_meta_uuid);
192 }
193
194 return retval;
195 }
196
197 /*
198 * superblock comparison - compare arbitrary superblock with
199 * filesystem mount-point superblock
200 *
201 * the verified fields include id and geometry.
202 *
203 * the inprogress fields, version numbers, and counters
204 * are allowed to differ as well as all fields after the
205 * counters to cope with the pre-6.5 mkfs non-zeroed
206 * secondary superblock sectors.
207 */
208 static int
209 compare_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
223 /*
224 * If the fs feature bits on a secondary superblock don't match the
225 * primary, we need to update them.
226 */
227 static inline int
228 check_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
288 if (mp->m_sb.sb_features_log_incompat != sb->sb_features_log_incompat) {
289 if (no_modify) {
290 do_warn(
291 _("would fix log incompat feature mismatch in AG %u super, 0x%x != 0x%x\n"),
292 agno, mp->m_sb.sb_features_log_incompat,
293 sb->sb_features_log_incompat);
294 } else {
295 do_warn(
296 _("will fix log incompat feature mismatch in AG %u super, 0x%x != 0x%x\n"),
297 agno, mp->m_sb.sb_features_log_incompat,
298 sb->sb_features_log_incompat);
299 dirty = true;
300 }
301 }
302
303 if (!dirty)
304 return 0;
305
306 sb->sb_features_compat = mp->m_sb.sb_features_compat;
307 sb->sb_features_ro_compat = mp->m_sb.sb_features_ro_compat;
308 sb->sb_features_incompat = mp->m_sb.sb_features_incompat;
309 sb->sb_features_log_incompat = mp->m_sb.sb_features_log_incompat;
310 return XR_AG_SB_SEC;
311 }
312
313 /*
314 * Possible fields that may have been set at mkfs time,
315 * sb_inoalignmt, sb_unit, sb_width and sb_dirblklog.
316 * The quota inode fields in the secondaries should be zero.
317 * Likewise, the sb_flags and sb_shared_vn should also be
318 * zero and the shared version bit should be cleared for
319 * current mkfs's.
320 *
321 * And everything else in the buffer beyond either sb_width,
322 * sb_dirblklog (v2 dirs), or sb_logsectsize can be zeroed.
323 *
324 * Note: contrary to the name, this routine is called for all
325 * superblocks, not just the secondary superblocks.
326 */
327 static int
328 secondary_sb_whack(
329 struct xfs_mount *mp,
330 struct xfs_buf *sbuf,
331 struct xfs_sb *sb,
332 xfs_agnumber_t i)
333 {
334 struct xfs_dsb *dsb = sbuf->b_addr;
335 int do_bzero = 0;
336 int size;
337 char *ip;
338 int rval = 0;
339 uuid_t tmpuuid;
340
341 rval = do_bzero = 0;
342
343 /*
344 * Check for garbage beyond the last valid field.
345 * Use field addresses instead so this code will still
346 * work against older filesystems when the superblock
347 * gets rev'ed again with new fields appended.
348 *
349 * size is the size of data which is valid for this sb.
350 */
351 if (xfs_sb_version_hasmetauuid(sb))
352 size = offsetof(xfs_sb_t, sb_meta_uuid)
353 + sizeof(sb->sb_meta_uuid);
354 else if (xfs_sb_version_hascrc(sb))
355 size = offsetof(xfs_sb_t, sb_lsn)
356 + sizeof(sb->sb_lsn);
357 else if (xfs_sb_version_hasmorebits(sb))
358 size = offsetof(xfs_sb_t, sb_bad_features2)
359 + sizeof(sb->sb_bad_features2);
360 else if (xfs_sb_version_haslogv2(sb))
361 size = offsetof(xfs_sb_t, sb_logsunit)
362 + sizeof(sb->sb_logsunit);
363 else if (xfs_sb_version_hassector(sb))
364 size = offsetof(xfs_sb_t, sb_logsectsize)
365 + sizeof(sb->sb_logsectsize);
366 else /* only support dirv2 or more recent */
367 size = offsetof(xfs_sb_t, sb_dirblklog)
368 + sizeof(sb->sb_dirblklog);
369
370 /* Check the buffer we read from disk for garbage outside size */
371 for (ip = (char *)sbuf->b_addr + size;
372 ip < (char *)sbuf->b_addr + mp->m_sb.sb_sectsize;
373 ip++) {
374 if (*ip) {
375 do_bzero = 1;
376 break;
377 }
378 }
379 if (do_bzero) {
380 rval |= XR_AG_SB_SEC;
381 if (!no_modify) {
382 do_warn(
383 _("zeroing unused portion of %s superblock (AG #%u)\n"),
384 !i ? _("primary") : _("secondary"), i);
385 /*
386 * zero both the in-memory sb and the disk buffer,
387 * because the former was read from disk and
388 * may contain newer version fields that shouldn't
389 * be set, and the latter is never updated past
390 * the last field - just zap them both.
391 */
392 memcpy(&tmpuuid, &sb->sb_meta_uuid, sizeof(uuid_t));
393 memset((void *)((intptr_t)sb + size), 0,
394 mp->m_sb.sb_sectsize - size);
395 memset((char *)sbuf->b_addr + size, 0,
396 mp->m_sb.sb_sectsize - size);
397 /* Preserve meta_uuid so we don't fail uuid checks */
398 memcpy(&sb->sb_meta_uuid, &tmpuuid, sizeof(uuid_t));
399 } else
400 do_warn(
401 _("would zero unused portion of %s superblock (AG #%u)\n"),
402 !i ? _("primary") : _("secondary"), i);
403 }
404
405 /*
406 * now look for the fields we can manipulate directly.
407 * if we did a zero and that zero could have included
408 * the field in question, just silently reset it. otherwise,
409 * complain.
410 *
411 * for now, just zero the flags field since only
412 * the readonly flag is used
413 */
414 if (sb->sb_flags) {
415 if (!no_modify)
416 sb->sb_flags = 0;
417 if (!do_bzero) {
418 rval |= XR_AG_SB;
419 do_warn(_("bad flags field in superblock %d\n"), i);
420 } else
421 rval |= XR_AG_SB_SEC;
422 }
423
424 /*
425 * quota inodes and flags in secondary superblocks are never set by
426 * mkfs. However, they could be set in a secondary if a fs with quotas
427 * was growfs'ed since growfs copies the new primary into the
428 * secondaries.
429 *
430 * Also, the in-core inode flags now have different meaning to the
431 * on-disk flags, and so libxfs_sb_to_disk cannot directly write the
432 * sb_gquotino/sb_pquotino fields without specific sb_qflags being set.
433 * Hence we need to zero those fields directly in the sb buffer here.
434 */
435
436 if (sb->sb_inprogress == 1 && sb->sb_uquotino != NULLFSINO) {
437 if (!no_modify)
438 sb->sb_uquotino = 0;
439 if (!do_bzero) {
440 rval |= XR_AG_SB;
441 do_warn(
442 _("non-null user quota inode field in superblock %d\n"),
443 i);
444
445 } else
446 rval |= XR_AG_SB_SEC;
447 }
448
449 if (sb->sb_inprogress == 1 && sb->sb_gquotino != NULLFSINO) {
450 if (!no_modify) {
451 sb->sb_gquotino = 0;
452 dsb->sb_gquotino = 0;
453 }
454 if (!do_bzero) {
455 rval |= XR_AG_SB;
456 do_warn(
457 _("non-null group quota inode field in superblock %d\n"),
458 i);
459
460 } else
461 rval |= XR_AG_SB_SEC;
462 }
463
464 /*
465 * Note that sb_pquotino is not considered a valid sb field for pre-v5
466 * superblocks. If it is anything other than 0 it is considered garbage
467 * data beyond the valid sb and explicitly zeroed above.
468 */
469 if (xfs_has_pquotino(mp) &&
470 sb->sb_inprogress == 1 && sb->sb_pquotino != NULLFSINO) {
471 if (!no_modify) {
472 sb->sb_pquotino = 0;
473 dsb->sb_pquotino = 0;
474 }
475 if (!do_bzero) {
476 rval |= XR_AG_SB;
477 do_warn(
478 _("non-null project quota inode field in superblock %d\n"),
479 i);
480
481 } else
482 rval |= XR_AG_SB_SEC;
483 }
484
485 if (sb->sb_inprogress == 1 && sb->sb_qflags) {
486 if (!no_modify)
487 sb->sb_qflags = 0;
488 if (!do_bzero) {
489 rval |= XR_AG_SB;
490 do_warn(_("non-null quota flags in superblock %d\n"),
491 i);
492 } else
493 rval |= XR_AG_SB_SEC;
494 }
495
496 /*
497 * if the secondaries agree on a stripe unit/width or inode
498 * alignment, those fields ought to be valid since they are
499 * written at mkfs time (and the corresponding sb version bits
500 * are set).
501 */
502 if (!xfs_sb_version_hasalign(sb) && sb->sb_inoalignmt != 0) {
503 if (!no_modify)
504 sb->sb_inoalignmt = 0;
505 if (!do_bzero) {
506 rval |= XR_AG_SB;
507 do_warn(
508 _("bad inode alignment field in superblock %d\n"),
509 i);
510 } else
511 rval |= XR_AG_SB_SEC;
512 }
513
514 if (!xfs_sb_version_hasdalign(sb) &&
515 (sb->sb_unit != 0 || sb->sb_width != 0)) {
516 if (!no_modify)
517 sb->sb_unit = sb->sb_width = 0;
518 if (!do_bzero) {
519 rval |= XR_AG_SB;
520 do_warn(
521 _("bad stripe unit/width fields in superblock %d\n"),
522 i);
523 } else
524 rval |= XR_AG_SB_SEC;
525 }
526
527 if (!xfs_sb_version_hassector(sb) &&
528 (sb->sb_sectsize != BBSIZE || sb->sb_sectlog != BBSHIFT ||
529 sb->sb_logsectsize != 0 || sb->sb_logsectlog != 0)) {
530 if (!no_modify) {
531 sb->sb_sectsize = BBSIZE;
532 sb->sb_sectlog = BBSHIFT;
533 sb->sb_logsectsize = 0;
534 sb->sb_logsectlog = 0;
535 }
536 if (!do_bzero) {
537 rval |= XR_AG_SB;
538 do_warn(
539 _("bad log/data device sector size fields in superblock %d\n"),
540 i);
541 } else
542 rval |= XR_AG_SB_SEC;
543 }
544
545 rval |= check_v5_feature_mismatch(mp, i, sb);
546
547 if (xfs_sb_version_needsrepair(sb)) {
548 if (i == 0) {
549 if (!no_modify)
550 do_warn(
551 _("clearing needsrepair flag and regenerating metadata\n"));
552 else
553 do_warn(
554 _("would clear needsrepair flag and regenerate metadata\n"));
555 } else {
556 /*
557 * Quietly clear needsrepair on the secondary supers as
558 * part of ensuring them. If needsrepair is set on the
559 * primary, it will be cleared at the end of repair
560 * once we've flushed all other dirty blocks to disk.
561 */
562 sb->sb_features_incompat &=
563 ~XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
564 rval |= XR_AG_SB_SEC;
565 }
566 }
567
568 return(rval);
569 }
570
571 /*
572 * verify and reset the ag header if required.
573 *
574 * lower 4 bits of rval are set depending on what got modified.
575 * (see agheader.h for more details)
576 *
577 * NOTE -- this routine does not tell the user that it has
578 * altered things. Rather, it is up to the caller to do so
579 * using the bits encoded into the return value.
580 */
581
582 int
583 verify_set_agheader(xfs_mount_t *mp, struct xfs_buf *sbuf, xfs_sb_t *sb,
584 xfs_agf_t *agf, xfs_agi_t *agi, xfs_agnumber_t i)
585 {
586 int rval = 0;
587 int status = XR_OK;
588 int status_sb = XR_OK;
589
590 status = verify_sb(sbuf->b_addr, sb, (i == 0));
591
592 if (status != XR_OK) {
593 do_warn(_("bad on-disk superblock %d - %s\n"),
594 i, err_string(status));
595 }
596
597 status_sb = compare_sb(mp, sb);
598
599 if (status_sb != XR_OK) {
600 do_warn(_("primary/secondary superblock %d conflict - %s\n"),
601 i, err_string(status_sb));
602 }
603
604 if (status != XR_OK || status_sb != XR_OK) {
605 if (!no_modify) {
606 *sb = mp->m_sb;
607
608 /*
609 * clear the more transient fields
610 */
611 sb->sb_inprogress = 1;
612
613 sb->sb_icount = 0;
614 sb->sb_ifree = 0;
615 sb->sb_fdblocks = 0;
616 sb->sb_frextents = 0;
617
618 sb->sb_qflags = 0;
619 }
620
621 rval |= XR_AG_SB;
622 }
623
624 rval |= secondary_sb_whack(mp, sbuf, sb, i);
625
626 rval |= verify_set_agf(mp, agf, i);
627 rval |= verify_set_agi(mp, agi, i);
628
629 return(rval);
630 }