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