1 | // SPDX-License-Identifier: GPL-2.0 |
---|---|
2 | /* |
3 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. |
4 | * All Rights Reserved. |
5 | */ |
6 | #include "xfs.h" |
7 | #include "xfs_fs.h" |
8 | #include "xfs_shared.h" |
9 | #include "xfs_format.h" |
10 | #include "xfs_log_format.h" |
11 | #include "xfs_trans_resv.h" |
12 | #include "xfs_bit.h" |
13 | #include "xfs_sb.h" |
14 | #include "xfs_mount.h" |
15 | #include "xfs_ialloc.h" |
16 | #include "xfs_alloc.h" |
17 | #include "xfs_error.h" |
18 | #include "xfs_trans.h" |
19 | #include "xfs_buf_item.h" |
20 | #include "xfs_bmap_btree.h" |
21 | #include "xfs_alloc_btree.h" |
22 | #include "xfs_log.h" |
23 | #include "xfs_rmap_btree.h" |
24 | #include "xfs_refcount_btree.h" |
25 | #include "xfs_da_format.h" |
26 | #include "xfs_health.h" |
27 | #include "xfs_ag.h" |
28 | #include "xfs_rtbitmap.h" |
29 | #include "xfs_exchrange.h" |
30 | #include "xfs_rtgroup.h" |
31 | #include "xfs_rtrmap_btree.h" |
32 | #include "xfs_rtrefcount_btree.h" |
33 | |
34 | /* |
35 | * Physical superblock buffer manipulations. Shared with libxfs in userspace. |
36 | */ |
37 | |
38 | /* |
39 | * Check that all the V4 feature bits that the V5 filesystem format requires are |
40 | * correctly set. |
41 | */ |
42 | static bool |
43 | xfs_sb_validate_v5_features( |
44 | struct xfs_sb *sbp) |
45 | { |
46 | /* We must not have any unknown V4 feature bits set */ |
47 | if (sbp->sb_versionnum & ~XFS_SB_VERSION_OKBITS) |
48 | return false; |
49 | |
50 | /* |
51 | * The CRC bit is considered an invalid V4 flag, so we have to add it |
52 | * manually to the OKBITS mask. |
53 | */ |
54 | if (sbp->sb_features2 & ~(XFS_SB_VERSION2_OKBITS | |
55 | XFS_SB_VERSION2_CRCBIT)) |
56 | return false; |
57 | |
58 | /* Now check all the required V4 feature flags are set. */ |
59 | |
60 | #define V5_VERS_FLAGS (XFS_SB_VERSION_NLINKBIT | \ |
61 | XFS_SB_VERSION_ALIGNBIT | \ |
62 | XFS_SB_VERSION_LOGV2BIT | \ |
63 | XFS_SB_VERSION_EXTFLGBIT | \ |
64 | XFS_SB_VERSION_DIRV2BIT | \ |
65 | XFS_SB_VERSION_MOREBITSBIT) |
66 | |
67 | #define V5_FEAT_FLAGS (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \ |
68 | XFS_SB_VERSION2_ATTR2BIT | \ |
69 | XFS_SB_VERSION2_PROJID32BIT | \ |
70 | XFS_SB_VERSION2_CRCBIT) |
71 | |
72 | if ((sbp->sb_versionnum & V5_VERS_FLAGS) != V5_VERS_FLAGS) |
73 | return false; |
74 | if ((sbp->sb_features2 & V5_FEAT_FLAGS) != V5_FEAT_FLAGS) |
75 | return false; |
76 | return true; |
77 | } |
78 | |
79 | /* |
80 | * We current support XFS v5 formats with known features and v4 superblocks with |
81 | * at least V2 directories. |
82 | */ |
83 | bool |
84 | xfs_sb_good_version( |
85 | struct xfs_sb *sbp) |
86 | { |
87 | /* |
88 | * All v5 filesystems are supported, but we must check that all the |
89 | * required v4 feature flags are enabled correctly as the code checks |
90 | * those flags and not for v5 support. |
91 | */ |
92 | if (xfs_sb_is_v5(sbp)) |
93 | return xfs_sb_validate_v5_features(sbp); |
94 | |
95 | /* versions prior to v4 are not supported */ |
96 | if (XFS_SB_VERSION_NUM(sbp) != XFS_SB_VERSION_4) |
97 | return false; |
98 | |
99 | /* We must not have any unknown v4 feature bits set */ |
100 | if ((sbp->sb_versionnum & ~XFS_SB_VERSION_OKBITS) || |
101 | ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && |
102 | (sbp->sb_features2 & ~XFS_SB_VERSION2_OKBITS))) |
103 | return false; |
104 | |
105 | /* V4 filesystems need v2 directories and unwritten extents */ |
106 | if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)) |
107 | return false; |
108 | if (!(sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT)) |
109 | return false; |
110 | |
111 | /* It's a supported v4 filesystem */ |
112 | return true; |
113 | } |
114 | |
115 | uint64_t |
116 | xfs_sb_version_to_features( |
117 | struct xfs_sb *sbp) |
118 | { |
119 | uint64_t features = 0; |
120 | |
121 | /* optional V4 features */ |
122 | if (sbp->sb_rblocks > 0) |
123 | features |= XFS_FEAT_REALTIME; |
124 | if (sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT) |
125 | features |= XFS_FEAT_NLINK; |
126 | if (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT) |
127 | features |= XFS_FEAT_ATTR; |
128 | if (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT) |
129 | features |= XFS_FEAT_QUOTA; |
130 | if (sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT) |
131 | features |= XFS_FEAT_ALIGN; |
132 | if (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT) |
133 | features |= XFS_FEAT_LOGV2; |
134 | if (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT) |
135 | features |= XFS_FEAT_DALIGN; |
136 | if (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT) |
137 | features |= XFS_FEAT_EXTFLG; |
138 | if (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT) |
139 | features |= XFS_FEAT_SECTOR; |
140 | if (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT) |
141 | features |= XFS_FEAT_ASCIICI; |
142 | if (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) { |
143 | if (sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT) |
144 | features |= XFS_FEAT_LAZYSBCOUNT; |
145 | if (sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT) |
146 | features |= XFS_FEAT_ATTR2; |
147 | if (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT) |
148 | features |= XFS_FEAT_PROJID32; |
149 | if (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE) |
150 | features |= XFS_FEAT_FTYPE; |
151 | } |
152 | |
153 | if (!xfs_sb_is_v5(sbp)) |
154 | return features; |
155 | |
156 | /* Always on V5 features */ |
157 | features |= XFS_FEAT_ALIGN | XFS_FEAT_LOGV2 | XFS_FEAT_EXTFLG | |
158 | XFS_FEAT_LAZYSBCOUNT | XFS_FEAT_ATTR2 | XFS_FEAT_PROJID32 | |
159 | XFS_FEAT_V3INODES | XFS_FEAT_CRC | XFS_FEAT_PQUOTINO; |
160 | |
161 | /* Optional V5 features */ |
162 | if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT) |
163 | features |= XFS_FEAT_FINOBT; |
164 | if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT) |
165 | features |= XFS_FEAT_RMAPBT; |
166 | if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK) |
167 | features |= XFS_FEAT_REFLINK; |
168 | if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT) |
169 | features |= XFS_FEAT_INOBTCNT; |
170 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_FTYPE) |
171 | features |= XFS_FEAT_FTYPE; |
172 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_SPINODES) |
173 | features |= XFS_FEAT_SPINODES; |
174 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID) |
175 | features |= XFS_FEAT_META_UUID; |
176 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_BIGTIME) |
177 | features |= XFS_FEAT_BIGTIME; |
178 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR) |
179 | features |= XFS_FEAT_NEEDSREPAIR; |
180 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_NREXT64) |
181 | features |= XFS_FEAT_NREXT64; |
182 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_EXCHRANGE) |
183 | features |= XFS_FEAT_EXCHANGE_RANGE; |
184 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_PARENT) |
185 | features |= XFS_FEAT_PARENT; |
186 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) |
187 | features |= XFS_FEAT_METADIR; |
188 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_ZONED) |
189 | features |= XFS_FEAT_ZONED; |
190 | |
191 | return features; |
192 | } |
193 | |
194 | /* Check all the superblock fields we care about when reading one in. */ |
195 | STATIC int |
196 | xfs_validate_sb_read( |
197 | struct xfs_mount *mp, |
198 | struct xfs_sb *sbp) |
199 | { |
200 | if (!xfs_sb_is_v5(sbp)) |
201 | return 0; |
202 | |
203 | /* |
204 | * Version 5 superblock feature mask validation. Reject combinations |
205 | * the kernel cannot support up front before checking anything else. |
206 | */ |
207 | if (xfs_sb_has_compat_feature(sbp, XFS_SB_FEAT_COMPAT_UNKNOWN)) { |
208 | xfs_warn(mp, |
209 | "Superblock has unknown compatible features (0x%x) enabled.", |
210 | (sbp->sb_features_compat & XFS_SB_FEAT_COMPAT_UNKNOWN)); |
211 | xfs_warn(mp, |
212 | "Using a more recent kernel is recommended."); |
213 | } |
214 | |
215 | if (xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) { |
216 | xfs_alert(mp, |
217 | "Superblock has unknown read-only compatible features (0x%x) enabled.", |
218 | (sbp->sb_features_ro_compat & |
219 | XFS_SB_FEAT_RO_COMPAT_UNKNOWN)); |
220 | if (!xfs_is_readonly(mp)) { |
221 | xfs_warn(mp, |
222 | "Attempted to mount read-only compatible filesystem read-write."); |
223 | xfs_warn(mp, |
224 | "Filesystem can only be safely mounted read only."); |
225 | |
226 | return -EINVAL; |
227 | } |
228 | } |
229 | if (xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_UNKNOWN)) { |
230 | xfs_warn(mp, |
231 | "Superblock has unknown incompatible features (0x%x) enabled.", |
232 | (sbp->sb_features_incompat & |
233 | XFS_SB_FEAT_INCOMPAT_UNKNOWN)); |
234 | xfs_warn(mp, |
235 | "Filesystem cannot be safely mounted by this kernel."); |
236 | return -EINVAL; |
237 | } |
238 | |
239 | return 0; |
240 | } |
241 | |
242 | /* Return the number of extents covered by a single rt bitmap file */ |
243 | static xfs_rtbxlen_t |
244 | xfs_extents_per_rbm( |
245 | struct xfs_sb *sbp) |
246 | { |
247 | if (xfs_sb_is_v5(sbp) && |
248 | (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) |
249 | return sbp->sb_rgextents; |
250 | return sbp->sb_rextents; |
251 | } |
252 | |
253 | /* |
254 | * Return the payload size of a single rt bitmap block (without the metadata |
255 | * header if any). |
256 | */ |
257 | static inline unsigned int |
258 | xfs_rtbmblock_size( |
259 | struct xfs_sb *sbp) |
260 | { |
261 | if (xfs_sb_is_v5(sbp) && |
262 | (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) |
263 | return sbp->sb_blocksize - sizeof(struct xfs_rtbuf_blkinfo); |
264 | return sbp->sb_blocksize; |
265 | } |
266 | |
267 | static uint64_t |
268 | xfs_expected_rbmblocks( |
269 | struct xfs_sb *sbp) |
270 | { |
271 | if (xfs_sb_is_v5(sbp) && |
272 | (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_ZONED)) |
273 | return 0; |
274 | return howmany_64(xfs_extents_per_rbm(sbp), |
275 | NBBY * xfs_rtbmblock_size(sbp)); |
276 | } |
277 | |
278 | /* Validate the realtime geometry */ |
279 | bool |
280 | xfs_validate_rt_geometry( |
281 | struct xfs_sb *sbp) |
282 | { |
283 | if (xfs_sb_is_v5(sbp) && |
284 | (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_ZONED)) { |
285 | if (sbp->sb_rextsize != 1) |
286 | return false; |
287 | } else { |
288 | if (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE || |
289 | sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) |
290 | return false; |
291 | } |
292 | |
293 | if (sbp->sb_rblocks == 0) { |
294 | if (sbp->sb_rextents != 0 || sbp->sb_rbmblocks != 0 || |
295 | sbp->sb_rextslog != 0 || sbp->sb_frextents != 0) |
296 | return false; |
297 | return true; |
298 | } |
299 | |
300 | if (sbp->sb_rextents == 0 || |
301 | sbp->sb_rextents != div_u64(sbp->sb_rblocks, sbp->sb_rextsize) || |
302 | sbp->sb_rextslog != xfs_compute_rextslog(sbp->sb_rextents) || |
303 | sbp->sb_rbmblocks != xfs_expected_rbmblocks(sbp)) |
304 | return false; |
305 | |
306 | return true; |
307 | } |
308 | |
309 | /* Check all the superblock fields we care about when writing one out. */ |
310 | STATIC int |
311 | xfs_validate_sb_write( |
312 | struct xfs_mount *mp, |
313 | struct xfs_buf *bp, |
314 | struct xfs_sb *sbp) |
315 | { |
316 | /* |
317 | * Carry out additional sb summary counter sanity checks when we write |
318 | * the superblock. We skip this in the read validator because there |
319 | * could be newer superblocks in the log and if the values are garbage |
320 | * even after replay we'll recalculate them at the end of log mount. |
321 | * |
322 | * mkfs has traditionally written zeroed counters to inprogress and |
323 | * secondary superblocks, so allow this usage to continue because |
324 | * we never read counters from such superblocks. |
325 | */ |
326 | if (xfs_buf_daddr(bp) == XFS_SB_DADDR && !sbp->sb_inprogress && |
327 | (sbp->sb_fdblocks > sbp->sb_dblocks || |
328 | !xfs_verify_icount(mp, sbp->sb_icount) || |
329 | sbp->sb_ifree > sbp->sb_icount)) { |
330 | xfs_warn(mp, "SB summary counter sanity check failed"); |
331 | return -EFSCORRUPTED; |
332 | } |
333 | |
334 | if (!xfs_sb_is_v5(sbp)) |
335 | return 0; |
336 | |
337 | /* |
338 | * Version 5 superblock feature mask validation. Reject combinations |
339 | * the kernel cannot support since we checked for unsupported bits in |
340 | * the read verifier, which means that memory is corrupt. |
341 | */ |
342 | if (!xfs_is_readonly(mp) && |
343 | xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) { |
344 | xfs_alert(mp, |
345 | "Corruption detected in superblock read-only compatible features (0x%x)!", |
346 | (sbp->sb_features_ro_compat & |
347 | XFS_SB_FEAT_RO_COMPAT_UNKNOWN)); |
348 | return -EFSCORRUPTED; |
349 | } |
350 | if (xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_UNKNOWN)) { |
351 | xfs_warn(mp, |
352 | "Corruption detected in superblock incompatible features (0x%x)!", |
353 | (sbp->sb_features_incompat & |
354 | XFS_SB_FEAT_INCOMPAT_UNKNOWN)); |
355 | return -EFSCORRUPTED; |
356 | } |
357 | if (xfs_sb_has_incompat_log_feature(sbp, |
358 | XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)) { |
359 | xfs_warn(mp, |
360 | "Corruption detected in superblock incompatible log features (0x%x)!", |
361 | (sbp->sb_features_log_incompat & |
362 | XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)); |
363 | return -EFSCORRUPTED; |
364 | } |
365 | |
366 | /* |
367 | * We can't read verify the sb LSN because the read verifier is called |
368 | * before the log is allocated and processed. We know the log is set up |
369 | * before write verifier calls, so check it here. |
370 | */ |
371 | if (!xfs_log_check_lsn(mp, sbp->sb_lsn)) |
372 | return -EFSCORRUPTED; |
373 | |
374 | return 0; |
375 | } |
376 | |
377 | int |
378 | xfs_compute_rgblklog( |
379 | xfs_rtxlen_t rgextents, |
380 | xfs_rgblock_t rextsize) |
381 | { |
382 | uint64_t rgblocks = (uint64_t)rgextents * rextsize; |
383 | |
384 | return xfs_highbit64(rgblocks - 1) + 1; |
385 | } |
386 | |
387 | static int |
388 | xfs_validate_sb_rtgroups( |
389 | struct xfs_mount *mp, |
390 | struct xfs_sb *sbp) |
391 | { |
392 | uint64_t groups; |
393 | int rgblklog; |
394 | |
395 | if (sbp->sb_rextsize == 0) { |
396 | xfs_warn(mp, |
397 | "Realtime extent size must not be zero."); |
398 | return -EINVAL; |
399 | } |
400 | |
401 | if (sbp->sb_rgextents > XFS_MAX_RGBLOCKS / sbp->sb_rextsize) { |
402 | xfs_warn(mp, |
403 | "Realtime group size (%u) must be less than %u rt extents.", |
404 | sbp->sb_rgextents, |
405 | XFS_MAX_RGBLOCKS / sbp->sb_rextsize); |
406 | return -EINVAL; |
407 | } |
408 | |
409 | if (sbp->sb_rgextents < XFS_MIN_RGEXTENTS) { |
410 | xfs_warn(mp, |
411 | "Realtime group size (%u) must be at least %u rt extents.", |
412 | sbp->sb_rgextents, XFS_MIN_RGEXTENTS); |
413 | return -EINVAL; |
414 | } |
415 | |
416 | if (sbp->sb_rgcount > XFS_MAX_RGNUMBER) { |
417 | xfs_warn(mp, |
418 | "Realtime groups (%u) must be less than %u.", |
419 | sbp->sb_rgcount, XFS_MAX_RGNUMBER); |
420 | return -EINVAL; |
421 | } |
422 | |
423 | groups = howmany_64(sbp->sb_rextents, sbp->sb_rgextents); |
424 | if (groups != sbp->sb_rgcount) { |
425 | xfs_warn(mp, |
426 | "Realtime groups (%u) do not cover the entire rt section; need (%llu) groups.", |
427 | sbp->sb_rgcount, groups); |
428 | return -EINVAL; |
429 | } |
430 | |
431 | /* Exchange-range is required for fsr to work on realtime files */ |
432 | if (!(sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_EXCHRANGE)) { |
433 | xfs_warn(mp, |
434 | "Realtime groups feature requires exchange-range support."); |
435 | return -EINVAL; |
436 | } |
437 | |
438 | rgblklog = xfs_compute_rgblklog(sbp->sb_rgextents, sbp->sb_rextsize); |
439 | if (sbp->sb_rgblklog != rgblklog) { |
440 | xfs_warn(mp, |
441 | "Realtime group log (%d) does not match expected value (%d).", |
442 | sbp->sb_rgblklog, rgblklog); |
443 | return -EINVAL; |
444 | } |
445 | |
446 | return 0; |
447 | } |
448 | |
449 | static int |
450 | xfs_validate_sb_zoned( |
451 | struct xfs_mount *mp, |
452 | struct xfs_sb *sbp) |
453 | { |
454 | if (sbp->sb_frextents != 0) { |
455 | xfs_warn(mp, |
456 | "sb_frextents must be zero for zoned file systems."); |
457 | return -EINVAL; |
458 | } |
459 | |
460 | if (sbp->sb_rtstart && sbp->sb_rtstart < sbp->sb_dblocks) { |
461 | xfs_warn(mp, |
462 | "sb_rtstart (%lld) overlaps sb_dblocks (%lld).", |
463 | sbp->sb_rtstart, sbp->sb_dblocks); |
464 | return -EINVAL; |
465 | } |
466 | |
467 | if (sbp->sb_rtreserved && sbp->sb_rtreserved >= sbp->sb_rblocks) { |
468 | xfs_warn(mp, |
469 | "sb_rtreserved (%lld) larger than sb_rblocks (%lld).", |
470 | sbp->sb_rtreserved, sbp->sb_rblocks); |
471 | return -EINVAL; |
472 | } |
473 | |
474 | return 0; |
475 | } |
476 | |
477 | /* Check the validity of the SB. */ |
478 | STATIC int |
479 | xfs_validate_sb_common( |
480 | struct xfs_mount *mp, |
481 | struct xfs_buf *bp, |
482 | struct xfs_sb *sbp) |
483 | { |
484 | struct xfs_dsb *dsb = bp->b_addr; |
485 | uint32_t agcount = 0; |
486 | uint32_t rem; |
487 | bool has_dalign; |
488 | int error; |
489 | |
490 | if (!xfs_verify_magic(bp, dsb->sb_magicnum)) { |
491 | xfs_warn(mp, |
492 | "Superblock has bad magic number 0x%x. Not an XFS filesystem?", |
493 | be32_to_cpu(dsb->sb_magicnum)); |
494 | return -EWRONGFS; |
495 | } |
496 | |
497 | if (!xfs_sb_good_version(sbp)) { |
498 | xfs_warn(mp, |
499 | "Superblock has unknown features enabled or corrupted feature masks."); |
500 | return -EWRONGFS; |
501 | } |
502 | |
503 | /* |
504 | * Validate feature flags and state |
505 | */ |
506 | if (xfs_sb_is_v5(sbp)) { |
507 | if (sbp->sb_blocksize < XFS_MIN_CRC_BLOCKSIZE) { |
508 | xfs_notice(mp, |
509 | "Block size (%u bytes) too small for Version 5 superblock (minimum %d bytes)", |
510 | sbp->sb_blocksize, XFS_MIN_CRC_BLOCKSIZE); |
511 | return -EFSCORRUPTED; |
512 | } |
513 | |
514 | /* V5 has a separate project quota inode */ |
515 | if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) { |
516 | xfs_notice(mp, |
517 | "Version 5 of Super block has XFS_OQUOTA bits."); |
518 | return -EFSCORRUPTED; |
519 | } |
520 | |
521 | /* |
522 | * Full inode chunks must be aligned to inode chunk size when |
523 | * sparse inodes are enabled to support the sparse chunk |
524 | * allocation algorithm and prevent overlapping inode records. |
525 | */ |
526 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_SPINODES) { |
527 | uint32_t align; |
528 | |
529 | align = XFS_INODES_PER_CHUNK * sbp->sb_inodesize |
530 | >> sbp->sb_blocklog; |
531 | if (sbp->sb_inoalignmt != align) { |
532 | xfs_warn(mp, |
533 | "Inode block alignment (%u) must match chunk size (%u) for sparse inodes.", |
534 | sbp->sb_inoalignmt, align); |
535 | return -EINVAL; |
536 | } |
537 | |
538 | if (sbp->sb_spino_align && |
539 | (sbp->sb_spino_align > sbp->sb_inoalignmt || |
540 | (sbp->sb_inoalignmt % sbp->sb_spino_align) != 0)) { |
541 | xfs_warn(mp, |
542 | "Sparse inode alignment (%u) is invalid, must be integer factor of (%u).", |
543 | sbp->sb_spino_align, |
544 | sbp->sb_inoalignmt); |
545 | return -EINVAL; |
546 | } |
547 | } else if (sbp->sb_spino_align) { |
548 | xfs_warn(mp, |
549 | "Sparse inode alignment (%u) should be zero.", |
550 | sbp->sb_spino_align); |
551 | return -EINVAL; |
552 | } |
553 | |
554 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) { |
555 | if (memchr_inv(sbp->sb_pad, 0, sizeof(sbp->sb_pad))) { |
556 | xfs_warn(mp, |
557 | "Metadir superblock padding fields must be zero."); |
558 | return -EINVAL; |
559 | } |
560 | |
561 | error = xfs_validate_sb_rtgroups(mp, sbp); |
562 | if (error) |
563 | return error; |
564 | } |
565 | if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_ZONED) { |
566 | error = xfs_validate_sb_zoned(mp, sbp); |
567 | if (error) |
568 | return error; |
569 | } |
570 | } else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD | |
571 | XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) { |
572 | xfs_notice(mp, |
573 | "Superblock earlier than Version 5 has XFS_{P|G}QUOTA_{ENFD|CHKD} bits."); |
574 | return -EFSCORRUPTED; |
575 | } |
576 | |
577 | if (unlikely( |
578 | sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { |
579 | xfs_warn(mp, |
580 | "filesystem is marked as having an external log; " |
581 | "specify logdev on the mount command line."); |
582 | return -EINVAL; |
583 | } |
584 | |
585 | if (unlikely( |
586 | sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { |
587 | xfs_warn(mp, |
588 | "filesystem is marked as having an internal log; " |
589 | "do not specify logdev on the mount command line."); |
590 | return -EINVAL; |
591 | } |
592 | |
593 | /* Compute agcount for this number of dblocks and agblocks */ |
594 | if (sbp->sb_agblocks) { |
595 | agcount = div_u64_rem(sbp->sb_dblocks, sbp->sb_agblocks, &rem); |
596 | if (rem) |
597 | agcount++; |
598 | } |
599 | |
600 | /* |
601 | * More sanity checking. Most of these were stolen directly from |
602 | * xfs_repair. |
603 | */ |
604 | if (unlikely( |
605 | sbp->sb_agcount <= 0 || |
606 | sbp->sb_sectsize < XFS_MIN_SECTORSIZE || |
607 | sbp->sb_sectsize > XFS_MAX_SECTORSIZE || |
608 | sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG || |
609 | sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG || |
610 | sbp->sb_sectsize != (1 << sbp->sb_sectlog) || |
611 | sbp->sb_blocksize < XFS_MIN_BLOCKSIZE || |
612 | sbp->sb_blocksize > XFS_MAX_BLOCKSIZE || |
613 | sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG || |
614 | sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || |
615 | sbp->sb_blocksize != (1 << sbp->sb_blocklog) || |
616 | sbp->sb_dirblklog + sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || |
617 | sbp->sb_inodesize < XFS_DINODE_MIN_SIZE || |
618 | sbp->sb_inodesize > XFS_DINODE_MAX_SIZE || |
619 | sbp->sb_inodelog < XFS_DINODE_MIN_LOG || |
620 | sbp->sb_inodelog > XFS_DINODE_MAX_LOG || |
621 | sbp->sb_inodesize != (1 << sbp->sb_inodelog) || |
622 | sbp->sb_inopblock != howmany(sbp->sb_blocksize,sbp->sb_inodesize) || |
623 | XFS_FSB_TO_B(mp, sbp->sb_agblocks) < XFS_MIN_AG_BYTES || |
624 | XFS_FSB_TO_B(mp, sbp->sb_agblocks) > XFS_MAX_AG_BYTES || |
625 | sbp->sb_agblklog != xfs_highbit32(sbp->sb_agblocks - 1) + 1 || |
626 | agcount == 0 || agcount != sbp->sb_agcount || |
627 | (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) || |
628 | (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || |
629 | (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || |
630 | (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */) || |
631 | sbp->sb_dblocks == 0 || |
632 | sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) || |
633 | sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp) || |
634 | sbp->sb_shared_vn != 0)) { |
635 | xfs_notice(mp, "SB sanity check failed"); |
636 | return -EFSCORRUPTED; |
637 | } |
638 | |
639 | /* |
640 | * Logs that are too large are not supported at all. Reject them |
641 | * outright. Logs that are too small are tolerated on v4 filesystems, |
642 | * but we can only check that when mounting the log. Hence we skip |
643 | * those checks here. |
644 | */ |
645 | if (sbp->sb_logblocks > XFS_MAX_LOG_BLOCKS) { |
646 | xfs_notice(mp, |
647 | "Log size 0x%x blocks too large, maximum size is 0x%llx blocks", |
648 | sbp->sb_logblocks, XFS_MAX_LOG_BLOCKS); |
649 | return -EFSCORRUPTED; |
650 | } |
651 | |
652 | if (XFS_FSB_TO_B(mp, sbp->sb_logblocks) > XFS_MAX_LOG_BYTES) { |
653 | xfs_warn(mp, |
654 | "log size 0x%llx bytes too large, maximum size is 0x%llx bytes", |
655 | XFS_FSB_TO_B(mp, sbp->sb_logblocks), |
656 | XFS_MAX_LOG_BYTES); |
657 | return -EFSCORRUPTED; |
658 | } |
659 | |
660 | /* |
661 | * Do not allow filesystems with corrupted log sector or stripe units to |
662 | * be mounted. We cannot safely size the iclogs or write to the log if |
663 | * the log stripe unit is not valid. |
664 | */ |
665 | if (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT) { |
666 | if (sbp->sb_logsectsize != (1U << sbp->sb_logsectlog)) { |
667 | xfs_notice(mp, |
668 | "log sector size in bytes/log2 (0x%x/0x%x) must match", |
669 | sbp->sb_logsectsize, 1U << sbp->sb_logsectlog); |
670 | return -EFSCORRUPTED; |
671 | } |
672 | } else if (sbp->sb_logsectsize || sbp->sb_logsectlog) { |
673 | xfs_notice(mp, |
674 | "log sector size in bytes/log2 (0x%x/0x%x) are not zero", |
675 | sbp->sb_logsectsize, sbp->sb_logsectlog); |
676 | return -EFSCORRUPTED; |
677 | } |
678 | |
679 | if (sbp->sb_logsunit > 1) { |
680 | if (sbp->sb_logsunit % sbp->sb_blocksize) { |
681 | xfs_notice(mp, |
682 | "log stripe unit 0x%x bytes must be a multiple of block size", |
683 | sbp->sb_logsunit); |
684 | return -EFSCORRUPTED; |
685 | } |
686 | if (sbp->sb_logsunit > XLOG_MAX_RECORD_BSIZE) { |
687 | xfs_notice(mp, |
688 | "log stripe unit 0x%x bytes over maximum size (0x%x bytes)", |
689 | sbp->sb_logsunit, XLOG_MAX_RECORD_BSIZE); |
690 | return -EFSCORRUPTED; |
691 | } |
692 | } |
693 | |
694 | if (!xfs_validate_rt_geometry(sbp)) { |
695 | xfs_notice(mp, |
696 | "realtime %sgeometry check failed", |
697 | sbp->sb_rblocks ? "": "zeroed "); |
698 | return -EFSCORRUPTED; |
699 | } |
700 | |
701 | /* |
702 | * Either (sb_unit and !hasdalign) or (!sb_unit and hasdalign) |
703 | * would imply the image is corrupted. |
704 | */ |
705 | has_dalign = sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT; |
706 | if (!!sbp->sb_unit ^ has_dalign) { |
707 | xfs_notice(mp, "SB stripe alignment sanity check failed"); |
708 | return -EFSCORRUPTED; |
709 | } |
710 | |
711 | if (!xfs_validate_stripe_geometry(mp, XFS_FSB_TO_B(mp, sbp->sb_unit), |
712 | XFS_FSB_TO_B(mp, sbp->sb_width), 0, |
713 | xfs_buf_daddr(bp) == XFS_SB_DADDR, false)) |
714 | return -EFSCORRUPTED; |
715 | |
716 | /* |
717 | * Currently only very few inode sizes are supported. |
718 | */ |
719 | switch (sbp->sb_inodesize) { |
720 | case 256: |
721 | case 512: |
722 | case 1024: |
723 | case 2048: |
724 | break; |
725 | default: |
726 | xfs_warn(mp, "inode size of %d bytes not supported", |
727 | sbp->sb_inodesize); |
728 | return -ENOSYS; |
729 | } |
730 | |
731 | return 0; |
732 | } |
733 | |
734 | void |
735 | xfs_sb_quota_from_disk(struct xfs_sb *sbp) |
736 | { |
737 | if (xfs_sb_is_v5(sbp) && |
738 | (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) { |
739 | sbp->sb_uquotino = NULLFSINO; |
740 | sbp->sb_gquotino = NULLFSINO; |
741 | sbp->sb_pquotino = NULLFSINO; |
742 | return; |
743 | } |
744 | |
745 | /* |
746 | * older mkfs doesn't initialize quota inodes to NULLFSINO. This |
747 | * leads to in-core values having two different values for a quota |
748 | * inode to be invalid: 0 and NULLFSINO. Change it to a single value |
749 | * NULLFSINO. |
750 | * |
751 | * Note that this change affect only the in-core values. These |
752 | * values are not written back to disk unless any quota information |
753 | * is written to the disk. Even in that case, sb_pquotino field is |
754 | * not written to disk unless the superblock supports pquotino. |
755 | */ |
756 | if (sbp->sb_uquotino == 0) |
757 | sbp->sb_uquotino = NULLFSINO; |
758 | if (sbp->sb_gquotino == 0) |
759 | sbp->sb_gquotino = NULLFSINO; |
760 | if (sbp->sb_pquotino == 0) |
761 | sbp->sb_pquotino = NULLFSINO; |
762 | |
763 | /* |
764 | * We need to do these manipilations only if we are working |
765 | * with an older version of on-disk superblock. |
766 | */ |
767 | if (xfs_sb_is_v5(sbp)) |
768 | return; |
769 | |
770 | if (sbp->sb_qflags & XFS_OQUOTA_ENFD) |
771 | sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ? |
772 | XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD; |
773 | if (sbp->sb_qflags & XFS_OQUOTA_CHKD) |
774 | sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ? |
775 | XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD; |
776 | sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD); |
777 | |
778 | if (sbp->sb_qflags & XFS_PQUOTA_ACCT && |
779 | sbp->sb_gquotino != NULLFSINO) { |
780 | /* |
781 | * In older version of superblock, on-disk superblock only |
782 | * has sb_gquotino, and in-core superblock has both sb_gquotino |
783 | * and sb_pquotino. But, only one of them is supported at any |
784 | * point of time. So, if PQUOTA is set in disk superblock, |
785 | * copy over sb_gquotino to sb_pquotino. The NULLFSINO test |
786 | * above is to make sure we don't do this twice and wipe them |
787 | * both out! |
788 | */ |
789 | sbp->sb_pquotino = sbp->sb_gquotino; |
790 | sbp->sb_gquotino = NULLFSINO; |
791 | } |
792 | } |
793 | |
794 | static void |
795 | __xfs_sb_from_disk( |
796 | struct xfs_sb *to, |
797 | struct xfs_dsb *from, |
798 | bool convert_xquota) |
799 | { |
800 | to->sb_magicnum = be32_to_cpu(from->sb_magicnum); |
801 | to->sb_blocksize = be32_to_cpu(from->sb_blocksize); |
802 | to->sb_dblocks = be64_to_cpu(from->sb_dblocks); |
803 | to->sb_rblocks = be64_to_cpu(from->sb_rblocks); |
804 | to->sb_rextents = be64_to_cpu(from->sb_rextents); |
805 | memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid)); |
806 | to->sb_logstart = be64_to_cpu(from->sb_logstart); |
807 | to->sb_rootino = be64_to_cpu(from->sb_rootino); |
808 | to->sb_rbmino = be64_to_cpu(from->sb_rbmino); |
809 | to->sb_rsumino = be64_to_cpu(from->sb_rsumino); |
810 | to->sb_rextsize = be32_to_cpu(from->sb_rextsize); |
811 | to->sb_agblocks = be32_to_cpu(from->sb_agblocks); |
812 | to->sb_agcount = be32_to_cpu(from->sb_agcount); |
813 | to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks); |
814 | to->sb_logblocks = be32_to_cpu(from->sb_logblocks); |
815 | to->sb_versionnum = be16_to_cpu(from->sb_versionnum); |
816 | to->sb_sectsize = be16_to_cpu(from->sb_sectsize); |
817 | to->sb_inodesize = be16_to_cpu(from->sb_inodesize); |
818 | to->sb_inopblock = be16_to_cpu(from->sb_inopblock); |
819 | memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname)); |
820 | to->sb_blocklog = from->sb_blocklog; |
821 | to->sb_sectlog = from->sb_sectlog; |
822 | to->sb_inodelog = from->sb_inodelog; |
823 | to->sb_inopblog = from->sb_inopblog; |
824 | to->sb_agblklog = from->sb_agblklog; |
825 | to->sb_rextslog = from->sb_rextslog; |
826 | to->sb_inprogress = from->sb_inprogress; |
827 | to->sb_imax_pct = from->sb_imax_pct; |
828 | to->sb_icount = be64_to_cpu(from->sb_icount); |
829 | to->sb_ifree = be64_to_cpu(from->sb_ifree); |
830 | to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks); |
831 | to->sb_frextents = be64_to_cpu(from->sb_frextents); |
832 | to->sb_uquotino = be64_to_cpu(from->sb_uquotino); |
833 | to->sb_gquotino = be64_to_cpu(from->sb_gquotino); |
834 | to->sb_qflags = be16_to_cpu(from->sb_qflags); |
835 | to->sb_flags = from->sb_flags; |
836 | to->sb_shared_vn = from->sb_shared_vn; |
837 | to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt); |
838 | to->sb_unit = be32_to_cpu(from->sb_unit); |
839 | to->sb_width = be32_to_cpu(from->sb_width); |
840 | to->sb_dirblklog = from->sb_dirblklog; |
841 | to->sb_logsectlog = from->sb_logsectlog; |
842 | to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize); |
843 | to->sb_logsunit = be32_to_cpu(from->sb_logsunit); |
844 | to->sb_features2 = be32_to_cpu(from->sb_features2); |
845 | to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2); |
846 | to->sb_features_compat = be32_to_cpu(from->sb_features_compat); |
847 | to->sb_features_ro_compat = be32_to_cpu(from->sb_features_ro_compat); |
848 | to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat); |
849 | to->sb_features_log_incompat = |
850 | be32_to_cpu(from->sb_features_log_incompat); |
851 | /* crc is only used on disk, not in memory; just init to 0 here. */ |
852 | to->sb_crc = 0; |
853 | to->sb_spino_align = be32_to_cpu(from->sb_spino_align); |
854 | to->sb_pquotino = be64_to_cpu(from->sb_pquotino); |
855 | to->sb_lsn = be64_to_cpu(from->sb_lsn); |
856 | /* |
857 | * sb_meta_uuid is only on disk if it differs from sb_uuid and the |
858 | * feature flag is set; if not set we keep it only in memory. |
859 | */ |
860 | if (xfs_sb_is_v5(to) && |
861 | (to->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID)) |
862 | uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid); |
863 | else |
864 | uuid_copy(&to->sb_meta_uuid, &from->sb_uuid); |
865 | /* Convert on-disk flags to in-memory flags? */ |
866 | if (convert_xquota) |
867 | xfs_sb_quota_from_disk(sbp: to); |
868 | |
869 | if (to->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) { |
870 | to->sb_metadirino = be64_to_cpu(from->sb_metadirino); |
871 | to->sb_rgblklog = from->sb_rgblklog; |
872 | memcpy(to->sb_pad, from->sb_pad, sizeof(to->sb_pad)); |
873 | to->sb_rgcount = be32_to_cpu(from->sb_rgcount); |
874 | to->sb_rgextents = be32_to_cpu(from->sb_rgextents); |
875 | to->sb_rbmino = NULLFSINO; |
876 | to->sb_rsumino = NULLFSINO; |
877 | } else { |
878 | to->sb_metadirino = NULLFSINO; |
879 | to->sb_rgcount = 1; |
880 | to->sb_rgextents = 0; |
881 | } |
882 | |
883 | if (to->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_ZONED) { |
884 | to->sb_rtstart = be64_to_cpu(from->sb_rtstart); |
885 | to->sb_rtreserved = be64_to_cpu(from->sb_rtreserved); |
886 | } else { |
887 | to->sb_rtstart = 0; |
888 | to->sb_rtreserved = 0; |
889 | } |
890 | } |
891 | |
892 | void |
893 | xfs_sb_from_disk( |
894 | struct xfs_sb *to, |
895 | struct xfs_dsb *from) |
896 | { |
897 | __xfs_sb_from_disk(to, from, true); |
898 | } |
899 | |
900 | static void |
901 | xfs_sb_quota_to_disk( |
902 | struct xfs_dsb *to, |
903 | struct xfs_sb *from) |
904 | { |
905 | uint16_t qflags = from->sb_qflags; |
906 | |
907 | if (xfs_sb_is_v5(from) && |
908 | (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) { |
909 | to->sb_qflags = cpu_to_be16(from->sb_qflags); |
910 | to->sb_uquotino = cpu_to_be64(0); |
911 | to->sb_gquotino = cpu_to_be64(0); |
912 | to->sb_pquotino = cpu_to_be64(0); |
913 | return; |
914 | } |
915 | |
916 | to->sb_uquotino = cpu_to_be64(from->sb_uquotino); |
917 | |
918 | /* |
919 | * The in-memory superblock quota state matches the v5 on-disk format so |
920 | * just write them out and return |
921 | */ |
922 | if (xfs_sb_is_v5(from)) { |
923 | to->sb_qflags = cpu_to_be16(from->sb_qflags); |
924 | to->sb_gquotino = cpu_to_be64(from->sb_gquotino); |
925 | to->sb_pquotino = cpu_to_be64(from->sb_pquotino); |
926 | return; |
927 | } |
928 | |
929 | /* |
930 | * For older superblocks (v4), the in-core version of sb_qflags do not |
931 | * have XFS_OQUOTA_* flags, whereas the on-disk version does. So, |
932 | * convert incore XFS_{PG}QUOTA_* flags to on-disk XFS_OQUOTA_* flags. |
933 | */ |
934 | qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD | |
935 | XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD); |
936 | |
937 | if (from->sb_qflags & |
938 | (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD)) |
939 | qflags |= XFS_OQUOTA_ENFD; |
940 | if (from->sb_qflags & |
941 | (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) |
942 | qflags |= XFS_OQUOTA_CHKD; |
943 | to->sb_qflags = cpu_to_be16(qflags); |
944 | |
945 | /* |
946 | * GQUOTINO and PQUOTINO cannot be used together in versions |
947 | * of superblock that do not have pquotino. from->sb_flags |
948 | * tells us which quota is active and should be copied to |
949 | * disk. If neither are active, we should NULL the inode. |
950 | * |
951 | * In all cases, the separate pquotino must remain 0 because it |
952 | * is beyond the "end" of the valid non-pquotino superblock. |
953 | */ |
954 | if (from->sb_qflags & XFS_GQUOTA_ACCT) |
955 | to->sb_gquotino = cpu_to_be64(from->sb_gquotino); |
956 | else if (from->sb_qflags & XFS_PQUOTA_ACCT) |
957 | to->sb_gquotino = cpu_to_be64(from->sb_pquotino); |
958 | else { |
959 | /* |
960 | * We can't rely on just the fields being logged to tell us |
961 | * that it is safe to write NULLFSINO - we should only do that |
962 | * if quotas are not actually enabled. Hence only write |
963 | * NULLFSINO if both in-core quota inodes are NULL. |
964 | */ |
965 | if (from->sb_gquotino == NULLFSINO && |
966 | from->sb_pquotino == NULLFSINO) |
967 | to->sb_gquotino = cpu_to_be64(NULLFSINO); |
968 | } |
969 | |
970 | to->sb_pquotino = 0; |
971 | } |
972 | |
973 | void |
974 | xfs_sb_to_disk( |
975 | struct xfs_dsb *to, |
976 | struct xfs_sb *from) |
977 | { |
978 | xfs_sb_quota_to_disk(to, from); |
979 | |
980 | to->sb_magicnum = cpu_to_be32(from->sb_magicnum); |
981 | to->sb_blocksize = cpu_to_be32(from->sb_blocksize); |
982 | to->sb_dblocks = cpu_to_be64(from->sb_dblocks); |
983 | to->sb_rblocks = cpu_to_be64(from->sb_rblocks); |
984 | to->sb_rextents = cpu_to_be64(from->sb_rextents); |
985 | memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid)); |
986 | to->sb_logstart = cpu_to_be64(from->sb_logstart); |
987 | to->sb_rootino = cpu_to_be64(from->sb_rootino); |
988 | to->sb_rbmino = cpu_to_be64(from->sb_rbmino); |
989 | to->sb_rsumino = cpu_to_be64(from->sb_rsumino); |
990 | to->sb_rextsize = cpu_to_be32(from->sb_rextsize); |
991 | to->sb_agblocks = cpu_to_be32(from->sb_agblocks); |
992 | to->sb_agcount = cpu_to_be32(from->sb_agcount); |
993 | to->sb_rbmblocks = cpu_to_be32(from->sb_rbmblocks); |
994 | to->sb_logblocks = cpu_to_be32(from->sb_logblocks); |
995 | to->sb_versionnum = cpu_to_be16(from->sb_versionnum); |
996 | to->sb_sectsize = cpu_to_be16(from->sb_sectsize); |
997 | to->sb_inodesize = cpu_to_be16(from->sb_inodesize); |
998 | to->sb_inopblock = cpu_to_be16(from->sb_inopblock); |
999 | memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname)); |
1000 | to->sb_blocklog = from->sb_blocklog; |
1001 | to->sb_sectlog = from->sb_sectlog; |
1002 | to->sb_inodelog = from->sb_inodelog; |
1003 | to->sb_inopblog = from->sb_inopblog; |
1004 | to->sb_agblklog = from->sb_agblklog; |
1005 | to->sb_rextslog = from->sb_rextslog; |
1006 | to->sb_inprogress = from->sb_inprogress; |
1007 | to->sb_imax_pct = from->sb_imax_pct; |
1008 | to->sb_icount = cpu_to_be64(from->sb_icount); |
1009 | to->sb_ifree = cpu_to_be64(from->sb_ifree); |
1010 | to->sb_fdblocks = cpu_to_be64(from->sb_fdblocks); |
1011 | to->sb_frextents = cpu_to_be64(from->sb_frextents); |
1012 | |
1013 | to->sb_flags = from->sb_flags; |
1014 | to->sb_shared_vn = from->sb_shared_vn; |
1015 | to->sb_inoalignmt = cpu_to_be32(from->sb_inoalignmt); |
1016 | to->sb_unit = cpu_to_be32(from->sb_unit); |
1017 | to->sb_width = cpu_to_be32(from->sb_width); |
1018 | to->sb_dirblklog = from->sb_dirblklog; |
1019 | to->sb_logsectlog = from->sb_logsectlog; |
1020 | to->sb_logsectsize = cpu_to_be16(from->sb_logsectsize); |
1021 | to->sb_logsunit = cpu_to_be32(from->sb_logsunit); |
1022 | |
1023 | /* |
1024 | * We need to ensure that bad_features2 always matches features2. |
1025 | * Hence we enforce that here rather than having to remember to do it |
1026 | * everywhere else that updates features2. |
1027 | */ |
1028 | from->sb_bad_features2 = from->sb_features2; |
1029 | to->sb_features2 = cpu_to_be32(from->sb_features2); |
1030 | to->sb_bad_features2 = cpu_to_be32(from->sb_bad_features2); |
1031 | |
1032 | if (!xfs_sb_is_v5(from)) |
1033 | return; |
1034 | |
1035 | to->sb_features_compat = cpu_to_be32(from->sb_features_compat); |
1036 | to->sb_features_ro_compat = |
1037 | cpu_to_be32(from->sb_features_ro_compat); |
1038 | to->sb_features_incompat = |
1039 | cpu_to_be32(from->sb_features_incompat); |
1040 | to->sb_features_log_incompat = |
1041 | cpu_to_be32(from->sb_features_log_incompat); |
1042 | to->sb_spino_align = cpu_to_be32(from->sb_spino_align); |
1043 | to->sb_lsn = cpu_to_be64(from->sb_lsn); |
1044 | if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID) |
1045 | uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid); |
1046 | |
1047 | if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR) { |
1048 | to->sb_metadirino = cpu_to_be64(from->sb_metadirino); |
1049 | to->sb_rgblklog = from->sb_rgblklog; |
1050 | memset(to->sb_pad, 0, sizeof(to->sb_pad)); |
1051 | to->sb_rgcount = cpu_to_be32(from->sb_rgcount); |
1052 | to->sb_rgextents = cpu_to_be32(from->sb_rgextents); |
1053 | to->sb_rbmino = cpu_to_be64(0); |
1054 | to->sb_rsumino = cpu_to_be64(0); |
1055 | } |
1056 | |
1057 | if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_ZONED) { |
1058 | to->sb_rtstart = cpu_to_be64(from->sb_rtstart); |
1059 | to->sb_rtreserved = cpu_to_be64(from->sb_rtreserved); |
1060 | } |
1061 | } |
1062 | |
1063 | /* |
1064 | * If the superblock has the CRC feature bit set or the CRC field is non-null, |
1065 | * check that the CRC is valid. We check the CRC field is non-null because a |
1066 | * single bit error could clear the feature bit and unused parts of the |
1067 | * superblock are supposed to be zero. Hence a non-null crc field indicates that |
1068 | * we've potentially lost a feature bit and we should check it anyway. |
1069 | * |
1070 | * However, past bugs (i.e. in growfs) left non-zeroed regions beyond the |
1071 | * last field in V4 secondary superblocks. So for secondary superblocks, |
1072 | * we are more forgiving, and ignore CRC failures if the primary doesn't |
1073 | * indicate that the fs version is V5. |
1074 | */ |
1075 | static void |
1076 | xfs_sb_read_verify( |
1077 | struct xfs_buf *bp) |
1078 | { |
1079 | struct xfs_sb sb; |
1080 | struct xfs_mount *mp = bp->b_mount; |
1081 | struct xfs_dsb *dsb = bp->b_addr; |
1082 | int error; |
1083 | |
1084 | /* |
1085 | * open code the version check to avoid needing to convert the entire |
1086 | * superblock from disk order just to check the version number |
1087 | */ |
1088 | if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC) && |
1089 | (((be16_to_cpu(dsb->sb_versionnum) & XFS_SB_VERSION_NUMBITS) == |
1090 | XFS_SB_VERSION_5) || |
1091 | dsb->sb_crc != 0)) { |
1092 | |
1093 | if (!xfs_buf_verify_cksum(bp, XFS_SB_CRC_OFF)) { |
1094 | /* Only fail bad secondaries on a known V5 filesystem */ |
1095 | if (xfs_buf_daddr(bp) == XFS_SB_DADDR || |
1096 | xfs_has_crc(mp)) { |
1097 | error = -EFSBADCRC; |
1098 | goto out_error; |
1099 | } |
1100 | } |
1101 | } |
1102 | |
1103 | /* |
1104 | * Check all the superblock fields. Don't byteswap the xquota flags |
1105 | * because _verify_common checks the on-disk values. |
1106 | */ |
1107 | __xfs_sb_from_disk(&sb, dsb, false); |
1108 | error = xfs_validate_sb_common(mp, bp, &sb); |
1109 | if (error) |
1110 | goto out_error; |
1111 | error = xfs_validate_sb_read(mp, &sb); |
1112 | |
1113 | out_error: |
1114 | if (error == -EFSCORRUPTED || error == -EFSBADCRC) |
1115 | xfs_verifier_error(bp, error, __this_address); |
1116 | else if (error) |
1117 | xfs_buf_ioerror(bp, error); |
1118 | } |
1119 | |
1120 | /* |
1121 | * We may be probed for a filesystem match, so we may not want to emit |
1122 | * messages when the superblock buffer is not actually an XFS superblock. |
1123 | * If we find an XFS superblock, then run a normal, noisy mount because we are |
1124 | * really going to mount it and want to know about errors. |
1125 | */ |
1126 | static void |
1127 | xfs_sb_quiet_read_verify( |
1128 | struct xfs_buf *bp) |
1129 | { |
1130 | struct xfs_dsb *dsb = bp->b_addr; |
1131 | |
1132 | if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC)) { |
1133 | /* XFS filesystem, verify noisily! */ |
1134 | xfs_sb_read_verify(bp); |
1135 | return; |
1136 | } |
1137 | /* quietly fail */ |
1138 | xfs_buf_ioerror(bp, -EWRONGFS); |
1139 | } |
1140 | |
1141 | static void |
1142 | xfs_sb_write_verify( |
1143 | struct xfs_buf *bp) |
1144 | { |
1145 | struct xfs_sb sb; |
1146 | struct xfs_mount *mp = bp->b_mount; |
1147 | struct xfs_buf_log_item *bip = bp->b_log_item; |
1148 | struct xfs_dsb *dsb = bp->b_addr; |
1149 | int error; |
1150 | |
1151 | /* |
1152 | * Check all the superblock fields. Don't byteswap the xquota flags |
1153 | * because _verify_common checks the on-disk values. |
1154 | */ |
1155 | __xfs_sb_from_disk(&sb, dsb, false); |
1156 | error = xfs_validate_sb_common(mp, bp, &sb); |
1157 | if (error) |
1158 | goto out_error; |
1159 | error = xfs_validate_sb_write(mp, bp, &sb); |
1160 | if (error) |
1161 | goto out_error; |
1162 | |
1163 | if (!xfs_sb_is_v5(&sb)) |
1164 | return; |
1165 | |
1166 | if (bip) |
1167 | dsb->sb_lsn = cpu_to_be64(bip->bli_item.li_lsn); |
1168 | |
1169 | xfs_buf_update_cksum(bp, XFS_SB_CRC_OFF); |
1170 | return; |
1171 | |
1172 | out_error: |
1173 | xfs_verifier_error(bp, error, __this_address); |
1174 | } |
1175 | |
1176 | const struct xfs_buf_ops xfs_sb_buf_ops = { |
1177 | .name = "xfs_sb", |
1178 | .magic = { cpu_to_be32(XFS_SB_MAGIC), cpu_to_be32(XFS_SB_MAGIC) }, |
1179 | .verify_read = xfs_sb_read_verify, |
1180 | .verify_write = xfs_sb_write_verify, |
1181 | }; |
1182 | |
1183 | const struct xfs_buf_ops xfs_sb_quiet_buf_ops = { |
1184 | .name = "xfs_sb_quiet", |
1185 | .magic = { cpu_to_be32(XFS_SB_MAGIC), cpu_to_be32(XFS_SB_MAGIC) }, |
1186 | .verify_read = xfs_sb_quiet_read_verify, |
1187 | .verify_write = xfs_sb_write_verify, |
1188 | }; |
1189 | |
1190 | /* Compute cached rt geometry from the incore sb. */ |
1191 | void |
1192 | xfs_sb_mount_rextsize( |
1193 | struct xfs_mount *mp, |
1194 | struct xfs_sb *sbp) |
1195 | { |
1196 | struct xfs_groups *rgs = &mp->m_groups[XG_TYPE_RTG]; |
1197 | |
1198 | mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize); |
1199 | mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize); |
1200 | |
1201 | if (xfs_sb_is_v5(sbp) && |
1202 | (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) { |
1203 | rgs->blocks = sbp->sb_rgextents * sbp->sb_rextsize; |
1204 | rgs->blklog = mp->m_sb.sb_rgblklog; |
1205 | rgs->blkmask = xfs_mask32lo(mp->m_sb.sb_rgblklog); |
1206 | rgs->start_fsb = mp->m_sb.sb_rtstart; |
1207 | if (xfs_sb_has_incompat_feature(sbp, |
1208 | XFS_SB_FEAT_INCOMPAT_ZONE_GAPS)) |
1209 | rgs->has_daddr_gaps = true; |
1210 | } else { |
1211 | rgs->blocks = 0; |
1212 | rgs->blklog = 0; |
1213 | rgs->blkmask = (uint64_t)-1; |
1214 | } |
1215 | } |
1216 | |
1217 | /* Update incore sb rt extent size, then recompute the cached rt geometry. */ |
1218 | void |
1219 | xfs_mount_sb_set_rextsize( |
1220 | struct xfs_mount *mp, |
1221 | struct xfs_sb *sbp, |
1222 | xfs_agblock_t rextsize) |
1223 | { |
1224 | sbp->sb_rextsize = rextsize; |
1225 | if (xfs_sb_is_v5(sbp) && |
1226 | (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) |
1227 | sbp->sb_rgblklog = xfs_compute_rgblklog(sbp->sb_rgextents, |
1228 | rextsize); |
1229 | |
1230 | xfs_sb_mount_rextsize(mp, sbp); |
1231 | } |
1232 | |
1233 | /* |
1234 | * xfs_mount_common |
1235 | * |
1236 | * Mount initialization code establishing various mount |
1237 | * fields from the superblock associated with the given |
1238 | * mount structure. |
1239 | * |
1240 | * Inode geometry are calculated in xfs_ialloc_setup_geometry. |
1241 | */ |
1242 | void |
1243 | xfs_sb_mount_common( |
1244 | struct xfs_mount *mp, |
1245 | struct xfs_sb *sbp) |
1246 | { |
1247 | struct xfs_groups *ags = &mp->m_groups[XG_TYPE_AG]; |
1248 | |
1249 | mp->m_agfrotor = 0; |
1250 | atomic_set(&mp->m_agirotor, 0); |
1251 | mp->m_maxagi = mp->m_sb.sb_agcount; |
1252 | mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG; |
1253 | mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT; |
1254 | mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; |
1255 | mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1; |
1256 | mp->m_blockmask = sbp->sb_blocksize - 1; |
1257 | mp->m_blockwsize = xfs_rtbmblock_size(sbp) >> XFS_WORDLOG; |
1258 | mp->m_rtx_per_rbmblock = mp->m_blockwsize << XFS_NBWORDLOG; |
1259 | |
1260 | ags->blocks = mp->m_sb.sb_agblocks; |
1261 | ags->blklog = mp->m_sb.sb_agblklog; |
1262 | ags->blkmask = xfs_mask32lo(mp->m_sb.sb_agblklog); |
1263 | |
1264 | xfs_sb_mount_rextsize(mp, sbp); |
1265 | |
1266 | mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, true); |
1267 | mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, false); |
1268 | mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2; |
1269 | mp->m_alloc_mnr[1] = mp->m_alloc_mxr[1] / 2; |
1270 | |
1271 | mp->m_bmap_dmxr[0] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, true); |
1272 | mp->m_bmap_dmxr[1] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, false); |
1273 | mp->m_bmap_dmnr[0] = mp->m_bmap_dmxr[0] / 2; |
1274 | mp->m_bmap_dmnr[1] = mp->m_bmap_dmxr[1] / 2; |
1275 | |
1276 | mp->m_rmap_mxr[0] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, true); |
1277 | mp->m_rmap_mxr[1] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, false); |
1278 | mp->m_rmap_mnr[0] = mp->m_rmap_mxr[0] / 2; |
1279 | mp->m_rmap_mnr[1] = mp->m_rmap_mxr[1] / 2; |
1280 | |
1281 | mp->m_rtrmap_mxr[0] = xfs_rtrmapbt_maxrecs(mp, sbp->sb_blocksize, true); |
1282 | mp->m_rtrmap_mxr[1] = xfs_rtrmapbt_maxrecs(mp, sbp->sb_blocksize, false); |
1283 | mp->m_rtrmap_mnr[0] = mp->m_rtrmap_mxr[0] / 2; |
1284 | mp->m_rtrmap_mnr[1] = mp->m_rtrmap_mxr[1] / 2; |
1285 | |
1286 | mp->m_refc_mxr[0] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize, true); |
1287 | mp->m_refc_mxr[1] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize, false); |
1288 | mp->m_refc_mnr[0] = mp->m_refc_mxr[0] / 2; |
1289 | mp->m_refc_mnr[1] = mp->m_refc_mxr[1] / 2; |
1290 | |
1291 | mp->m_rtrefc_mxr[0] = xfs_rtrefcountbt_maxrecs(mp, sbp->sb_blocksize, |
1292 | true); |
1293 | mp->m_rtrefc_mxr[1] = xfs_rtrefcountbt_maxrecs(mp, sbp->sb_blocksize, |
1294 | false); |
1295 | mp->m_rtrefc_mnr[0] = mp->m_rtrefc_mxr[0] / 2; |
1296 | mp->m_rtrefc_mnr[1] = mp->m_rtrefc_mxr[1] / 2; |
1297 | |
1298 | mp->m_bsize = XFS_FSB_TO_BB(mp, 1); |
1299 | mp->m_alloc_set_aside = xfs_alloc_set_aside(mp); |
1300 | mp->m_ag_max_usable = xfs_alloc_ag_max_usable(mp); |
1301 | } |
1302 | |
1303 | /* |
1304 | * xfs_log_sb() can be used to copy arbitrary changes to the in-core superblock |
1305 | * into the superblock buffer to be logged. It does not provide the higher |
1306 | * level of locking that is needed to protect the in-core superblock from |
1307 | * concurrent access. |
1308 | */ |
1309 | void |
1310 | xfs_log_sb( |
1311 | struct xfs_trans *tp) |
1312 | { |
1313 | struct xfs_mount *mp = tp->t_mountp; |
1314 | struct xfs_buf *bp = xfs_trans_getsb(tp); |
1315 | |
1316 | /* |
1317 | * Lazy sb counters don't update the in-core superblock so do that now. |
1318 | * If this is at unmount, the counters will be exactly correct, but at |
1319 | * any other time they will only be ballpark correct because of |
1320 | * reservations that have been taken out percpu counters. If we have an |
1321 | * unclean shutdown, this will be corrected by log recovery rebuilding |
1322 | * the counters from the AGF block counts. |
1323 | */ |
1324 | if (xfs_has_lazysbcount(mp)) { |
1325 | mp->m_sb.sb_icount = percpu_counter_sum_positive(&mp->m_icount); |
1326 | mp->m_sb.sb_ifree = min_t(uint64_t, |
1327 | percpu_counter_sum_positive(&mp->m_ifree), |
1328 | mp->m_sb.sb_icount); |
1329 | mp->m_sb.sb_fdblocks = xfs_sum_freecounter(mp, XC_FREE_BLOCKS); |
1330 | } |
1331 | |
1332 | /* |
1333 | * sb_frextents was added to the lazy sb counters when the rt groups |
1334 | * feature was introduced. This counter can go negative due to the way |
1335 | * we handle nearly-lockless reservations, so we must use the _positive |
1336 | * variant here to avoid writing out nonsense frextents. |
1337 | */ |
1338 | if (xfs_has_rtgroups(mp) && !xfs_has_zoned(mp)) { |
1339 | mp->m_sb.sb_frextents = |
1340 | xfs_sum_freecounter(mp, XC_FREE_RTEXTENTS); |
1341 | } |
1342 | |
1343 | xfs_sb_to_disk(to: bp->b_addr, from: &mp->m_sb); |
1344 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); |
1345 | xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb) - 1); |
1346 | } |
1347 | |
1348 | /* |
1349 | * xfs_sync_sb |
1350 | * |
1351 | * Sync the superblock to disk. |
1352 | * |
1353 | * Note that the caller is responsible for checking the frozen state of the |
1354 | * filesystem. This procedure uses the non-blocking transaction allocator and |
1355 | * thus will allow modifications to a frozen fs. This is required because this |
1356 | * code can be called during the process of freezing where use of the high-level |
1357 | * allocator would deadlock. |
1358 | */ |
1359 | int |
1360 | xfs_sync_sb( |
1361 | struct xfs_mount *mp, |
1362 | bool wait) |
1363 | { |
1364 | struct xfs_trans *tp; |
1365 | int error; |
1366 | |
1367 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, |
1368 | XFS_TRANS_NO_WRITECOUNT, &tp); |
1369 | if (error) |
1370 | return error; |
1371 | |
1372 | xfs_log_sb(tp); |
1373 | if (wait) |
1374 | xfs_trans_set_sync(tp); |
1375 | return xfs_trans_commit(tp); |
1376 | } |
1377 | |
1378 | /* |
1379 | * Update all the secondary superblocks to match the new state of the primary. |
1380 | * Because we are completely overwriting all the existing fields in the |
1381 | * secondary superblock buffers, there is no need to read them in from disk. |
1382 | * Just get a new buffer, stamp it and write it. |
1383 | * |
1384 | * The sb buffers need to be cached here so that we serialise against other |
1385 | * operations that access the secondary superblocks, but we don't want to keep |
1386 | * them in memory once it is written so we mark it as a one-shot buffer. |
1387 | */ |
1388 | int |
1389 | xfs_update_secondary_sbs( |
1390 | struct xfs_mount *mp) |
1391 | { |
1392 | struct xfs_perag *pag = NULL; |
1393 | int saved_error = 0; |
1394 | int error = 0; |
1395 | LIST_HEAD (buffer_list); |
1396 | |
1397 | /* update secondary superblocks. */ |
1398 | while ((pag = xfs_perag_next_from(mp, pag, 1))) { |
1399 | struct xfs_buf *bp; |
1400 | |
1401 | error = xfs_buf_get(mp->m_ddev_targp, |
1402 | XFS_AG_DADDR(mp, pag_agno(pag), XFS_SB_DADDR), |
1403 | XFS_FSS_TO_BB(mp, 1), &bp); |
1404 | /* |
1405 | * If we get an error reading or writing alternate superblocks, |
1406 | * continue. xfs_repair chooses the "best" superblock based |
1407 | * on most matches; if we break early, we'll leave more |
1408 | * superblocks un-updated than updated, and xfs_repair may |
1409 | * pick them over the properly-updated primary. |
1410 | */ |
1411 | if (error) { |
1412 | xfs_warn(mp, |
1413 | "error allocating secondary superblock for ag %d", |
1414 | pag_agno(pag)); |
1415 | if (!saved_error) |
1416 | saved_error = error; |
1417 | continue; |
1418 | } |
1419 | |
1420 | bp->b_ops = &xfs_sb_buf_ops; |
1421 | xfs_buf_oneshot(bp); |
1422 | xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); |
1423 | xfs_sb_to_disk(to: bp->b_addr, from: &mp->m_sb); |
1424 | xfs_buf_delwri_queue(bp, &buffer_list); |
1425 | xfs_buf_relse(bp); |
1426 | |
1427 | /* don't hold too many buffers at once */ |
1428 | if (pag_agno(pag) % 16) |
1429 | continue; |
1430 | |
1431 | error = xfs_buf_delwri_submit(&buffer_list); |
1432 | if (error) { |
1433 | xfs_warn(mp, |
1434 | "write error %d updating a secondary superblock near ag %d", |
1435 | error, pag_agno(pag)); |
1436 | if (!saved_error) |
1437 | saved_error = error; |
1438 | continue; |
1439 | } |
1440 | } |
1441 | error = xfs_buf_delwri_submit(&buffer_list); |
1442 | if (error) |
1443 | xfs_warn(mp, "error %d writing secondary superblocks", error); |
1444 | return saved_error ? saved_error : error; |
1445 | } |
1446 | |
1447 | /* |
1448 | * Same behavior as xfs_sync_sb, except that it is always synchronous and it |
1449 | * also writes the superblock buffer to disk sector 0 immediately. |
1450 | */ |
1451 | int |
1452 | xfs_sync_sb_buf( |
1453 | struct xfs_mount *mp, |
1454 | bool update_rtsb) |
1455 | { |
1456 | struct xfs_trans *tp; |
1457 | struct xfs_buf *bp; |
1458 | struct xfs_buf *rtsb_bp = NULL; |
1459 | int error; |
1460 | |
1461 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp); |
1462 | if (error) |
1463 | return error; |
1464 | |
1465 | bp = xfs_trans_getsb(tp); |
1466 | xfs_log_sb(tp); |
1467 | xfs_trans_bhold(tp, bp); |
1468 | if (update_rtsb) { |
1469 | rtsb_bp = xfs_log_rtsb(tp, sb_bp: bp); |
1470 | if (rtsb_bp) |
1471 | xfs_trans_bhold(tp, rtsb_bp); |
1472 | } |
1473 | xfs_trans_set_sync(tp); |
1474 | error = xfs_trans_commit(tp); |
1475 | if (error) |
1476 | goto out; |
1477 | /* |
1478 | * write out the sb buffer to get the changes to disk |
1479 | */ |
1480 | error = xfs_bwrite(bp); |
1481 | if (!error && rtsb_bp) |
1482 | error = xfs_bwrite(rtsb_bp); |
1483 | out: |
1484 | if (rtsb_bp) |
1485 | xfs_buf_relse(rtsb_bp); |
1486 | xfs_buf_relse(bp); |
1487 | return error; |
1488 | } |
1489 | |
1490 | void |
1491 | xfs_fs_geometry( |
1492 | struct xfs_mount *mp, |
1493 | struct xfs_fsop_geom *geo, |
1494 | int struct_version) |
1495 | { |
1496 | struct xfs_sb *sbp = &mp->m_sb; |
1497 | |
1498 | memset(geo, 0, sizeof(struct xfs_fsop_geom)); |
1499 | |
1500 | geo->blocksize = sbp->sb_blocksize; |
1501 | geo->rtextsize = sbp->sb_rextsize; |
1502 | geo->agblocks = sbp->sb_agblocks; |
1503 | geo->agcount = sbp->sb_agcount; |
1504 | geo->logblocks = sbp->sb_logblocks; |
1505 | geo->sectsize = sbp->sb_sectsize; |
1506 | geo->inodesize = sbp->sb_inodesize; |
1507 | geo->imaxpct = sbp->sb_imax_pct; |
1508 | geo->datablocks = sbp->sb_dblocks; |
1509 | geo->rtblocks = sbp->sb_rblocks; |
1510 | geo->rtextents = sbp->sb_rextents; |
1511 | geo->logstart = sbp->sb_logstart; |
1512 | BUILD_BUG_ON(sizeof(geo->uuid) != sizeof(sbp->sb_uuid)); |
1513 | memcpy(geo->uuid, &sbp->sb_uuid, sizeof(sbp->sb_uuid)); |
1514 | |
1515 | if (struct_version < 2) |
1516 | return; |
1517 | |
1518 | geo->sunit = sbp->sb_unit; |
1519 | geo->swidth = sbp->sb_width; |
1520 | |
1521 | if (struct_version < 3) |
1522 | return; |
1523 | |
1524 | geo->version = XFS_FSOP_GEOM_VERSION; |
1525 | geo->flags = XFS_FSOP_GEOM_FLAGS_NLINK | |
1526 | XFS_FSOP_GEOM_FLAGS_DIRV2 | |
1527 | XFS_FSOP_GEOM_FLAGS_EXTFLG; |
1528 | if (xfs_has_attr(mp)) |
1529 | geo->flags |= XFS_FSOP_GEOM_FLAGS_ATTR; |
1530 | if (xfs_has_quota(mp)) |
1531 | geo->flags |= XFS_FSOP_GEOM_FLAGS_QUOTA; |
1532 | if (xfs_has_align(mp)) |
1533 | geo->flags |= XFS_FSOP_GEOM_FLAGS_IALIGN; |
1534 | if (xfs_has_dalign(mp)) |
1535 | geo->flags |= XFS_FSOP_GEOM_FLAGS_DALIGN; |
1536 | if (xfs_has_asciici(mp)) |
1537 | geo->flags |= XFS_FSOP_GEOM_FLAGS_DIRV2CI; |
1538 | if (xfs_has_lazysbcount(mp)) |
1539 | geo->flags |= XFS_FSOP_GEOM_FLAGS_LAZYSB; |
1540 | if (xfs_has_attr2(mp)) |
1541 | geo->flags |= XFS_FSOP_GEOM_FLAGS_ATTR2; |
1542 | if (xfs_has_projid32(mp)) |
1543 | geo->flags |= XFS_FSOP_GEOM_FLAGS_PROJID32; |
1544 | if (xfs_has_crc(mp)) |
1545 | geo->flags |= XFS_FSOP_GEOM_FLAGS_V5SB; |
1546 | if (xfs_has_ftype(mp)) |
1547 | geo->flags |= XFS_FSOP_GEOM_FLAGS_FTYPE; |
1548 | if (xfs_has_finobt(mp)) |
1549 | geo->flags |= XFS_FSOP_GEOM_FLAGS_FINOBT; |
1550 | if (xfs_has_sparseinodes(mp)) |
1551 | geo->flags |= XFS_FSOP_GEOM_FLAGS_SPINODES; |
1552 | if (xfs_has_rmapbt(mp)) |
1553 | geo->flags |= XFS_FSOP_GEOM_FLAGS_RMAPBT; |
1554 | if (xfs_has_reflink(mp)) |
1555 | geo->flags |= XFS_FSOP_GEOM_FLAGS_REFLINK; |
1556 | if (xfs_has_bigtime(mp)) |
1557 | geo->flags |= XFS_FSOP_GEOM_FLAGS_BIGTIME; |
1558 | if (xfs_has_inobtcounts(mp)) |
1559 | geo->flags |= XFS_FSOP_GEOM_FLAGS_INOBTCNT; |
1560 | if (xfs_has_parent(mp)) |
1561 | geo->flags |= XFS_FSOP_GEOM_FLAGS_PARENT; |
1562 | if (xfs_has_sector(mp)) { |
1563 | geo->flags |= XFS_FSOP_GEOM_FLAGS_SECTOR; |
1564 | geo->logsectsize = sbp->sb_logsectsize; |
1565 | } else { |
1566 | geo->logsectsize = BBSIZE; |
1567 | } |
1568 | if (xfs_has_large_extent_counts(mp)) |
1569 | geo->flags |= XFS_FSOP_GEOM_FLAGS_NREXT64; |
1570 | if (xfs_has_exchange_range(mp)) |
1571 | geo->flags |= XFS_FSOP_GEOM_FLAGS_EXCHANGE_RANGE; |
1572 | if (xfs_has_metadir(mp)) |
1573 | geo->flags |= XFS_FSOP_GEOM_FLAGS_METADIR; |
1574 | if (xfs_has_zoned(mp)) |
1575 | geo->flags |= XFS_FSOP_GEOM_FLAGS_ZONED; |
1576 | geo->rtsectsize = sbp->sb_blocksize; |
1577 | geo->dirblocksize = xfs_dir2_dirblock_bytes(sbp); |
1578 | |
1579 | if (struct_version < 4) |
1580 | return; |
1581 | |
1582 | if (xfs_has_logv2(mp)) |
1583 | geo->flags |= XFS_FSOP_GEOM_FLAGS_LOGV2; |
1584 | |
1585 | geo->logsunit = sbp->sb_logsunit; |
1586 | |
1587 | if (struct_version < 5) |
1588 | return; |
1589 | |
1590 | geo->version = XFS_FSOP_GEOM_VERSION_V5; |
1591 | |
1592 | if (xfs_has_rtgroups(mp)) { |
1593 | geo->rgcount = sbp->sb_rgcount; |
1594 | geo->rgextents = sbp->sb_rgextents; |
1595 | } |
1596 | if (xfs_has_zoned(mp)) { |
1597 | geo->rtstart = sbp->sb_rtstart; |
1598 | geo->rtreserved = sbp->sb_rtreserved; |
1599 | } |
1600 | } |
1601 | |
1602 | /* Read a secondary superblock. */ |
1603 | int |
1604 | xfs_sb_read_secondary( |
1605 | struct xfs_mount *mp, |
1606 | struct xfs_trans *tp, |
1607 | xfs_agnumber_t agno, |
1608 | struct xfs_buf **bpp) |
1609 | { |
1610 | struct xfs_buf *bp; |
1611 | int error; |
1612 | |
1613 | ASSERT(agno != 0 && agno != NULLAGNUMBER); |
1614 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, |
1615 | XFS_AG_DADDR(mp, agno, XFS_SB_BLOCK(mp)), |
1616 | XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_sb_buf_ops); |
1617 | if (xfs_metadata_is_sick(error)) |
1618 | xfs_agno_mark_sick(mp, agno, XFS_SICK_AG_SB); |
1619 | if (error) |
1620 | return error; |
1621 | xfs_buf_set_ref(bp, XFS_SSB_REF); |
1622 | *bpp = bp; |
1623 | return 0; |
1624 | } |
1625 | |
1626 | /* Get an uninitialised secondary superblock buffer. */ |
1627 | int |
1628 | xfs_sb_get_secondary( |
1629 | struct xfs_mount *mp, |
1630 | struct xfs_trans *tp, |
1631 | xfs_agnumber_t agno, |
1632 | struct xfs_buf **bpp) |
1633 | { |
1634 | struct xfs_buf *bp; |
1635 | int error; |
1636 | |
1637 | ASSERT(agno != 0 && agno != NULLAGNUMBER); |
1638 | error = xfs_trans_get_buf(tp, mp->m_ddev_targp, |
1639 | XFS_AG_DADDR(mp, agno, XFS_SB_BLOCK(mp)), |
1640 | XFS_FSS_TO_BB(mp, 1), 0, &bp); |
1641 | if (error) |
1642 | return error; |
1643 | bp->b_ops = &xfs_sb_buf_ops; |
1644 | xfs_buf_oneshot(bp); |
1645 | *bpp = bp; |
1646 | return 0; |
1647 | } |
1648 | |
1649 | /* |
1650 | * sunit, swidth, sectorsize(optional with 0) should be all in bytes, so users |
1651 | * won't be confused by values in error messages. This function returns false |
1652 | * if the stripe geometry is invalid and the caller is unable to repair the |
1653 | * stripe configuration later in the mount process. |
1654 | */ |
1655 | bool |
1656 | xfs_validate_stripe_geometry( |
1657 | struct xfs_mount *mp, |
1658 | __s64 sunit, |
1659 | __s64 swidth, |
1660 | int sectorsize, |
1661 | bool may_repair, |
1662 | bool silent) |
1663 | { |
1664 | if (swidth > INT_MAX) { |
1665 | if (!silent) |
1666 | xfs_notice(mp, |
1667 | "stripe width (%lld) is too large", swidth); |
1668 | goto check_override; |
1669 | } |
1670 | |
1671 | if (sunit > swidth) { |
1672 | if (!silent) |
1673 | xfs_notice(mp, |
1674 | "stripe unit (%lld) is larger than the stripe width (%lld)", sunit, swidth); |
1675 | goto check_override; |
1676 | } |
1677 | |
1678 | if (sectorsize && (int)sunit % sectorsize) { |
1679 | if (!silent) |
1680 | xfs_notice(mp, |
1681 | "stripe unit (%lld) must be a multiple of the sector size (%d)", |
1682 | sunit, sectorsize); |
1683 | goto check_override; |
1684 | } |
1685 | |
1686 | if (sunit && !swidth) { |
1687 | if (!silent) |
1688 | xfs_notice(mp, |
1689 | "invalid stripe unit (%lld) and stripe width of 0", sunit); |
1690 | goto check_override; |
1691 | } |
1692 | |
1693 | if (!sunit && swidth) { |
1694 | if (!silent) |
1695 | xfs_notice(mp, |
1696 | "invalid stripe width (%lld) and stripe unit of 0", swidth); |
1697 | goto check_override; |
1698 | } |
1699 | |
1700 | if (sunit && (int)swidth % (int)sunit) { |
1701 | if (!silent) |
1702 | xfs_notice(mp, |
1703 | "stripe width (%lld) must be a multiple of the stripe unit (%lld)", |
1704 | swidth, sunit); |
1705 | goto check_override; |
1706 | } |
1707 | return true; |
1708 | |
1709 | check_override: |
1710 | if (!may_repair) |
1711 | return false; |
1712 | /* |
1713 | * During mount, mp->m_dalign will not be set unless the sunit mount |
1714 | * option was set. If it was set, ignore the bad stripe alignment values |
1715 | * and allow the validation and overwrite later in the mount process to |
1716 | * attempt to overwrite the bad stripe alignment values with the values |
1717 | * supplied by mount options. |
1718 | */ |
1719 | if (!mp->m_dalign) |
1720 | return false; |
1721 | if (!silent) |
1722 | xfs_notice(mp, |
1723 | "Will try to correct with specified mount options sunit (%d) and swidth (%d)", |
1724 | BBTOB(mp->m_dalign), BBTOB(mp->m_swidth)); |
1725 | return true; |
1726 | } |
1727 | |
1728 | /* |
1729 | * Compute the maximum level number of the realtime summary file, as defined by |
1730 | * mkfs. The historic use of highbit32 on a 64-bit quantity prohibited correct |
1731 | * use of rt volumes with more than 2^32 extents. |
1732 | */ |
1733 | uint8_t |
1734 | xfs_compute_rextslog( |
1735 | xfs_rtbxlen_t rtextents) |
1736 | { |
1737 | if (!rtextents) |
1738 | return 0; |
1739 | return xfs_highbit64(rtextents); |
1740 | } |
1741 |
Definitions
- xfs_sb_validate_v5_features
- xfs_sb_good_version
- xfs_sb_version_to_features
- xfs_validate_sb_read
- xfs_extents_per_rbm
- xfs_rtbmblock_size
- xfs_expected_rbmblocks
- xfs_validate_rt_geometry
- xfs_validate_sb_write
- xfs_compute_rgblklog
- xfs_validate_sb_rtgroups
- xfs_validate_sb_zoned
- xfs_validate_sb_common
- xfs_sb_quota_from_disk
- __xfs_sb_from_disk
- xfs_sb_from_disk
- xfs_sb_quota_to_disk
- xfs_sb_to_disk
- xfs_sb_read_verify
- xfs_sb_quiet_read_verify
- xfs_sb_write_verify
- xfs_sb_buf_ops
- xfs_sb_quiet_buf_ops
- xfs_sb_mount_rextsize
- xfs_mount_sb_set_rextsize
- xfs_sb_mount_common
- xfs_log_sb
- xfs_sync_sb
- xfs_update_secondary_sbs
- xfs_sync_sb_buf
- xfs_fs_geometry
- xfs_sb_read_secondary
- xfs_sb_get_secondary
- xfs_validate_stripe_geometry
Improve your Profiling and Debugging skills
Find out more