]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/agheader.c
2 * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
37 #include "err_protos.h"
40 verify_set_agf(xfs_mount_t
*mp
, xfs_agf_t
*agf
, xfs_agnumber_t i
)
42 xfs_drfsbno_t agblocks
;
45 /* check common fields */
47 if (INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
) != XFS_AGF_MAGIC
) {
49 do_warn(_("bad magic # 0x%x for agf %d\n"),
50 INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
), i
);
53 INT_SET(agf
->agf_magicnum
, ARCH_CONVERT
, XFS_AGF_MAGIC
);
56 if (!XFS_AGF_GOOD_VERSION(INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
))) {
58 do_warn(_("bad version # %d for agf %d\n"),
59 INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
), i
);
62 INT_SET(agf
->agf_versionnum
, ARCH_CONVERT
,
66 if (INT_GET(agf
->agf_seqno
, ARCH_CONVERT
) != i
) {
68 do_warn(_("bad sequence # %d for agf %d\n"),
69 INT_GET(agf
->agf_seqno
, ARCH_CONVERT
), i
);
72 INT_SET(agf
->agf_seqno
, ARCH_CONVERT
, i
);
75 if (INT_GET(agf
->agf_length
, ARCH_CONVERT
) != mp
->m_sb
.sb_agblocks
) {
76 if (i
!= mp
->m_sb
.sb_agcount
- 1) {
78 do_warn(_("bad length %d for agf %d, should be %d\n"),
79 INT_GET(agf
->agf_length
, ARCH_CONVERT
), i
,
80 mp
->m_sb
.sb_agblocks
);
82 INT_SET(agf
->agf_length
, ARCH_CONVERT
,
83 mp
->m_sb
.sb_agblocks
);
85 agblocks
= mp
->m_sb
.sb_dblocks
-
86 (xfs_drfsbno_t
) mp
->m_sb
.sb_agblocks
* i
;
88 if (INT_GET(agf
->agf_length
, ARCH_CONVERT
) != agblocks
) {
91 _("bad length %d for agf %d, should be %llu\n"),
92 INT_GET(agf
->agf_length
, ARCH_CONVERT
),
95 INT_SET(agf
->agf_length
, ARCH_CONVERT
,
96 (xfs_agblock_t
) agblocks
);
102 * check first/last AGF fields. if need be, lose the free
103 * space in the AGFL, we'll reclaim it later.
105 if (INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
) >= XFS_AGFL_SIZE(mp
)) {
106 do_warn(_("flfirst %d in agf %d too large (max = %d)\n"),
107 INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
),
108 i
, XFS_AGFL_SIZE(mp
));
110 INT_ZERO(agf
->agf_flfirst
, ARCH_CONVERT
);
113 if (INT_GET(agf
->agf_fllast
, ARCH_CONVERT
) >= XFS_AGFL_SIZE(mp
)) {
114 do_warn(_("fllast %d in agf %d too large (max = %d)\n"),
115 INT_GET(agf
->agf_fllast
, ARCH_CONVERT
),
116 i
, XFS_AGFL_SIZE(mp
));
118 INT_ZERO(agf
->agf_fllast
, ARCH_CONVERT
);
121 /* don't check freespace btrees -- will be checked by caller */
127 verify_set_agi(xfs_mount_t
*mp
, xfs_agi_t
*agi
, xfs_agnumber_t i
)
129 xfs_drfsbno_t agblocks
;
132 /* check common fields */
134 if (INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
) != XFS_AGI_MAGIC
) {
136 do_warn(_("bad magic # 0x%x for agi %d\n"),
137 INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
), i
);
140 INT_SET(agi
->agi_magicnum
, ARCH_CONVERT
, XFS_AGI_MAGIC
);
143 if (!XFS_AGI_GOOD_VERSION(INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
))) {
145 do_warn(_("bad version # %d for agi %d\n"),
146 INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
), i
);
149 INT_SET(agi
->agi_versionnum
, ARCH_CONVERT
,
153 if (INT_GET(agi
->agi_seqno
, ARCH_CONVERT
) != i
) {
155 do_warn(_("bad sequence # %d for agi %d\n"),
156 INT_GET(agi
->agi_seqno
, ARCH_CONVERT
), i
);
159 INT_SET(agi
->agi_seqno
, ARCH_CONVERT
, i
);
162 if (INT_GET(agi
->agi_length
, ARCH_CONVERT
) != mp
->m_sb
.sb_agblocks
) {
163 if (i
!= mp
->m_sb
.sb_agcount
- 1) {
165 do_warn(_("bad length # %d for agi %d, should be %d\n"),
166 INT_GET(agi
->agi_length
, ARCH_CONVERT
), i
,
167 mp
->m_sb
.sb_agblocks
);
169 INT_SET(agi
->agi_length
, ARCH_CONVERT
,
170 mp
->m_sb
.sb_agblocks
);
172 agblocks
= mp
->m_sb
.sb_dblocks
-
173 (xfs_drfsbno_t
) mp
->m_sb
.sb_agblocks
* i
;
175 if (INT_GET(agi
->agi_length
, ARCH_CONVERT
) != agblocks
) {
178 _("bad length # %d for agi %d, should be %llu\n"),
179 INT_GET(agi
->agi_length
, ARCH_CONVERT
),
182 INT_SET(agi
->agi_length
, ARCH_CONVERT
,
183 (xfs_agblock_t
) agblocks
);
188 /* don't check inode btree -- will be checked by caller */
194 * superblock comparison - compare arbitrary superblock with
195 * filesystem mount-point superblock
197 * the verified fields include id and geometry.
199 * the inprogress fields, version numbers, and counters
200 * are allowed to differ as well as all fields after the
201 * counters to cope with the pre-6.5 mkfs non-bzeroed
202 * secondary superblock sectors.
206 compare_sb(xfs_mount_t
*mp
, xfs_sb_t
*sb
)
208 fs_geometry_t fs_geo
, sb_geo
;
210 get_sb_geometry(&fs_geo
, &mp
->m_sb
);
211 get_sb_geometry(&sb_geo
, sb
);
213 if (memcmp(&fs_geo
, &sb_geo
,
214 (char *) &fs_geo
.sb_shared_vn
- (char *) &fs_geo
))
215 return(XR_SB_GEO_MISMATCH
);
221 * Possible fields that may have been set at mkfs time,
222 * sb_inoalignmt, sb_unit, sb_width and sb_dirblklog.
223 * The quota inode fields in the secondaries should be zero.
224 * Likewise, the sb_flags and sb_shared_vn should also be
225 * zero and the shared version bit should be cleared for
228 * And everything else in the buffer beyond either sb_width,
229 * sb_dirblklog (v2 dirs), or sb_logsectsize can be zeroed.
231 * Note: contrary to the name, this routine is called for all
232 * superblocks, not just the secondary superblocks.
235 secondary_sb_wack(xfs_mount_t
*mp
, xfs_buf_t
*sbuf
, xfs_sb_t
*sb
,
246 * mkfs's that stamped a feature bit besides the ones in the mask
247 * (e.g. were pre-6.5 beta) could leave garbage in the secondary
248 * superblock sectors. Anything stamping the shared fs bit or better
249 * into the secondaries is ok and should generate clean secondary
250 * superblock sectors. so only run the bzero check on the
251 * potentially garbaged secondaries.
254 (sb
->sb_versionnum
& XR_GOOD_SECSB_VNMASK
) == 0 ||
255 sb
->sb_versionnum
< XFS_SB_VERSION_4
) {
257 * Check for garbage beyond the last field.
258 * Use field addresses instead so this code will still
259 * work against older filesystems when the superblock
260 * gets rev'ed again with new fields appended.
262 if (XFS_SB_VERSION_HASLOGV2(sb
))
263 size
= (__psint_t
)&sb
->sb_logsunit
264 + sizeof(sb
->sb_logsunit
) - (__psint_t
)sb
;
265 else if (XFS_SB_VERSION_HASSECTOR(sb
))
266 size
= (__psint_t
)&sb
->sb_logsectsize
267 + sizeof(sb
->sb_logsectsize
) - (__psint_t
)sb
;
268 else if (XFS_SB_VERSION_HASDIRV2(sb
))
269 size
= (__psint_t
)&sb
->sb_dirblklog
270 + sizeof(sb
->sb_dirblklog
) - (__psint_t
)sb
;
272 size
= (__psint_t
)&sb
->sb_width
273 + sizeof(sb
->sb_width
) - (__psint_t
)sb
;
274 for (ip
= (char *)((__psint_t
)sb
+ size
);
275 ip
< (char *)((__psint_t
)sb
+ mp
->m_sb
.sb_sectsize
);
284 rval
|= XR_AG_SB_SEC
;
287 _("zeroing unused portion of %s superblock (AG #%u)\n"),
288 !i
? _("primary") : _("secondary"), i
);
289 bzero((void *)((__psint_t
)sb
+ size
),
290 mp
->m_sb
.sb_sectsize
- size
);
293 _("would zero unused portion of %s superblock (AG #%u)\n"),
294 !i
? _("primary") : _("secondary"), i
);
299 * now look for the fields we can manipulate directly.
300 * if we did a bzero and that bzero could have included
301 * the field in question, just silently reset it. otherwise,
304 * for now, just zero the flags field since only
305 * the readonly flag is used
310 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
312 do_warn(_("bad flags field in superblock %d\n"), i
);
314 rval
|= XR_AG_SB_SEC
;
318 * quota inodes and flags in secondary superblocks
319 * are never set by mkfs. However, they could be set
320 * in a secondary if a fs with quotas was growfs'ed since
321 * growfs copies the new primary into the secondaries.
323 if (sb
->sb_inprogress
== 1 && sb
->sb_uquotino
) {
326 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
329 _("non-null user quota inode field in superblock %d\n"),
333 rval
|= XR_AG_SB_SEC
;
336 if (sb
->sb_inprogress
== 1 && sb
->sb_gquotino
) {
339 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
342 _("non-null group quota inode field in superblock %d\n"),
346 rval
|= XR_AG_SB_SEC
;
349 if (sb
->sb_inprogress
== 1 && sb
->sb_qflags
) {
352 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
354 do_warn(_("non-null quota flags in superblock %d\n"),
357 rval
|= XR_AG_SB_SEC
;
361 * if the secondaries agree on a stripe unit/width or inode
362 * alignment, those fields ought to be valid since they are
363 * written at mkfs time (and the corresponding sb version bits
366 if (!XFS_SB_VERSION_HASSHARED(sb
) && sb
->sb_shared_vn
!= 0) {
368 sb
->sb_shared_vn
= 0;
369 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
372 _("bad shared version number in superblock %d\n"),
375 rval
|= XR_AG_SB_SEC
;
378 if (!XFS_SB_VERSION_HASALIGN(sb
) && sb
->sb_inoalignmt
!= 0) {
380 sb
->sb_inoalignmt
= 0;
381 if (sb
->sb_versionnum
& XR_PART_SECSB_VNMASK
|| !do_bzero
) {
384 _("bad inode alignment field in superblock %d\n"),
387 rval
|= XR_AG_SB_SEC
;
390 if (!XFS_SB_VERSION_HASDALIGN(sb
) &&
391 (sb
->sb_unit
!= 0 || sb
->sb_width
!= 0)) {
393 sb
->sb_unit
= sb
->sb_width
= 0;
394 if (sb
->sb_versionnum
& XR_GOOD_SECSB_VNMASK
|| !do_bzero
) {
397 _("bad stripe unit/width fields in superblock %d\n"),
400 rval
|= XR_AG_SB_SEC
;
403 if (!XFS_SB_VERSION_HASSECTOR(sb
) &&
404 (sb
->sb_sectsize
!= BBSIZE
|| sb
->sb_sectlog
!= BBSHIFT
||
405 sb
->sb_logsectsize
!= 0 || sb
->sb_logsectlog
!= 0)) {
407 sb
->sb_sectsize
= BBSIZE
;
408 sb
->sb_sectlog
= BBSHIFT
;
409 sb
->sb_logsectsize
= 0;
410 sb
->sb_logsectlog
= 0;
412 if (sb
->sb_versionnum
& XR_GOOD_SECSB_VNMASK
|| !do_bzero
) {
415 _("bad log/data device sector size fields in superblock %d\n"),
418 rval
|= XR_AG_SB_SEC
;
425 * verify and reset the ag header if required.
427 * lower 4 bits of rval are set depending on what got modified.
428 * (see agheader.h for more details)
430 * NOTE -- this routine does not tell the user that it has
431 * altered things. Rather, it is up to the caller to do so
432 * using the bits encoded into the return value.
436 verify_set_agheader(xfs_mount_t
*mp
, xfs_buf_t
*sbuf
, xfs_sb_t
*sb
,
437 xfs_agf_t
*agf
, xfs_agi_t
*agi
, xfs_agnumber_t i
)
441 int status_sb
= XR_OK
;
443 status
= verify_sb(sb
, (i
== 0));
445 if (status
!= XR_OK
) {
446 do_warn(_("bad on-disk superblock %d - %s\n"),
447 i
, err_string(status
));
450 status_sb
= compare_sb(mp
, sb
);
452 if (status_sb
!= XR_OK
) {
453 do_warn(_("primary/secondary superblock %d conflict - %s\n"),
454 i
, err_string(status_sb
));
457 if (status
!= XR_OK
|| status_sb
!= XR_OK
) {
462 * clear the more transient fields
464 sb
->sb_inprogress
= 1;
469 sb
->sb_frextents
= 0;
477 rval
|= secondary_sb_wack(mp
, sbuf
, sb
, i
);
479 rval
|= verify_set_agf(mp
, agf
, i
);
480 rval
|= verify_set_agi(mp
, agi
, i
);