LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_inode_buf.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 281 328 85.7 %
Date: 2023-07-31 20:08:17 Functions: 17 17 100.0 %

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

Generated by: LCOV version 1.14