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