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

Generated by: LCOV version 1.14