]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_inode_buf.c
xfs: convert to ctime accessor functions
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_inode_buf.c
CommitLineData
37b3b4d6 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
5e656dbb 3 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
da23017d 4 * All Rights Reserved.
2bd0ea18 5 */
9c799827 6#include "libxfs_priv.h"
b626fb59
DC
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_mount.h"
8aa34dc9 13#include "xfs_ag.h"
b626fb59 14#include "xfs_inode.h"
2cf10e4c 15#include "xfs_errortag.h"
b626fb59
DC
16#include "xfs_trans.h"
17#include "xfs_ialloc.h"
0962b5b3 18#include "xfs_dir2.h"
2bd0ea18 19
998aed52 20
f85fc622
DC
21/*
22 * If we are doing readahead on an inode buffer, we might be in log recovery
23 * reading an inode allocation buffer that hasn't yet been replayed, and hence
24 * has not had the inode cores stamped into it. Hence for readahead, the buffer
25 * may be potentially invalid.
26 *
736e1cf6
DC
27 * If the readahead buffer is invalid, we need to mark it with an error and
28 * clear the DONE status of the buffer so that a followup read will re-read it
29 * from disk. We don't report the error otherwise to avoid warnings during log
c2f0ae02 30 * recovery and we don't get unnecessary panics on debug kernels. We use EIO here
736e1cf6
DC
31 * because all we want to do is say readahead failed; there is no-one to report
32 * the error to, so this will distinguish it from a non-ra verifier failure.
c2f0ae02 33 * Changes to this readahead error behaviour also need to be reflected in
6daba42a 34 * xfs_dquot_buf_readahead_verify().
f85fc622 35 */
a2ceac1f
DC
36static void
37xfs_inode_buf_verify(
f85fc622
DC
38 struct xfs_buf *bp,
39 bool readahead)
5e656dbb 40{
7861ef77 41 struct xfs_mount *mp = bp->b_mount;
5e656dbb
BN
42 int i;
43 int ni;
5e656dbb
BN
44
45 /*
46 * Validate the magic number and version of every inode in the buffer
5e656dbb 47 */
a2ceac1f 48 ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock;
5e656dbb 49 for (i = 0; i < ni; i++) {
7328ea6e
CH
50 struct xfs_dinode *dip;
51 xfs_agino_t unlinked_ino;
52 int di_ok;
5e656dbb 53
92acb899 54 dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog));
2949b467 55 unlinked_ino = be32_to_cpu(dip->di_next_unlinked);
9e26de8f 56 di_ok = xfs_verify_magic16(bp, dip->di_magic) &&
03d8044d 57 xfs_dinode_good_version(mp, dip->di_version) &&
8aa34dc9 58 xfs_verify_agino_or_null(bp->b_pag, unlinked_ino);
5e656dbb 59 if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
e2a190dd 60 XFS_ERRTAG_ITOBP_INOTOBP))) {
f85fc622
DC
61 if (readahead) {
62 bp->b_flags &= ~XBF_DONE;
736e1cf6 63 xfs_buf_ioerror(bp, -EIO);
f85fc622
DC
64 return;
65 }
66
5e656dbb 67#ifdef DEBUG
ea6a00d4 68 xfs_alert(mp,
a2ceac1f 69 "bad inode magic/vsn daddr %lld #%d (magic=%x)",
f1208396 70 (unsigned long long)xfs_buf_daddr(bp), i,
56b2de80 71 be16_to_cpu(dip->di_magic));
5e656dbb 72#endif
43f7ceb5
DW
73 xfs_buf_verifier_error(bp, -EFSCORRUPTED,
74 __func__, dip, sizeof(*dip),
75 NULL);
2949b467 76 return;
5e656dbb
BN
77 }
78 }
a2ceac1f 79}
5e656dbb 80
e6d77a21 81
a2ceac1f
DC
82static void
83xfs_inode_buf_read_verify(
84 struct xfs_buf *bp)
85{
f85fc622
DC
86 xfs_inode_buf_verify(bp, false);
87}
88
89static void
90xfs_inode_buf_readahead_verify(
91 struct xfs_buf *bp)
92{
93 xfs_inode_buf_verify(bp, true);
5e656dbb 94}
2bd0ea18 95
a2ceac1f
DC
96static void
97xfs_inode_buf_write_verify(
98 struct xfs_buf *bp)
56b2de80 99{
f85fc622 100 xfs_inode_buf_verify(bp, false);
56b2de80
DC
101}
102
a2ceac1f 103const struct xfs_buf_ops xfs_inode_buf_ops = {
a3fac935 104 .name = "xfs_inode",
9e26de8f
DW
105 .magic16 = { cpu_to_be16(XFS_DINODE_MAGIC),
106 cpu_to_be16(XFS_DINODE_MAGIC) },
a2ceac1f
DC
107 .verify_read = xfs_inode_buf_read_verify,
108 .verify_write = xfs_inode_buf_write_verify,
109};
110
f85fc622 111const struct xfs_buf_ops xfs_inode_buf_ra_ops = {
7563fc9c 112 .name = "xfs_inode_ra",
9e26de8f
DW
113 .magic16 = { cpu_to_be16(XFS_DINODE_MAGIC),
114 cpu_to_be16(XFS_DINODE_MAGIC) },
f85fc622
DC
115 .verify_read = xfs_inode_buf_readahead_verify,
116 .verify_write = xfs_inode_buf_write_verify,
117};
118
119
2bd0ea18 120/*
a2ceac1f
DC
121 * This routine is called to map an inode to the buffer containing the on-disk
122 * version of the inode. It returns a pointer to the buffer containing the
c074900b 123 * on-disk inode in the bpp parameter.
2bd0ea18
NS
124 */
125int
a2ceac1f
DC
126xfs_imap_to_bp(
127 struct xfs_mount *mp,
128 struct xfs_trans *tp,
129 struct xfs_imap *imap,
c074900b 130 struct xfs_buf **bpp)
2bd0ea18 131{
c074900b
CH
132 return xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno,
133 imap->im_len, XBF_UNMAPPED, bpp,
a2ceac1f 134 &xfs_inode_buf_ops);
2bd0ea18
NS
135}
136
e7e3beb9
DW
137static inline struct timespec64 xfs_inode_decode_bigtime(uint64_t ts)
138{
139 struct timespec64 tv;
140 uint32_t n;
141
142 tv.tv_sec = xfs_bigtime_to_unix(div_u64_rem(ts, NSEC_PER_SEC, &n));
143 tv.tv_nsec = n;
144
145 return tv;
146}
147
a252aadf
DW
148/* Convert an ondisk timestamp to an incore timestamp. */
149struct timespec64
150xfs_inode_from_disk_ts(
e7e3beb9 151 struct xfs_dinode *dip,
a252aadf
DW
152 const xfs_timestamp_t ts)
153{
154 struct timespec64 tv;
155 struct xfs_legacy_timestamp *lts;
156
e7e3beb9
DW
157 if (xfs_dinode_has_bigtime(dip))
158 return xfs_inode_decode_bigtime(be64_to_cpu(ts));
159
a252aadf
DW
160 lts = (struct xfs_legacy_timestamp *)&ts;
161 tv.tv_sec = (int)be32_to_cpu(lts->t_sec);
162 tv.tv_nsec = (int)be32_to_cpu(lts->t_nsec);
163
164 return tv;
165}
166
3eb685ae 167int
1bc6cbe3
DC
168xfs_inode_from_disk(
169 struct xfs_inode *ip,
138659f1 170 struct xfs_dinode *from)
2bd0ea18 171{
1bc6cbe3 172 struct inode *inode = VFS_I(ip);
07973a77 173 int error;
d1eeae6b 174 xfs_failaddr_t fa;
07973a77
CH
175
176 ASSERT(ip->i_cowfp == NULL);
1bc6cbe3 177
d1eeae6b
CH
178 fa = xfs_dinode_verify(ip->i_mount, ip->i_ino, from);
179 if (fa) {
180 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "dinode", from,
181 sizeof(*from), fa);
182 return -EFSCORRUPTED;
183 }
184
f47e002f
CH
185 /*
186 * First get the permanent information that is needed to allocate an
187 * inode. If the inode is unused, mode is zero and we shouldn't mess
c2f0ae02 188 * with the uninitialized part of it.
f47e002f 189 */
94541a16 190 if (!xfs_has_v3inodes(ip->i_mount))
dc1d7a09 191 ip->i_flushiter = be16_to_cpu(from->di_flushiter);
f47e002f
CH
192 inode->i_generation = be32_to_cpu(from->di_gen);
193 inode->i_mode = be16_to_cpu(from->di_mode);
194 if (!inode->i_mode)
195 return 0;
196
f089fc42
DC
197 /*
198 * Convert v1 inodes immediately to v2 inode format as this is the
199 * minimum inode version format we support in the rest of the code.
fd82a87e 200 * They will also be unconditionally written back to disk as v2 inodes.
f089fc42 201 */
fd82a87e 202 if (unlikely(from->di_version == 1)) {
bcbe04c1 203 set_nlink(inode, be16_to_cpu(from->di_onlink));
0ca7fa97 204 ip->i_projid = 0;
f089fc42 205 } else {
bcbe04c1 206 set_nlink(inode, be32_to_cpu(from->di_nlink));
0ca7fa97 207 ip->i_projid = (prid_t)be16_to_cpu(from->di_projid_hi) << 16 |
e6bd76f0 208 be16_to_cpu(from->di_projid_lo);
f089fc42
DC
209 }
210
100eb9e9
CH
211 i_uid_write(inode, be32_to_cpu(from->di_uid));
212 i_gid_write(inode, be32_to_cpu(from->di_gid));
1bc6cbe3
DC
213
214 /*
215 * Time is signed, so need to convert to signed 32 bit before
216 * storing in inode timestamp which may be 64 bit. Otherwise
217 * a time before epoch is converted to a time long after epoch
218 * on 64 bit systems.
219 */
e7e3beb9
DW
220 inode->i_atime = xfs_inode_from_disk_ts(from, from->di_atime);
221 inode->i_mtime = xfs_inode_from_disk_ts(from, from->di_mtime);
6cfd0b48
JL
222 inode_set_ctime_to_ts(inode,
223 xfs_inode_from_disk_ts(from, from->di_ctime));
1bc6cbe3 224
509dcb4b 225 ip->i_disk_size = be64_to_cpu(from->di_size);
aa00f286 226 ip->i_nblocks = be64_to_cpu(from->di_nblocks);
fd2f92c8 227 ip->i_extsize = be32_to_cpu(from->di_extsize);
073f2424 228 ip->i_forkoff = from->di_forkoff;
69535dad
DC
229 ip->i_diflags = be16_to_cpu(from->di_flags);
230 ip->i_next_unlinked = be32_to_cpu(from->di_next_unlinked);
41ce5f36 231
ed6a3429
CH
232 if (from->di_dmevmask || from->di_dmstate)
233 xfs_iflags_set(ip, XFS_IPRESERVE_DM_FIELDS);
234
94541a16 235 if (xfs_has_v3inodes(ip->i_mount)) {
d5105a89
JL
236 inode_set_iversion_queried(inode,
237 be64_to_cpu(from->di_changecount));
a1f6b388 238 ip->i_crtime = xfs_inode_from_disk_ts(from, from->di_crtime);
defd6446 239 ip->i_diflags2 = be64_to_cpu(from->di_flags2);
fd535ea4 240 ip->i_cowextsize = be32_to_cpu(from->di_cowextsize);
41ce5f36 241 }
3eb685ae 242
07973a77
CH
243 error = xfs_iformat_data_fork(ip, from);
244 if (error)
245 return error;
8c6cccd7 246 if (from->di_forkoff) {
07973a77
CH
247 error = xfs_iformat_attr_fork(ip, from);
248 if (error)
249 goto out_destroy_data_fork;
250 }
251 if (xfs_is_reflink_inode(ip))
252 xfs_ifork_init_cow(ip);
253 return 0;
254
255out_destroy_data_fork:
a87a40a2 256 xfs_idestroy_fork(&ip->i_df);
07973a77 257 return error;
5e656dbb
BN
258}
259
a252aadf
DW
260/* Convert an incore timestamp to an ondisk timestamp. */
261static inline xfs_timestamp_t
262xfs_inode_to_disk_ts(
e7e3beb9 263 struct xfs_inode *ip,
a252aadf
DW
264 const struct timespec64 tv)
265{
266 struct xfs_legacy_timestamp *lts;
267 xfs_timestamp_t ts;
268
e7e3beb9
DW
269 if (xfs_inode_has_bigtime(ip))
270 return cpu_to_be64(xfs_inode_encode_bigtime(tv));
271
a252aadf
DW
272 lts = (struct xfs_legacy_timestamp *)&ts;
273 lts->t_sec = cpu_to_be32(tv.tv_sec);
274 lts->t_nsec = cpu_to_be32(tv.tv_nsec);
275
276 return ts;
277}
278
8be26c6a
CB
279static inline void
280xfs_inode_to_disk_iext_counters(
281 struct xfs_inode *ip,
282 struct xfs_dinode *to)
283{
284 if (xfs_inode_has_large_extent_counts(ip)) {
285 to->di_big_nextents = cpu_to_be64(xfs_ifork_nextents(&ip->i_df));
7ff5f1ed 286 to->di_big_anextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_af));
8be26c6a
CB
287 /*
288 * We might be upgrading the inode to use larger extent counters
289 * than was previously used. Hence zero the unused field.
290 */
291 to->di_nrext64_pad = cpu_to_be16(0);
292 } else {
293 to->di_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
7ff5f1ed 294 to->di_anextents = cpu_to_be16(xfs_ifork_nextents(&ip->i_af));
8be26c6a
CB
295 }
296}
297
5e656dbb 298void
1bc6cbe3
DC
299xfs_inode_to_disk(
300 struct xfs_inode *ip,
db17aebe
DC
301 struct xfs_dinode *to,
302 xfs_lsn_t lsn)
1bc6cbe3 303{
1bc6cbe3
DC
304 struct inode *inode = VFS_I(ip);
305
db17aebe 306 to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
f089fc42 307 to->di_onlink = 0;
db17aebe 308
d967a68d 309 to->di_format = xfs_ifork_format(&ip->i_df);
100eb9e9
CH
310 to->di_uid = cpu_to_be32(i_uid_read(inode));
311 to->di_gid = cpu_to_be32(i_gid_read(inode));
0ca7fa97
CH
312 to->di_projid_lo = cpu_to_be16(ip->i_projid & 0xffff);
313 to->di_projid_hi = cpu_to_be16(ip->i_projid >> 16);
1bc6cbe3 314
e7e3beb9
DW
315 to->di_atime = xfs_inode_to_disk_ts(ip, inode->i_atime);
316 to->di_mtime = xfs_inode_to_disk_ts(ip, inode->i_mtime);
6cfd0b48 317 to->di_ctime = xfs_inode_to_disk_ts(ip, inode_get_ctime(inode));
bcbe04c1 318 to->di_nlink = cpu_to_be32(inode->i_nlink);
6652c253 319 to->di_gen = cpu_to_be32(inode->i_generation);
e37bf53c 320 to->di_mode = cpu_to_be16(inode->i_mode);
1bc6cbe3 321
509dcb4b 322 to->di_size = cpu_to_be64(ip->i_disk_size);
aa00f286 323 to->di_nblocks = cpu_to_be64(ip->i_nblocks);
fd2f92c8 324 to->di_extsize = cpu_to_be32(ip->i_extsize);
073f2424 325 to->di_forkoff = ip->i_forkoff;
7ff5f1ed 326 to->di_aformat = xfs_ifork_format(&ip->i_af);
4350eee7 327 to->di_flags = cpu_to_be16(ip->i_diflags);
1bc6cbe3 328
94541a16 329 if (xfs_has_v3inodes(ip->i_mount)) {
fd82a87e 330 to->di_version = 3;
d5105a89 331 to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
a1f6b388 332 to->di_crtime = xfs_inode_to_disk_ts(ip, ip->i_crtime);
defd6446 333 to->di_flags2 = cpu_to_be64(ip->i_diflags2);
fd535ea4 334 to->di_cowextsize = cpu_to_be32(ip->i_cowextsize);
db17aebe
DC
335 to->di_ino = cpu_to_be64(ip->i_ino);
336 to->di_lsn = cpu_to_be64(lsn);
337 memset(to->di_pad2, 0, sizeof(to->di_pad2));
338 uuid_copy(&to->di_uuid, &ip->i_mount->m_sb.sb_meta_uuid);
8be26c6a 339 to->di_v3_pad = 0;
1bc6cbe3 340 } else {
fd82a87e 341 to->di_version = 2;
36e4f363 342 to->di_flushiter = cpu_to_be16(ip->i_flushiter);
8be26c6a 343 memset(to->di_v2_pad, 0, sizeof(to->di_v2_pad));
1bc6cbe3 344 }
8be26c6a
CB
345
346 xfs_inode_to_disk_iext_counters(ip, to);
1bc6cbe3
DC
347}
348
8ac50baf
DC
349static xfs_failaddr_t
350xfs_dinode_verify_fork(
351 struct xfs_dinode *dip,
352 struct xfs_mount *mp,
353 int whichfork)
354{
5f70c91b 355 xfs_extnum_t di_nextents;
099e5eb3 356 xfs_extnum_t max_extents;
173809af
DC
357 mode_t mode = be16_to_cpu(dip->di_mode);
358 uint32_t fork_size = XFS_DFORK_SIZE(dip, mp, whichfork);
359 uint32_t fork_format = XFS_DFORK_FORMAT(dip, whichfork);
8ac50baf 360
5f70c91b
CB
361 di_nextents = xfs_dfork_nextents(dip, whichfork);
362
173809af
DC
363 /*
364 * For fork types that can contain local data, check that the fork
365 * format matches the size of local data contained within the fork.
366 *
367 * For all types, check that when the size says the should be in extent
368 * or btree format, the inode isn't claiming it is in local format.
369 */
370 if (whichfork == XFS_DATA_FORK) {
371 if (S_ISDIR(mode) || S_ISLNK(mode)) {
372 if (be64_to_cpu(dip->di_size) <= fork_size &&
373 fork_format != XFS_DINODE_FMT_LOCAL)
374 return __this_address;
375 }
376
377 if (be64_to_cpu(dip->di_size) > fork_size &&
378 fork_format == XFS_DINODE_FMT_LOCAL)
379 return __this_address;
380 }
381
382 switch (fork_format) {
8ac50baf
DC
383 case XFS_DINODE_FMT_LOCAL:
384 /*
173809af 385 * No local regular files yet.
8ac50baf 386 */
173809af
DC
387 if (S_ISREG(mode) && whichfork == XFS_DATA_FORK)
388 return __this_address;
8ac50baf
DC
389 if (di_nextents)
390 return __this_address;
391 break;
392 case XFS_DINODE_FMT_EXTENTS:
393 if (di_nextents > XFS_DFORK_MAXEXT(dip, mp, whichfork))
394 return __this_address;
395 break;
396 case XFS_DINODE_FMT_BTREE:
5a8b4d6a
CB
397 max_extents = xfs_iext_max_nextents(
398 xfs_dinode_has_large_extent_counts(dip),
399 whichfork);
099e5eb3 400 if (di_nextents > max_extents)
8ac50baf 401 return __this_address;
8ac50baf
DC
402 break;
403 default:
404 return __this_address;
405 }
406 return NULL;
407}
408
91b32a08
ES
409static xfs_failaddr_t
410xfs_dinode_verify_forkoff(
411 struct xfs_dinode *dip,
412 struct xfs_mount *mp)
413{
8c6cccd7 414 if (!dip->di_forkoff)
91b32a08
ES
415 return NULL;
416
417 switch (dip->di_format) {
418 case XFS_DINODE_FMT_DEV:
419 if (dip->di_forkoff != (roundup(sizeof(xfs_dev_t), 8) >> 3))
420 return __this_address;
421 break;
422 case XFS_DINODE_FMT_LOCAL: /* fall through ... */
423 case XFS_DINODE_FMT_EXTENTS: /* fall through ... */
424 case XFS_DINODE_FMT_BTREE:
4de63245 425 if (dip->di_forkoff >= (XFS_LITINO(mp) >> 3))
91b32a08
ES
426 return __this_address;
427 break;
428 default:
429 return __this_address;
430 }
431 return NULL;
432}
433
8be26c6a
CB
434static xfs_failaddr_t
435xfs_dinode_verify_nrext64(
436 struct xfs_mount *mp,
437 struct xfs_dinode *dip)
438{
439 if (xfs_dinode_has_large_extent_counts(dip)) {
440 if (!xfs_has_large_extent_counts(mp))
441 return __this_address;
442 if (dip->di_nrext64_pad != 0)
443 return __this_address;
444 } else if (dip->di_version >= 3) {
445 if (dip->di_v3_pad != 0)
446 return __this_address;
447 }
448
449 return NULL;
450}
451
bc01119d 452xfs_failaddr_t
41ce5f36
DC
453xfs_dinode_verify(
454 struct xfs_mount *mp,
e515cca1 455 xfs_ino_t ino,
41ce5f36
DC
456 struct xfs_dinode *dip)
457{
316d5a9f 458 xfs_failaddr_t fa;
3cfabff6 459 uint16_t mode;
183537ed
DW
460 uint16_t flags;
461 uint64_t flags2;
ad42e5a1 462 uint64_t di_size;
5f70c91b
CB
463 xfs_extnum_t nextents;
464 xfs_extnum_t naextents;
465 xfs_filblks_t nblocks;
183537ed 466
41ce5f36 467 if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))
bc01119d 468 return __this_address;
41ce5f36 469
98703400
DW
470 /* Verify v3 integrity information first */
471 if (dip->di_version >= 3) {
94541a16 472 if (!xfs_has_v3inodes(mp))
98703400
DW
473 return __this_address;
474 if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize,
475 XFS_DINODE_CRC_OFF))
476 return __this_address;
477 if (be64_to_cpu(dip->di_ino) != ino)
478 return __this_address;
479 if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_meta_uuid))
480 return __this_address;
481 }
482
9d85eb44 483 /* don't allow invalid i_size */
ad42e5a1
DW
484 di_size = be64_to_cpu(dip->di_size);
485 if (di_size & (1ULL << 63))
bc01119d 486 return __this_address;
9d85eb44 487
3cfabff6 488 mode = be16_to_cpu(dip->di_mode);
0962b5b3 489 if (mode && xfs_mode_to_ftype(mode) == XFS_DIR3_FT_UNKNOWN)
bc01119d 490 return __this_address;
3cfabff6
AG
491
492 /* No zero-length symlinks/dirs. */
ad42e5a1 493 if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0)
bc01119d 494 return __this_address;
9d85eb44 495
8be26c6a
CB
496 fa = xfs_dinode_verify_nrext64(mp, dip);
497 if (fa)
498 return fa;
499
5f70c91b
CB
500 nextents = xfs_dfork_data_extents(dip);
501 naextents = xfs_dfork_attr_extents(dip);
502 nblocks = be64_to_cpu(dip->di_nblocks);
503
ad42e5a1 504 /* Fork checks carried over from xfs_iformat_fork */
5f70c91b 505 if (mode && nextents + naextents > nblocks)
ad42e5a1
DW
506 return __this_address;
507
f0683d63
CB
508 if (S_ISDIR(mode) && nextents > mp->m_dir_geo->max_extents)
509 return __this_address;
510
ad42e5a1
DW
511 if (mode && XFS_DFORK_BOFF(dip) > mp->m_sb.sb_inodesize)
512 return __this_address;
513
514 flags = be16_to_cpu(dip->di_flags);
515
516 if (mode && (flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)
517 return __this_address;
518
91b32a08
ES
519 /* check for illegal values of forkoff */
520 fa = xfs_dinode_verify_forkoff(dip, mp);
521 if (fa)
522 return fa;
523
ad42e5a1
DW
524 /* Do we have appropriate data fork formats for the mode? */
525 switch (mode & S_IFMT) {
526 case S_IFIFO:
527 case S_IFCHR:
528 case S_IFBLK:
529 case S_IFSOCK:
530 if (dip->di_format != XFS_DINODE_FMT_DEV)
531 return __this_address;
532 break;
533 case S_IFREG:
534 case S_IFLNK:
535 case S_IFDIR:
8ac50baf
DC
536 fa = xfs_dinode_verify_fork(dip, mp, XFS_DATA_FORK);
537 if (fa)
538 return fa;
ad42e5a1
DW
539 break;
540 case 0:
541 /* Uninitialized inode ok. */
542 break;
543 default:
544 return __this_address;
545 }
546
8c6cccd7 547 if (dip->di_forkoff) {
8ac50baf
DC
548 fa = xfs_dinode_verify_fork(dip, mp, XFS_ATTR_FORK);
549 if (fa)
550 return fa;
3060f26a
ES
551 } else {
552 /*
553 * If there is no fork offset, this may be a freshly-made inode
554 * in a new disk cluster, in which case di_aformat is zeroed.
555 * Otherwise, such an inode must be in EXTENTS format; this goes
556 * for freed inodes as well.
557 */
558 switch (dip->di_aformat) {
559 case 0:
560 case XFS_DINODE_FMT_EXTENTS:
561 break;
562 default:
563 return __this_address;
564 }
5f70c91b 565 if (naextents)
3060f26a 566 return __this_address;
ad42e5a1
DW
567 }
568
316d5a9f
DC
569 /* extent size hint validation */
570 fa = xfs_inode_validate_extsize(mp, be32_to_cpu(dip->di_extsize),
571 mode, flags);
572 if (fa)
573 return fa;
574
41ce5f36
DC
575 /* only version 3 or greater inodes are extensively verified here */
576 if (dip->di_version < 3)
bc01119d 577 return NULL;
41ce5f36 578
183537ed
DW
579 flags2 = be64_to_cpu(dip->di_flags2);
580
581 /* don't allow reflink/cowextsize if we don't have reflink */
582 if ((flags2 & (XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE)) &&
b16a427a 583 !xfs_has_reflink(mp))
bc01119d 584 return __this_address;
183537ed 585
ad42e5a1
DW
586 /* only regular files get reflink */
587 if ((flags2 & XFS_DIFLAG2_REFLINK) && (mode & S_IFMT) != S_IFREG)
588 return __this_address;
589
183537ed
DW
590 /* don't let reflink and realtime mix */
591 if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags & XFS_DIFLAG_REALTIME))
bc01119d 592 return __this_address;
183537ed 593
77e17d58
DC
594 /* COW extent size hint validation */
595 fa = xfs_inode_validate_cowextsize(mp, be32_to_cpu(dip->di_cowextsize),
596 mode, flags, flags2);
597 if (fa)
598 return fa;
599
e7e3beb9
DW
600 /* bigtime iflag can only happen on bigtime filesystems */
601 if (xfs_dinode_has_bigtime(dip) &&
94541a16 602 !xfs_has_bigtime(mp))
e7e3beb9
DW
603 return __this_address;
604
bc01119d 605 return NULL;
41ce5f36 606}
e6d77a21 607
41ce5f36
DC
608void
609xfs_dinode_calc_crc(
610 struct xfs_mount *mp,
611 struct xfs_dinode *dip)
612{
4a492e72 613 uint32_t crc;
41ce5f36
DC
614
615 if (dip->di_version < 3)
616 return;
617
b16a427a 618 ASSERT(xfs_has_crc(mp));
0bb90214 619 crc = xfs_start_cksum_update((char *)dip, mp->m_sb.sb_inodesize,
3faddc54 620 XFS_DINODE_CRC_OFF);
41ce5f36 621 dip->di_crc = xfs_end_cksum(crc);
2bd0ea18
NS
622}
623
fd0c360d
DW
624/*
625 * Validate di_extsize hint.
626 *
ef39c7c7
DW
627 * 1. Extent size hint is only valid for directories and regular files.
628 * 2. FS_XFLAG_EXTSIZE is only valid for regular files.
629 * 3. FS_XFLAG_EXTSZINHERIT is only valid for directories.
630 * 4. Hint cannot be larger than MAXTEXTLEN.
631 * 5. Can be changed on directories at any time.
632 * 6. Hint value of 0 turns off hints, clears inode flags.
633 * 7. Extent size must be a multiple of the appropriate block size.
634 * For realtime files, this is the rt extent size.
635 * 8. For non-realtime files, the extent size hint must be limited
636 * to half the AG size to avoid alignment extending the extent beyond the
637 * limits of the AG.
fd0c360d
DW
638 */
639xfs_failaddr_t
640xfs_inode_validate_extsize(
641 struct xfs_mount *mp,
642 uint32_t extsize,
643 uint16_t mode,
644 uint16_t flags)
645{
646 bool rt_flag;
647 bool hint_flag;
648 bool inherit_flag;
649 uint32_t extsize_bytes;
650 uint32_t blocksize_bytes;
651
652 rt_flag = (flags & XFS_DIFLAG_REALTIME);
653 hint_flag = (flags & XFS_DIFLAG_EXTSIZE);
654 inherit_flag = (flags & XFS_DIFLAG_EXTSZINHERIT);
655 extsize_bytes = XFS_FSB_TO_B(mp, extsize);
656
c16edcd7
DW
657 /*
658 * This comment describes a historic gap in this verifier function.
659 *
d7de0c3e
DW
660 * For a directory with both RTINHERIT and EXTSZINHERIT flags set, this
661 * function has never checked that the extent size hint is an integer
662 * multiple of the realtime extent size. Since we allow users to set
663 * this combination on non-rt filesystems /and/ to change the rt
664 * extent size when adding a rt device to a filesystem, the net effect
665 * is that users can configure a filesystem anticipating one rt
666 * geometry and change their minds later. Directories do not use the
667 * extent size hint, so this is harmless for them.
c16edcd7
DW
668 *
669 * If a directory with a misaligned extent size hint is allowed to
670 * propagate that hint into a new regular realtime file, the result
671 * is that the inode cluster buffer verifier will trigger a corruption
d7de0c3e
DW
672 * shutdown the next time it is run, because the verifier has always
673 * enforced the alignment rule for regular files.
c16edcd7 674 *
d7de0c3e
DW
675 * Because we allow administrators to set a new rt extent size when
676 * adding a rt section, we cannot add a check to this verifier because
677 * that will result a new source of directory corruption errors when
678 * reading an existing filesystem. Instead, we rely on callers to
679 * decide when alignment checks are appropriate, and fix things up as
680 * needed.
c16edcd7
DW
681 */
682
fd0c360d 683 if (rt_flag)
6d211aaa 684 blocksize_bytes = XFS_FSB_TO_B(mp, mp->m_sb.sb_rextsize);
fd0c360d
DW
685 else
686 blocksize_bytes = mp->m_sb.sb_blocksize;
687
688 if ((hint_flag || inherit_flag) && !(S_ISDIR(mode) || S_ISREG(mode)))
689 return __this_address;
690
691 if (hint_flag && !S_ISREG(mode))
692 return __this_address;
693
694 if (inherit_flag && !S_ISDIR(mode))
695 return __this_address;
696
697 if ((hint_flag || inherit_flag) && extsize == 0)
698 return __this_address;
699
206bef93
ES
700 /* free inodes get flags set to zero but extsize remains */
701 if (mode && !(hint_flag || inherit_flag) && extsize != 0)
fd0c360d
DW
702 return __this_address;
703
704 if (extsize_bytes % blocksize_bytes)
705 return __this_address;
706
d3e0c71f 707 if (extsize > XFS_MAX_BMBT_EXTLEN)
fd0c360d
DW
708 return __this_address;
709
710 if (!rt_flag && extsize > mp->m_sb.sb_agblocks / 2)
711 return __this_address;
712
713 return NULL;
714}
715
716/*
717 * Validate di_cowextsize hint.
718 *
ef39c7c7
DW
719 * 1. CoW extent size hint can only be set if reflink is enabled on the fs.
720 * The inode does not have to have any shared blocks, but it must be a v3.
721 * 2. FS_XFLAG_COWEXTSIZE is only valid for directories and regular files;
722 * for a directory, the hint is propagated to new files.
723 * 3. Can be changed on files & directories at any time.
724 * 4. Hint value of 0 turns off hints, clears inode flags.
725 * 5. Extent size must be a multiple of the appropriate block size.
726 * 6. The extent size hint must be limited to half the AG size to avoid
727 * alignment extending the extent beyond the limits of the AG.
fd0c360d
DW
728 */
729xfs_failaddr_t
730xfs_inode_validate_cowextsize(
731 struct xfs_mount *mp,
732 uint32_t cowextsize,
733 uint16_t mode,
734 uint16_t flags,
735 uint64_t flags2)
736{
737 bool rt_flag;
738 bool hint_flag;
739 uint32_t cowextsize_bytes;
740
741 rt_flag = (flags & XFS_DIFLAG_REALTIME);
742 hint_flag = (flags2 & XFS_DIFLAG2_COWEXTSIZE);
743 cowextsize_bytes = XFS_FSB_TO_B(mp, cowextsize);
744
b16a427a 745 if (hint_flag && !xfs_has_reflink(mp))
fd0c360d
DW
746 return __this_address;
747
748 if (hint_flag && !(S_ISDIR(mode) || S_ISREG(mode)))
749 return __this_address;
750
751 if (hint_flag && cowextsize == 0)
752 return __this_address;
753
206bef93
ES
754 /* free inodes get flags set to zero but cowextsize remains */
755 if (mode && !hint_flag && cowextsize != 0)
fd0c360d
DW
756 return __this_address;
757
758 if (hint_flag && rt_flag)
759 return __this_address;
760
761 if (cowextsize_bytes % mp->m_sb.sb_blocksize)
762 return __this_address;
763
d3e0c71f 764 if (cowextsize > XFS_MAX_BMBT_EXTLEN)
fd0c360d
DW
765 return __this_address;
766
767 if (cowextsize > mp->m_sb.sb_agblocks / 2)
768 return __this_address;
769
770 return NULL;
771}