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