]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/agheader.c
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
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
7 * published by the Free Software Foundation.
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.
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
23 #include "err_protos.h"
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?
31 verify_set_agf(xfs_mount_t
*mp
, xfs_agf_t
*agf
, xfs_agnumber_t i
)
33 xfs_drfsbno_t agblocks
;
36 /* check common fields */
38 if (be32_to_cpu(agf
->agf_magicnum
) != XFS_AGF_MAGIC
) {
40 do_warn(_("bad magic # 0x%x for agf %d\n"),
41 be32_to_cpu(agf
->agf_magicnum
), i
);
44 agf
->agf_magicnum
= cpu_to_be32(XFS_AGF_MAGIC
);
47 if (!XFS_AGF_GOOD_VERSION(be32_to_cpu(agf
->agf_versionnum
))) {
49 do_warn(_("bad version # %d for agf %d\n"),
50 be32_to_cpu(agf
->agf_versionnum
), i
);
53 agf
->agf_versionnum
= cpu_to_be32(XFS_AGF_VERSION
);
56 if (be32_to_cpu(agf
->agf_seqno
) != i
) {
58 do_warn(_("bad sequence # %d for agf %d\n"),
59 be32_to_cpu(agf
->agf_seqno
), i
);
62 agf
->agf_seqno
= cpu_to_be32(i
);
65 if (be32_to_cpu(agf
->agf_length
) != mp
->m_sb
.sb_agblocks
) {
66 if (i
!= mp
->m_sb
.sb_agcount
- 1) {
68 do_warn(_("bad length %d for agf %d, should be %d\n"),
69 be32_to_cpu(agf
->agf_length
), i
,
70 mp
->m_sb
.sb_agblocks
);
73 cpu_to_be32(mp
->m_sb
.sb_agblocks
);
75 agblocks
= mp
->m_sb
.sb_dblocks
-
76 (xfs_drfsbno_t
) mp
->m_sb
.sb_agblocks
* i
;
78 if (be32_to_cpu(agf
->agf_length
) != agblocks
) {
81 _("bad length %d for agf %d, should be %" PRIu64
"\n"),
82 be32_to_cpu(agf
->agf_length
),
85 agf
->agf_length
= cpu_to_be32(agblocks
);
91 * check first/last AGF fields. if need be, lose the free
92 * space in the AGFL, we'll reclaim it later.
94 if (be32_to_cpu(agf
->agf_flfirst
) >= XFS_AGFL_SIZE(mp
)) {
95 do_warn(_("flfirst %d in agf %d too large (max = %zu)\n"),
96 be32_to_cpu(agf
->agf_flfirst
),
97 i
, XFS_AGFL_SIZE(mp
));
99 agf
->agf_flfirst
= cpu_to_be32(0);
102 if (be32_to_cpu(agf
->agf_fllast
) >= XFS_AGFL_SIZE(mp
)) {
103 do_warn(_("fllast %d in agf %d too large (max = %zu)\n"),
104 be32_to_cpu(agf
->agf_fllast
),
105 i
, XFS_AGFL_SIZE(mp
));
107 agf
->agf_fllast
= cpu_to_be32(0);
110 /* don't check freespace btrees -- will be checked by caller */
112 if (!xfs_sb_version_hascrc(&mp
->m_sb
))
115 if (platform_uuid_compare(&agf
->agf_uuid
, &mp
->m_sb
.sb_uuid
)) {
119 platform_uuid_unparse(&agf
->agf_uuid
, uu
);
120 do_warn(_("bad uuid %s for agf %d\n"), uu
, i
);
123 platform_uuid_copy(&agf
->agf_uuid
, &mp
->m_sb
.sb_uuid
);
129 verify_set_agi(xfs_mount_t
*mp
, xfs_agi_t
*agi
, xfs_agnumber_t agno
)
131 xfs_drfsbno_t agblocks
;
134 /* check common fields */
136 if (be32_to_cpu(agi
->agi_magicnum
) != XFS_AGI_MAGIC
) {
138 do_warn(_("bad magic # 0x%x for agi %d\n"),
139 be32_to_cpu(agi
->agi_magicnum
), agno
);
142 agi
->agi_magicnum
= cpu_to_be32(XFS_AGI_MAGIC
);
145 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi
->agi_versionnum
))) {
147 do_warn(_("bad version # %d for agi %d\n"),
148 be32_to_cpu(agi
->agi_versionnum
), agno
);
151 agi
->agi_versionnum
= cpu_to_be32(XFS_AGI_VERSION
);
154 if (be32_to_cpu(agi
->agi_seqno
) != agno
) {
156 do_warn(_("bad sequence # %d for agi %d\n"),
157 be32_to_cpu(agi
->agi_seqno
), agno
);
160 agi
->agi_seqno
= cpu_to_be32(agno
);
163 if (be32_to_cpu(agi
->agi_length
) != mp
->m_sb
.sb_agblocks
) {
164 if (agno
!= mp
->m_sb
.sb_agcount
- 1) {
166 do_warn(_("bad length # %d for agi %d, should be %d\n"),
167 be32_to_cpu(agi
->agi_length
), agno
,
168 mp
->m_sb
.sb_agblocks
);
171 cpu_to_be32(mp
->m_sb
.sb_agblocks
);
173 agblocks
= mp
->m_sb
.sb_dblocks
-
174 (xfs_drfsbno_t
) mp
->m_sb
.sb_agblocks
* agno
;
176 if (be32_to_cpu(agi
->agi_length
) != agblocks
) {
179 _("bad length # %d for agi %d, should be %" PRIu64
"\n"),
180 be32_to_cpu(agi
->agi_length
),
183 agi
->agi_length
= cpu_to_be32(agblocks
);
188 /* don't check inode btree -- will be checked by caller */
190 if (!xfs_sb_version_hascrc(&mp
->m_sb
))
193 if (platform_uuid_compare(&agi
->agi_uuid
, &mp
->m_sb
.sb_uuid
)) {
197 platform_uuid_unparse(&agi
->agi_uuid
, uu
);
198 do_warn(_("bad uuid %s for agi %d\n"), uu
, agno
);
201 platform_uuid_copy(&agi
->agi_uuid
, &mp
->m_sb
.sb_uuid
);
208 * superblock comparison - compare arbitrary superblock with
209 * filesystem mount-point superblock
211 * the verified fields include id and geometry.
213 * the inprogress fields, version numbers, and counters
214 * are allowed to differ as well as all fields after the
215 * counters to cope with the pre-6.5 mkfs non-zeroed
216 * secondary superblock sectors.
219 compare_sb(xfs_mount_t
*mp
, xfs_sb_t
*sb
)
221 fs_geometry_t fs_geo
, sb_geo
;
223 get_sb_geometry(&fs_geo
, &mp
->m_sb
);
224 get_sb_geometry(&sb_geo
, sb
);
226 if (memcmp(&fs_geo
, &sb_geo
,
227 (char *) &fs_geo
.sb_shared_vn
- (char *) &fs_geo
))
228 return(XR_SB_GEO_MISMATCH
);
234 * Possible fields that may have been set at mkfs time,
235 * sb_inoalignmt, sb_unit, sb_width and sb_dirblklog.
236 * The quota inode fields in the secondaries should be zero.
237 * Likewise, the sb_flags and sb_shared_vn should also be
238 * zero and the shared version bit should be cleared for
241 * And everything else in the buffer beyond either sb_width,
242 * sb_dirblklog (v2 dirs), or sb_logsectsize can be zeroed.
244 * Note: contrary to the name, this routine is called for all
245 * superblocks, not just the secondary superblocks.
248 secondary_sb_wack(xfs_mount_t
*mp
, xfs_buf_t
*sbuf
, xfs_sb_t
*sb
,
259 * mkfs's that stamped a feature bit besides the ones in the mask
260 * (e.g. were pre-6.5 beta) could leave garbage in the secondary
261 * superblock sectors. Anything stamping the shared fs bit or better
262 * into the secondaries is ok and should generate clean secondary
263 * superblock sectors. so only run the zero check on the
264 * potentially garbaged secondaries.
267 (sb
->sb_versionnum
& XR_GOOD_SECSB_VNMASK
) == 0 ||
268 sb
->sb_versionnum
< XFS_SB_VERSION_4
) {
270 * Check for garbage beyond the last field.
271 * Use field addresses instead so this code will still
272 * work against older filesystems when the superblock
273 * gets rev'ed again with new fields appended.
275 if (xfs_sb_version_hasmorebits(sb
))
276 size
= (__psint_t
)&sb
->sb_features2
277 + sizeof(sb
->sb_features2
) - (__psint_t
)sb
;
278 else if (xfs_sb_version_haslogv2(sb
))
279 size
= (__psint_t
)&sb
->sb_logsunit
280 + sizeof(sb
->sb_logsunit
) - (__psint_t
)sb
;
281 else if (xfs_sb_version_hassector(sb
))
282 size
= (__psint_t
)&sb
->sb_logsectsize
283 + sizeof(sb
->sb_logsectsize
) - (__psint_t
)sb
;
284 else if (xfs_sb_version_hasdirv2(sb
))
285 size
= (__psint_t
)&sb
->sb_dirblklog
286 + sizeof(sb
->sb_dirblklog
) - (__psint_t
)sb
;
288 size
= (__psint_t
)&sb
->sb_width
289 + sizeof(sb
->sb_width
) - (__psint_t
)sb
;
290 for (ip
= (char *)((__psint_t
)sb
+ size
);
291 ip
< (char *)((__psint_t
)sb
+ mp
->m_sb
.sb_sectsize
);
300 rval
|= XR_AG_SB_SEC
;
303 _("zeroing unused portion of %s superblock (AG #%u)\n"),
304 !i
? _("primary") : _("secondary"), i
);
305 memset((void *)((__psint_t
)sb
+ size
), 0,
306 mp
->m_sb
.sb_sectsize
- size
);
309 _("would zero unused portion of %s superblock (AG #%u)\n"),
310 !i
? _("primary") : _("secondary"), i
);
315 * now look for the fields we can manipulate directly.
316 * if we did a zero and that zero could have included
317 * the field in question, just silently reset it. otherwise,
320 * for now, just zero the flags field since only
321 * the readonly flag is used
326 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
328 do_warn(_("bad flags field in superblock %d\n"), i
);
330 rval
|= XR_AG_SB_SEC
;
334 * quota inodes and flags in secondary superblocks
335 * are never set by mkfs. However, they could be set
336 * in a secondary if a fs with quotas was growfs'ed since
337 * growfs copies the new primary into the secondaries.
339 if (sb
->sb_inprogress
== 1 && sb
->sb_uquotino
) {
342 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
345 _("non-null user quota inode field in superblock %d\n"),
349 rval
|= XR_AG_SB_SEC
;
352 if (sb
->sb_inprogress
== 1 && sb
->sb_gquotino
) {
355 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
358 _("non-null group quota inode field in superblock %d\n"),
362 rval
|= XR_AG_SB_SEC
;
365 if (sb
->sb_inprogress
== 1 && sb
->sb_pquotino
) {
368 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
371 _("non-null project quota inode field in superblock %d\n"),
375 rval
|= XR_AG_SB_SEC
;
378 if (sb
->sb_inprogress
== 1 && sb
->sb_qflags
) {
381 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
383 do_warn(_("non-null quota flags in superblock %d\n"),
386 rval
|= XR_AG_SB_SEC
;
390 * if the secondaries agree on a stripe unit/width or inode
391 * alignment, those fields ought to be valid since they are
392 * written at mkfs time (and the corresponding sb version bits
395 if (!xfs_sb_version_hasshared(sb
) && sb
->sb_shared_vn
!= 0) {
397 sb
->sb_shared_vn
= 0;
398 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
401 _("bad shared version number in superblock %d\n"),
404 rval
|= XR_AG_SB_SEC
;
407 if (!xfs_sb_version_hasalign(sb
) && sb
->sb_inoalignmt
!= 0) {
409 sb
->sb_inoalignmt
= 0;
410 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
413 _("bad inode alignment field in superblock %d\n"),
416 rval
|= XR_AG_SB_SEC
;
419 if (!xfs_sb_version_hasdalign(sb
) &&
420 (sb
->sb_unit
!= 0 || sb
->sb_width
!= 0)) {
422 sb
->sb_unit
= sb
->sb_width
= 0;
423 if (sb
->sb_versionnum
& XR_GOOD_SECSB_VNMASK
|| !do_bzero
) {
426 _("bad stripe unit/width fields in superblock %d\n"),
429 rval
|= XR_AG_SB_SEC
;
432 if (!xfs_sb_version_hassector(sb
) &&
433 (sb
->sb_sectsize
!= BBSIZE
|| sb
->sb_sectlog
!= BBSHIFT
||
434 sb
->sb_logsectsize
!= 0 || sb
->sb_logsectlog
!= 0)) {
436 sb
->sb_sectsize
= BBSIZE
;
437 sb
->sb_sectlog
= BBSHIFT
;
438 sb
->sb_logsectsize
= 0;
439 sb
->sb_logsectlog
= 0;
441 if (sb
->sb_versionnum
& XR_GOOD_SECSB_VNMASK
|| !do_bzero
) {
444 _("bad log/data device sector size fields in superblock %d\n"),
447 rval
|= XR_AG_SB_SEC
;
454 * verify and reset the ag header if required.
456 * lower 4 bits of rval are set depending on what got modified.
457 * (see agheader.h for more details)
459 * NOTE -- this routine does not tell the user that it has
460 * altered things. Rather, it is up to the caller to do so
461 * using the bits encoded into the return value.
465 verify_set_agheader(xfs_mount_t
*mp
, xfs_buf_t
*sbuf
, xfs_sb_t
*sb
,
466 xfs_agf_t
*agf
, xfs_agi_t
*agi
, xfs_agnumber_t i
)
470 int status_sb
= XR_OK
;
472 status
= verify_sb(sb
, (i
== 0));
474 if (status
!= XR_OK
) {
475 do_warn(_("bad on-disk superblock %d - %s\n"),
476 i
, err_string(status
));
479 status_sb
= compare_sb(mp
, sb
);
481 if (status_sb
!= XR_OK
) {
482 do_warn(_("primary/secondary superblock %d conflict - %s\n"),
483 i
, err_string(status_sb
));
486 if (status
!= XR_OK
|| status_sb
!= XR_OK
) {
491 * clear the more transient fields
493 sb
->sb_inprogress
= 1;
498 sb
->sb_frextents
= 0;
506 rval
|= secondary_sb_wack(mp
, sbuf
, sb
, i
);
508 rval
|= verify_set_agf(mp
, agf
, i
);
509 rval
|= verify_set_agi(mp
, agi
, i
);