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-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 314 384 81.8 %
Date: 2023-07-31 20:08:34 Functions: 18 18 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    70739166 : xfs_inode_buf_verify(
      42             :         struct xfs_buf  *bp,
      43             :         bool            readahead)
      44             : {
      45    70739166 :         struct xfs_mount *mp = bp->b_mount;
      46    70739166 :         int             i;
      47    70739166 :         int             ni;
      48             : 
      49             :         /*
      50             :          * Validate the magic number and version of every inode in the buffer
      51             :          */
      52    70739166 :         ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock;
      53  2334235949 :         for (i = 0; i < ni; i++) {
      54  2263501944 :                 struct xfs_dinode       *dip;
      55  2263501944 :                 xfs_agino_t             unlinked_ino;
      56  2263501944 :                 int                     di_ok;
      57             : 
      58  2263501944 :                 dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog));
      59  2263501977 :                 unlinked_ino = be32_to_cpu(dip->di_next_unlinked);
      60  4527000300 :                 di_ok = xfs_verify_magic16(bp, dip->di_magic) &&
      61  2263501944 :                         xfs_dinode_good_version(mp, dip->di_version) &&
      62  2263498158 :                         xfs_verify_agino_or_null(bp->b_pag, unlinked_ino);
      63  2263501944 :                 if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
      64             :                                                 XFS_ERRTAG_ITOBP_INOTOBP))) {
      65        5161 :                         if (readahead) {
      66        3177 :                                 bp->b_flags &= ~XBF_DONE;
      67        3177 :                                 xfs_buf_ioerror(bp, -EIO);
      68        3177 :                                 return;
      69             :                         }
      70             : 
      71             : #ifdef DEBUG
      72        1984 :                         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        1984 :                         xfs_buf_verifier_error(bp, -EFSCORRUPTED,
      78             :                                         __func__, dip, sizeof(*dip),
      79             :                                         NULL);
      80        1984 :                         return;
      81             :                 }
      82             :         }
      83             : }
      84             : 
      85             : 
      86             : static void
      87    11330981 : xfs_inode_buf_read_verify(
      88             :         struct xfs_buf  *bp)
      89             : {
      90    11330981 :         xfs_inode_buf_verify(bp, false);
      91    11330981 : }
      92             : 
      93             : static void
      94      279217 : xfs_inode_buf_readahead_verify(
      95             :         struct xfs_buf  *bp)
      96             : {
      97      279217 :         xfs_inode_buf_verify(bp, true);
      98      279217 : }
      99             : 
     100             : static void
     101    59128970 : xfs_inode_buf_write_verify(
     102             :         struct xfs_buf  *bp)
     103             : {
     104    59128970 :         xfs_inode_buf_verify(bp, false);
     105    59128970 : }
     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   912950802 : 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   912950802 :         int                     error;
     137             : 
     138   912950802 :         error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno,
     139   912950802 :                         imap->im_len, XBF_UNMAPPED, bpp, &xfs_inode_buf_ops);
     140   913150823 :         if (xfs_metadata_is_sick(error))
     141        1930 :                 xfs_agno_mark_sick(mp, xfs_daddr_to_agno(mp, imap->im_blkno),
     142             :                                 XFS_SICK_AG_INODES);
     143   913150823 :         return error;
     144             : }
     145             : 
     146             : static inline struct timespec64 xfs_inode_decode_bigtime(uint64_t ts)
     147             : {
     148  2048309474 :         struct timespec64       tv;
     149  2048309474 :         uint32_t                n;
     150             : 
     151  2048309474 :         tv.tv_sec = xfs_bigtime_to_unix(div_u64_rem(ts, NSEC_PER_SEC, &n));
     152  2048309474 :         tv.tv_nsec = n;
     153             : 
     154  2048309474 :         return tv;
     155             : }
     156             : 
     157             : /* Convert an ondisk timestamp to an incore timestamp. */
     158             : struct timespec64
     159  2048895318 : xfs_inode_from_disk_ts(
     160             :         struct xfs_dinode               *dip,
     161             :         const xfs_timestamp_t           ts)
     162             : {
     163  2048895318 :         struct timespec64               tv;
     164  2048895318 :         struct xfs_legacy_timestamp     *lts;
     165             : 
     166  4097790636 :         if (xfs_dinode_has_bigtime(dip))
     167  2048309474 :                 return xfs_inode_decode_bigtime(be64_to_cpu(ts));
     168             : 
     169      585844 :         lts = (struct xfs_legacy_timestamp *)&ts;
     170      585844 :         tv.tv_sec = (int)be32_to_cpu(lts->t_sec);
     171      585844 :         tv.tv_nsec = (int)be32_to_cpu(lts->t_nsec);
     172             : 
     173      585844 :         return tv;
     174             : }
     175             : 
     176             : int
     177   376224831 : xfs_inode_from_disk(
     178             :         struct xfs_inode        *ip,
     179             :         struct xfs_dinode       *from)
     180             : {
     181   376224831 :         struct inode            *inode = VFS_I(ip);
     182   376224831 :         int                     error;
     183   376224831 :         xfs_failaddr_t          fa;
     184             : 
     185   376224831 :         ASSERT(ip->i_cowfp == NULL);
     186             : 
     187   376224831 :         fa = xfs_dinode_verify(ip->i_mount, ip->i_ino, from);
     188   376204776 :         if (fa) {
     189        1082 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "dinode", from,
     190             :                                 sizeof(*from), fa);
     191        1082 :                 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   376203694 :         if (!xfs_has_v3inodes(ip->i_mount))
     200        2262 :                 ip->i_flushiter = be16_to_cpu(from->di_flushiter);
     201   376203694 :         inode->i_generation = be32_to_cpu(from->di_gen);
     202   376203694 :         inode->i_mode = be16_to_cpu(from->di_mode);
     203   376203694 :         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   376202270 :         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   376202270 :                 set_nlink(inode, be32_to_cpu(from->di_nlink));
     216   376184492 :                 ip->i_projid = (prid_t)be16_to_cpu(from->di_projid_hi) << 16 |
     217   376184492 :                                         be16_to_cpu(from->di_projid_lo);
     218             :         }
     219             : 
     220   376184492 :         i_uid_write(inode, be32_to_cpu(from->di_uid));
     221   376199798 :         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   376225331 :         inode->i_atime = xfs_inode_from_disk_ts(from, from->di_atime);
     230   376225331 :         inode->i_mtime = xfs_inode_from_disk_ts(from, from->di_mtime);
     231   376225331 :         inode->i_ctime = xfs_inode_from_disk_ts(from, from->di_ctime);
     232             : 
     233   376225331 :         ip->i_disk_size = be64_to_cpu(from->di_size);
     234   376225331 :         ip->i_nblocks = be64_to_cpu(from->di_nblocks);
     235   376225331 :         ip->i_extsize = be32_to_cpu(from->di_extsize);
     236   376225331 :         ip->i_forkoff = from->di_forkoff;
     237   376225331 :         ip->i_diflags = be16_to_cpu(from->di_flags);
     238   376225331 :         ip->i_next_unlinked = be32_to_cpu(from->di_next_unlinked);
     239             : 
     240   376225331 :         if (from->di_dmevmask || from->di_dmstate)
     241           5 :                 xfs_iflags_set(ip, XFS_IPRESERVE_DM_FIELDS);
     242             : 
     243   376228026 :         if (xfs_has_v3inodes(ip->i_mount)) {
     244   376227188 :                 inode_set_iversion_queried(inode,
     245   376227188 :                                            be64_to_cpu(from->di_changecount));
     246   376227188 :                 ip->i_crtime = xfs_inode_from_disk_ts(from, from->di_crtime);
     247   376227188 :                 ip->i_diflags2 = be64_to_cpu(from->di_flags2);
     248   376227188 :                 ip->i_cowextsize = be32_to_cpu(from->di_cowextsize);
     249             :         }
     250             : 
     251   376228026 :         error = xfs_iformat_data_fork(ip, from);
     252   376230365 :         if (error)
     253             :                 return error;
     254   376230343 :         if (from->di_forkoff) {
     255   373449767 :                 error = xfs_iformat_attr_fork(ip, from);
     256   373434987 :                 if (error)
     257           0 :                         goto out_destroy_data_fork;
     258             :         }
     259   376215563 :         if (xfs_is_reflink_inode(ip))
     260    90879702 :                 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  1997575862 : xfs_inode_to_disk_ts(
     271             :         struct xfs_inode                *ip,
     272             :         const struct timespec64         tv)
     273             : {
     274  1997575862 :         struct xfs_legacy_timestamp     *lts;
     275  1997575862 :         xfs_timestamp_t                 ts;
     276             : 
     277  1997575862 :         if (xfs_inode_has_bigtime(ip))
     278  1997024251 :                 return cpu_to_be64(xfs_inode_encode_bigtime(tv));
     279             : 
     280      551611 :         lts = (struct xfs_legacy_timestamp *)&ts;
     281      551611 :         lts->t_sec = cpu_to_be32(tv.tv_sec);
     282      551611 :         lts->t_nsec = cpu_to_be32(tv.tv_nsec);
     283             : 
     284      551611 :         return ts;
     285             : }
     286             : 
     287             : static inline void
     288   499671055 : xfs_inode_to_disk_iext_counters(
     289             :         struct xfs_inode        *ip,
     290             :         struct xfs_dinode       *to)
     291             : {
     292   499671055 :         if (xfs_inode_has_large_extent_counts(ip)) {
     293   499669373 :                 to->di_big_nextents = cpu_to_be64(xfs_ifork_nextents(&ip->i_df));
     294   499669373 :                 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   499669373 :                 to->di_nrext64_pad = cpu_to_be16(0);
     300             :         } else {
     301        1682 :                 to->di_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
     302        3364 :                 to->di_anextents = cpu_to_be16(xfs_ifork_nextents(&ip->i_af));
     303             :         }
     304   499671055 : }
     305             : 
     306             : void
     307   500055463 : xfs_inode_to_disk(
     308             :         struct xfs_inode        *ip,
     309             :         struct xfs_dinode       *to,
     310             :         xfs_lsn_t               lsn)
     311             : {
     312   500055463 :         struct inode            *inode = VFS_I(ip);
     313             : 
     314   500055463 :         to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
     315   500055463 :         to->di_onlink = 0;
     316             : 
     317   500055463 :         to->di_format = xfs_ifork_format(&ip->i_df);
     318   500055463 :         to->di_uid = cpu_to_be32(i_uid_read(inode));
     319   499628405 :         to->di_gid = cpu_to_be32(i_gid_read(inode));
     320   500085483 :         to->di_projid_lo = cpu_to_be16(ip->i_projid & 0xffff);
     321   500085483 :         to->di_projid_hi = cpu_to_be16(ip->i_projid >> 16);
     322             : 
     323   500085483 :         to->di_atime = xfs_inode_to_disk_ts(ip, inode->i_atime);
     324   500085483 :         to->di_mtime = xfs_inode_to_disk_ts(ip, inode->i_mtime);
     325   500085483 :         to->di_ctime = xfs_inode_to_disk_ts(ip, inode->i_ctime);
     326   500085483 :         to->di_nlink = cpu_to_be32(inode->i_nlink);
     327   500085483 :         to->di_gen = cpu_to_be32(inode->i_generation);
     328   500085483 :         to->di_mode = cpu_to_be16(inode->i_mode);
     329             : 
     330   500085483 :         to->di_size = cpu_to_be64(ip->i_disk_size);
     331   500085483 :         to->di_nblocks = cpu_to_be64(ip->i_nblocks);
     332   500085483 :         to->di_extsize = cpu_to_be32(ip->i_extsize);
     333   500085483 :         to->di_forkoff = ip->i_forkoff;
     334   500085483 :         to->di_aformat = xfs_ifork_format(&ip->i_af);
     335   500085483 :         to->di_flags = cpu_to_be16(ip->i_diflags);
     336             : 
     337   500085483 :         if (xfs_has_v3inodes(ip->i_mount)) {
     338   500084070 :                 to->di_version = 3;
     339   500084070 :                 to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
     340   500084070 :                 to->di_crtime = xfs_inode_to_disk_ts(ip, ip->i_crtime);
     341   500084070 :                 to->di_flags2 = cpu_to_be64(ip->i_diflags2);
     342   500084070 :                 to->di_cowextsize = cpu_to_be32(ip->i_cowextsize);
     343   500084070 :                 to->di_ino = cpu_to_be64(ip->i_ino);
     344   500084070 :                 to->di_lsn = cpu_to_be64(lsn);
     345   500084070 :                 memset(to->di_pad2, 0, sizeof(to->di_pad2));
     346   500084070 :                 uuid_copy(&to->di_uuid, &ip->i_mount->m_sb.sb_meta_uuid);
     347   499514156 :                 to->di_v3_pad = 0;
     348             :         } else {
     349        1413 :                 to->di_version = 2;
     350        1413 :                 to->di_flushiter = cpu_to_be16(ip->i_flushiter);
     351        2826 :                 memset(to->di_v2_pad, 0, sizeof(to->di_v2_pad));
     352             :         }
     353             : 
     354   499515569 :         xfs_inode_to_disk_iext_counters(ip, to);
     355   499632393 : }
     356             : 
     357             : static xfs_failaddr_t
     358   624636538 : xfs_dinode_verify_fork(
     359             :         struct xfs_dinode       *dip,
     360             :         struct xfs_mount        *mp,
     361             :         int                     whichfork)
     362             : {
     363   624636538 :         xfs_extnum_t            di_nextents;
     364   624636538 :         xfs_extnum_t            max_extents;
     365   624636538 :         mode_t                  mode = be16_to_cpu(dip->di_mode);
     366   624637387 :         uint32_t                fork_size = XFS_DFORK_SIZE(dip, mp, whichfork);
     367   624636538 :         uint32_t                fork_format = XFS_DFORK_FORMAT(dip, whichfork);
     368             : 
     369   624636538 :         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   624633763 :         if (whichfork == XFS_DATA_FORK) {
     379   251215718 :                 if (S_ISDIR(mode) || S_ISLNK(mode)) {
     380    80257718 :                         if (be64_to_cpu(dip->di_size) <= fork_size &&
     381             :                             fork_format != XFS_DINODE_FMT_LOCAL)
     382          33 :                                 return __this_address;
     383             :                 }
     384             : 
     385   251215685 :                 if (be64_to_cpu(dip->di_size) > fork_size &&
     386             :                     fork_format == XFS_DINODE_FMT_LOCAL)
     387           0 :                         return __this_address;
     388             :         }
     389             : 
     390   624633730 :         switch (fork_format) {
     391   433789337 :         case XFS_DINODE_FMT_LOCAL:
     392             :                 /*
     393             :                  * No local regular files yet.
     394             :                  */
     395   433789337 :                 if (S_ISREG(mode) && whichfork == XFS_DATA_FORK)
     396          22 :                         return __this_address;
     397   433789315 :                 if (di_nextents)
     398           0 :                         return __this_address;
     399             :                 break;
     400   177659922 :         case XFS_DINODE_FMT_EXTENTS:
     401   177660513 :                 if (di_nextents > XFS_DFORK_MAXEXT(dip, mp, whichfork))
     402           0 :                         return __this_address;
     403             :                 break;
     404             :         case XFS_DINODE_FMT_BTREE:
     405    25979430 :                 max_extents = xfs_iext_max_nextents(
     406             :                                         xfs_dinode_has_large_extent_counts(dip),
     407             :                                         whichfork);
     408    12989712 :                 if (di_nextents > max_extents)
     409           0 :                         return __this_address;
     410             :                 break;
     411       97411 :         case XFS_DINODE_FMT_RMAP:
     412       97411 :                 if (!xfs_has_rtrmapbt(mp))
     413           0 :                         return __this_address;
     414       97411 :                 if (!(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADIR)))
     415           0 :                         return __this_address;
     416             :                 break;
     417       97301 :         case XFS_DINODE_FMT_REFCOUNT:
     418       97301 :                 if (!xfs_has_rtreflink(mp))
     419           0 :                         return __this_address;
     420       97301 :                 if (!(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADIR)))
     421           0 :                         return __this_address;
     422             :                 break;
     423             :         default:
     424          44 :                 return __this_address;
     425             :         }
     426             :         return NULL;
     427             : }
     428             : 
     429             : static xfs_failaddr_t
     430   376212253 : xfs_dinode_verify_forkoff(
     431             :         struct xfs_dinode       *dip,
     432             :         struct xfs_mount        *mp)
     433             : {
     434   376212253 :         if (!dip->di_forkoff)
     435             :                 return NULL;
     436             : 
     437   373429718 :         switch (dip->di_format)  {
     438   124923483 :         case XFS_DINODE_FMT_DEV:
     439   124923483 :                 if (dip->di_forkoff != (roundup(sizeof(xfs_dev_t), 8) >> 3))
     440           0 :                         return __this_address;
     441             :                 break;
     442             :         case XFS_DINODE_FMT_RMAP:
     443             :         case XFS_DINODE_FMT_REFCOUNT:
     444      193202 :                 if (!(xfs_has_metadir(mp) && xfs_has_parent(mp)))
     445           0 :                         return __this_address;
     446   248506235 :                 fallthrough;
     447             :         case XFS_DINODE_FMT_LOCAL:      /* fall through ... */
     448             :         case XFS_DINODE_FMT_EXTENTS:    /* fall through ... */
     449             :         case XFS_DINODE_FMT_BTREE:
     450   248506246 :                 if (dip->di_forkoff >= (XFS_LITINO(mp) >> 3))
     451           0 :                         return __this_address;
     452             :                 break;
     453             :         default:
     454           0 :                 return __this_address;
     455             :         }
     456             :         return NULL;
     457             : }
     458             : 
     459             : static xfs_failaddr_t
     460   376211799 : xfs_dinode_verify_nrext64(
     461             :         struct xfs_mount        *mp,
     462             :         struct xfs_dinode       *dip)
     463             : {
     464   752423598 :         if (xfs_dinode_has_large_extent_counts(dip)) {
     465   376209478 :                 if (!xfs_has_large_extent_counts(mp))
     466           0 :                         return __this_address;
     467   376209478 :                 if (dip->di_nrext64_pad != 0)
     468           0 :                         return __this_address;
     469        2321 :         } else if (dip->di_version >= 3) {
     470          48 :                 if (dip->di_v3_pad != 0)
     471           0 :                         return __this_address;
     472             :         }
     473             : 
     474             :         return NULL;
     475             : }
     476             : 
     477             : /*
     478             :  * Validate all the picky requirements we have for a file that claims to be
     479             :  * filesystem metadata.
     480             :  */
     481             : xfs_failaddr_t
     482      606702 : xfs_dinode_verify_metadir(
     483             :         struct xfs_mount        *mp,
     484             :         struct xfs_dinode       *dip,
     485             :         uint16_t                mode,
     486             :         uint16_t                flags,
     487             :         uint64_t                flags2)
     488             : {
     489      606702 :         if (!xfs_has_metadir(mp))
     490           0 :                 return __this_address;
     491             : 
     492             :         /* V5 filesystem only */
     493      606702 :         if (dip->di_version < 3)
     494           0 :                 return __this_address;
     495             : 
     496             :         /* V3 inode fields that are always zero */
     497      606702 :         if (dip->di_onlink)
     498           0 :                 return __this_address;
     499      606702 :         if ((flags2 & XFS_DIFLAG2_NREXT64) && dip->di_nrext64_pad)
     500           0 :                 return __this_address;
     501      606702 :         if (!(flags2 & XFS_DIFLAG2_NREXT64) && dip->di_flushiter)
     502           0 :                 return __this_address;
     503             : 
     504             :         /* Metadata files can only be directories or regular files */
     505      606702 :         if (!S_ISDIR(mode) && !S_ISREG(mode))
     506           0 :                 return __this_address;
     507             : 
     508             :         /* They must have zero access permissions */
     509      606702 :         if (mode & 0777)
     510           0 :                 return __this_address;
     511             : 
     512             :         /* DMAPI event and state masks are zero */
     513      606702 :         if (dip->di_dmevmask || dip->di_dmstate)
     514           0 :                 return __this_address;
     515             : 
     516             :         /* User, group, and project IDs must be zero */
     517      606702 :         if (dip->di_uid || dip->di_gid ||
     518      606702 :             dip->di_projid_lo || dip->di_projid_hi)
     519           0 :                 return __this_address;
     520             : 
     521             :         /* Immutable, sync, noatime, nodump, and nodefrag flags must be set */
     522      606702 :         if (!(flags & XFS_DIFLAG_IMMUTABLE))
     523           0 :                 return __this_address;
     524      606702 :         if (!(flags & XFS_DIFLAG_SYNC))
     525           0 :                 return __this_address;
     526      606702 :         if (!(flags & XFS_DIFLAG_NOATIME))
     527           0 :                 return __this_address;
     528      606702 :         if (!(flags & XFS_DIFLAG_NODUMP))
     529           0 :                 return __this_address;
     530      606702 :         if (!(flags & XFS_DIFLAG_NODEFRAG))
     531           0 :                 return __this_address;
     532             : 
     533             :         /* Directories must have nosymlinks flags set */
     534      606702 :         if (S_ISDIR(mode) && !(flags & XFS_DIFLAG_NOSYMLINKS))
     535           0 :                 return __this_address;
     536             : 
     537             :         /* dax flags2 must not be set */
     538      606702 :         if (flags2 & XFS_DIFLAG2_DAX)
     539           0 :                 return __this_address;
     540             : 
     541             :         return NULL;
     542             : }
     543             : 
     544             : xfs_failaddr_t
     545   376243075 : xfs_dinode_verify(
     546             :         struct xfs_mount        *mp,
     547             :         xfs_ino_t               ino,
     548             :         struct xfs_dinode       *dip)
     549             : {
     550   376243075 :         xfs_failaddr_t          fa;
     551   376243075 :         uint16_t                mode;
     552   376243075 :         uint16_t                flags;
     553   376243075 :         uint64_t                flags2;
     554   376243075 :         uint64_t                di_size;
     555   376243075 :         xfs_extnum_t            nextents;
     556   376243075 :         xfs_extnum_t            naextents;
     557   376243075 :         xfs_filblks_t           nblocks;
     558             : 
     559   376243075 :         if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))
     560           0 :                 return __this_address;
     561             : 
     562             :         /* Verify v3 integrity information first */
     563   376243075 :         if (dip->di_version >= 3) {
     564   376232664 :                 if (!xfs_has_v3inodes(mp))
     565           0 :                         return __this_address;
     566   376232664 :                 if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize,
     567             :                                       XFS_DINODE_CRC_OFF))
     568          26 :                         return __this_address;
     569   376229054 :                 if (be64_to_cpu(dip->di_ino) != ino)
     570           0 :                         return __this_address;
     571   376229054 :                 if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_meta_uuid))
     572           0 :                         return __this_address;
     573             :         }
     574             : 
     575   376218907 :         if (dip->di_version > 1) {
     576   376218907 :                 if (dip->di_onlink)
     577           0 :                         return __this_address;
     578             :         } else {
     579           0 :                 if (dip->di_nlink)
     580           0 :                         return __this_address;
     581             :         }
     582             : 
     583             :         /* don't allow invalid i_size */
     584   376218907 :         di_size = be64_to_cpu(dip->di_size);
     585   376218907 :         if (di_size & (1ULL << 63))
     586           0 :                 return __this_address;
     587             : 
     588   376218907 :         mode = be16_to_cpu(dip->di_mode);
     589   376218907 :         if (mode && xfs_mode_to_ftype(mode) == XFS_DIR3_FT_UNKNOWN)
     590         693 :                 return __this_address;
     591             : 
     592             :         /* No zero-length symlinks/dirs. */
     593   376215462 :         if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0)
     594          88 :                 return __this_address;
     595             : 
     596   376215374 :         fa = xfs_dinode_verify_nrext64(mp, dip);
     597   376208817 :         if (fa)
     598             :                 return fa;
     599             : 
     600   376212456 :         nextents = xfs_dfork_data_extents(dip);
     601   376212456 :         naextents = xfs_dfork_attr_extents(dip);
     602   376212456 :         nblocks = be64_to_cpu(dip->di_nblocks);
     603             : 
     604             :         /* Fork checks carried over from xfs_iformat_fork */
     605   376212456 :         if (mode && nextents + naextents > nblocks)
     606           0 :                 return __this_address;
     607             : 
     608   376212456 :         if (S_ISDIR(mode) && nextents > mp->m_dir_geo->max_extents)
     609           0 :                 return __this_address;
     610             : 
     611   376212456 :         if (mode && XFS_DFORK_BOFF(dip) > mp->m_sb.sb_inodesize)
     612           0 :                 return __this_address;
     613             : 
     614   376212456 :         flags = be16_to_cpu(dip->di_flags);
     615             : 
     616   376212456 :         if (mode && (flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)
     617           0 :                 return __this_address;
     618             : 
     619             :         /* check for illegal values of forkoff */
     620   376212456 :         fa = xfs_dinode_verify_forkoff(dip, mp);
     621   376196239 :         if (fa)
     622             :                 return fa;
     623             : 
     624             :         /* Do we have appropriate data fork formats for the mode? */
     625   376213834 :         switch (mode & S_IFMT) {
     626   124993751 :         case S_IFIFO:
     627             :         case S_IFCHR:
     628             :         case S_IFBLK:
     629             :         case S_IFSOCK:
     630   124993751 :                 if (dip->di_format != XFS_DINODE_FMT_DEV)
     631         176 :                         return __this_address;
     632             :                 break;
     633   251219159 :         case S_IFREG:
     634             :         case S_IFLNK:
     635             :         case S_IFDIR:
     636   251219159 :                 fa = xfs_dinode_verify_fork(dip, mp, XFS_DATA_FORK);
     637   251212618 :                 if (fa)
     638             :                         return fa;
     639             :                 break;
     640             :         case 0:
     641             :                 /* Uninitialized inode ok. */
     642             :                 break;
     643             :         default:
     644           0 :                 return __this_address;
     645             :         }
     646             : 
     647   376207329 :         if (dip->di_forkoff) {
     648   373424939 :                 fa = xfs_dinode_verify_fork(dip, mp, XFS_ATTR_FORK);
     649   373424142 :                 if (fa)
     650             :                         return fa;
     651             :         } else {
     652             :                 /*
     653             :                  * If there is no fork offset, this may be a freshly-made inode
     654             :                  * in a new disk cluster, in which case di_aformat is zeroed.
     655             :                  * Otherwise, such an inode must be in EXTENTS format; this goes
     656             :                  * for freed inodes as well.
     657             :                  */
     658     2782390 :                 switch (dip->di_aformat) {
     659             :                 case 0:
     660             :                 case XFS_DINODE_FMT_EXTENTS:
     661     2782390 :                         break;
     662             :                 default:
     663           0 :                         return __this_address;
     664             :                 }
     665     2782390 :                 if (naextents)
     666           0 :                         return __this_address;
     667             :         }
     668             : 
     669             :         /* extent size hint validation */
     670   376206861 :         fa = xfs_inode_validate_extsize(mp, be32_to_cpu(dip->di_extsize),
     671             :                         mode, flags);
     672   376191487 :         if (fa)
     673             :                 return fa;
     674             : 
     675             :         /* only version 3 or greater inodes are extensively verified here */
     676   376192902 :         if (dip->di_version < 3)
     677             :                 return NULL;
     678             : 
     679   376190640 :         flags2 = be64_to_cpu(dip->di_flags2);
     680             : 
     681             :         /* don't allow reflink/cowextsize if we don't have reflink */
     682   376190640 :         if ((flags2 & (XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE)) &&
     683             :              !xfs_has_reflink(mp))
     684           0 :                 return __this_address;
     685             : 
     686             :         /* only regular files get reflink */
     687   376190640 :         if ((flags2 & XFS_DIFLAG2_REFLINK) && (mode & S_IFMT) != S_IFREG)
     688           0 :                 return __this_address;
     689             : 
     690             :         /* don't let reflink and realtime mix */
     691   376190640 :         if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags & XFS_DIFLAG_REALTIME) &&
     692       87381 :             !xfs_has_rtreflink(mp))
     693           0 :                 return __this_address;
     694             : 
     695             :         /* COW extent size hint validation */
     696   376190640 :         fa = xfs_inode_validate_cowextsize(mp, be32_to_cpu(dip->di_cowextsize),
     697             :                         mode, flags, flags2);
     698   376186452 :         if (fa)
     699             :                 return fa;
     700             : 
     701             :         /* bigtime iflag can only happen on bigtime filesystems */
     702   752372206 :         if (xfs_dinode_has_bigtime(dip) &&
     703             :             !xfs_has_bigtime(mp))
     704           0 :                 return __this_address;
     705             : 
     706   376186103 :         if (flags2 & XFS_DIFLAG2_METADIR) {
     707      606702 :                 fa = xfs_dinode_verify_metadir(mp, dip, mode, flags, flags2);
     708      606702 :                 if (fa)
     709           0 :                         return fa;
     710             :         }
     711             : 
     712             :         return NULL;
     713             : }
     714             : 
     715             : void
     716   503227287 : xfs_dinode_calc_crc(
     717             :         struct xfs_mount        *mp,
     718             :         struct xfs_dinode       *dip)
     719             : {
     720   503227287 :         uint32_t                crc;
     721             : 
     722   503227287 :         if (dip->di_version < 3)
     723             :                 return;
     724             : 
     725   503225962 :         ASSERT(xfs_has_crc(mp));
     726   503225962 :         crc = xfs_start_cksum_update((char *)dip, mp->m_sb.sb_inodesize,
     727             :                               XFS_DINODE_CRC_OFF);
     728   503164316 :         dip->di_crc = xfs_end_cksum(crc);
     729             : }
     730             : 
     731             : /*
     732             :  * Validate di_extsize hint.
     733             :  *
     734             :  * 1. Extent size hint is only valid for directories and regular files.
     735             :  * 2. FS_XFLAG_EXTSIZE is only valid for regular files.
     736             :  * 3. FS_XFLAG_EXTSZINHERIT is only valid for directories.
     737             :  * 4. Hint cannot be larger than MAXTEXTLEN.
     738             :  * 5. Can be changed on directories at any time.
     739             :  * 6. Hint value of 0 turns off hints, clears inode flags.
     740             :  * 7. Extent size must be a multiple of the appropriate block size.
     741             :  *    For realtime files, this is the rt extent size.
     742             :  * 8. For non-realtime files, the extent size hint must be limited
     743             :  *    to half the AG size to avoid alignment extending the extent beyond the
     744             :  *    limits of the AG.
     745             :  */
     746             : xfs_failaddr_t
     747   547804894 : xfs_inode_validate_extsize(
     748             :         struct xfs_mount                *mp,
     749             :         uint32_t                        extsize,
     750             :         uint16_t                        mode,
     751             :         uint16_t                        flags)
     752             : {
     753   547804894 :         bool                            rt_flag;
     754   547804894 :         bool                            hint_flag;
     755   547804894 :         bool                            inherit_flag;
     756   547804894 :         uint32_t                        alloc_unit = 1;
     757             : 
     758   547804894 :         rt_flag = (flags & XFS_DIFLAG_REALTIME);
     759   547804894 :         hint_flag = (flags & XFS_DIFLAG_EXTSIZE);
     760   547804894 :         inherit_flag = (flags & XFS_DIFLAG_EXTSZINHERIT);
     761             : 
     762             :         /*
     763             :          * This comment describes a historic gap in this verifier function.
     764             :          *
     765             :          * For a directory with both RTINHERIT and EXTSZINHERIT flags set, this
     766             :          * function has never checked that the extent size hint is an integer
     767             :          * multiple of the realtime extent size.  Since we allow users to set
     768             :          * this combination  on non-rt filesystems /and/ to change the rt
     769             :          * extent size when adding a rt device to a filesystem, the net effect
     770             :          * is that users can configure a filesystem anticipating one rt
     771             :          * geometry and change their minds later.  Directories do not use the
     772             :          * extent size hint, so this is harmless for them.
     773             :          *
     774             :          * If a directory with a misaligned extent size hint is allowed to
     775             :          * propagate that hint into a new regular realtime file, the result
     776             :          * is that the inode cluster buffer verifier will trigger a corruption
     777             :          * shutdown the next time it is run, because the verifier has always
     778             :          * enforced the alignment rule for regular files.
     779             :          *
     780             :          * Because we allow administrators to set a new rt extent size when
     781             :          * adding a rt section, we cannot add a check to this verifier because
     782             :          * that will result a new source of directory corruption errors when
     783             :          * reading an existing filesystem.  Instead, we rely on callers to
     784             :          * decide when alignment checks are appropriate, and fix things up as
     785             :          * needed.
     786             :          */
     787             : 
     788   547804894 :         if (rt_flag)
     789    73825484 :                 alloc_unit = mp->m_sb.sb_rextsize;
     790             : 
     791   547804894 :         if ((hint_flag || inherit_flag) && !(S_ISDIR(mode) || S_ISREG(mode)))
     792           0 :                 return __this_address;
     793             : 
     794   547804894 :         if (hint_flag && !S_ISREG(mode))
     795           0 :                 return __this_address;
     796             : 
     797   547804894 :         if (inherit_flag && !S_ISDIR(mode))
     798           0 :                 return __this_address;
     799             : 
     800   547804894 :         if ((hint_flag || inherit_flag) && extsize == 0)
     801           0 :                 return __this_address;
     802             : 
     803             :         /* free inodes get flags set to zero but extsize remains */
     804   547804894 :         if (mode && !(hint_flag || inherit_flag) && extsize != 0)
     805           0 :                 return __this_address;
     806             : 
     807   547804894 :         if (extsize % alloc_unit)
     808           2 :                 return __this_address;
     809             : 
     810   547804892 :         if (extsize > XFS_MAX_BMBT_EXTLEN)
     811           0 :                 return __this_address;
     812             : 
     813   547804892 :         if (!rt_flag && extsize > mp->m_sb.sb_agblocks / 2)
     814           0 :                 return __this_address;
     815             : 
     816             :         return NULL;
     817             : }
     818             : 
     819             : /*
     820             :  * Validate di_cowextsize hint.
     821             :  *
     822             :  * 1. CoW extent size hint can only be set if reflink is enabled on the fs.
     823             :  *    The inode does not have to have any shared blocks, but it must be a v3.
     824             :  * 2. FS_XFLAG_COWEXTSIZE is only valid for directories and regular files;
     825             :  *    for a directory, the hint is propagated to new files.
     826             :  * 3. Can be changed on files & directories at any time.
     827             :  * 4. Hint value of 0 turns off hints, clears inode flags.
     828             :  * 5. Extent size must be a multiple of the appropriate block size.
     829             :  * 6. The extent size hint must be limited to half the AG size to avoid
     830             :  *    alignment extending the extent beyond the limits of the AG.
     831             :  */
     832             : xfs_failaddr_t
     833   588957229 : xfs_inode_validate_cowextsize(
     834             :         struct xfs_mount                *mp,
     835             :         uint32_t                        cowextsize,
     836             :         uint16_t                        mode,
     837             :         uint16_t                        flags,
     838             :         uint64_t                        flags2)
     839             : {
     840   588957229 :         bool                            rt_flag;
     841   588957229 :         bool                            hint_flag;
     842   588957229 :         uint32_t                        alloc_unit = 1;
     843             : 
     844   588957229 :         rt_flag = (flags & XFS_DIFLAG_REALTIME);
     845   588957229 :         hint_flag = (flags2 & XFS_DIFLAG2_COWEXTSIZE);
     846             : 
     847             :         /*
     848             :          * Similar to extent size hints, a directory can be configured to
     849             :          * propagate realtime status and a CoW extent size hint to newly
     850             :          * created files even if there is no realtime device, and the hints on
     851             :          * disk can become misaligned if the sysadmin changes the rt extent
     852             :          * size while adding the realtime device.
     853             :          *
     854             :          * Therefore, we can only enforce the rextsize alignment check against
     855             :          * regular realtime files, and rely on callers to decide when alignment
     856             :          * checks are appropriate, and fix things up as needed.
     857             :          */
     858             : 
     859   588957229 :         if (rt_flag)
     860    73603483 :                 alloc_unit = mp->m_sb.sb_rextsize;
     861             : 
     862   588957229 :         if (hint_flag && !xfs_has_reflink(mp))
     863           0 :                 return __this_address;
     864             : 
     865   588957229 :         if (hint_flag && !(S_ISDIR(mode) || S_ISREG(mode)))
     866           0 :                 return __this_address;
     867             : 
     868   588957229 :         if (hint_flag && cowextsize == 0)
     869           0 :                 return __this_address;
     870             : 
     871             :         /* free inodes get flags set to zero but cowextsize remains */
     872   588957229 :         if (mode && !hint_flag && cowextsize != 0)
     873           0 :                 return __this_address;
     874             : 
     875   588957229 :         if (cowextsize % alloc_unit)
     876           0 :                 return __this_address;
     877             : 
     878   588957229 :         if (cowextsize > XFS_MAX_BMBT_EXTLEN)
     879           0 :                 return __this_address;
     880             : 
     881   588957229 :         if (!rt_flag && cowextsize > mp->m_sb.sb_agblocks / 2)
     882           0 :                 return __this_address;
     883             : 
     884             :         return NULL;
     885             : }

Generated by: LCOV version 1.14