LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_inode_fork.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 295 353 83.6 %
Date: 2023-07-31 20:08:34 Functions: 22 22 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             : 
       7             : #include "xfs.h"
       8             : #include "xfs_fs.h"
       9             : #include "xfs_shared.h"
      10             : #include "xfs_format.h"
      11             : #include "xfs_log_format.h"
      12             : #include "xfs_trans_resv.h"
      13             : #include "xfs_mount.h"
      14             : #include "xfs_inode.h"
      15             : #include "xfs_trans.h"
      16             : #include "xfs_inode_item.h"
      17             : #include "xfs_btree.h"
      18             : #include "xfs_bmap_btree.h"
      19             : #include "xfs_bmap.h"
      20             : #include "xfs_error.h"
      21             : #include "xfs_trace.h"
      22             : #include "xfs_da_format.h"
      23             : #include "xfs_da_btree.h"
      24             : #include "xfs_dir2_priv.h"
      25             : #include "xfs_attr_leaf.h"
      26             : #include "xfs_types.h"
      27             : #include "xfs_errortag.h"
      28             : #include "xfs_health.h"
      29             : #include "xfs_symlink_remote.h"
      30             : #include "xfs_rtrmap_btree.h"
      31             : #include "xfs_rtrefcount_btree.h"
      32             : 
      33             : struct kmem_cache *xfs_ifork_cache;
      34             : 
      35             : void
      36   445448575 : xfs_init_local_fork(
      37             :         struct xfs_inode        *ip,
      38             :         int                     whichfork,
      39             :         const void              *data,
      40             :         int64_t                 size)
      41             : {
      42   445448575 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
      43   445425094 :         int                     mem_size = size;
      44   445425094 :         bool                    zero_terminate;
      45             : 
      46             :         /*
      47             :          * If we are using the local fork to store a symlink body we need to
      48             :          * zero-terminate it so that we can pass it back to the VFS directly.
      49             :          * Overallocate the in-memory fork by one for that and add a zero
      50             :          * to terminate it below.
      51             :          */
      52   445425094 :         zero_terminate = S_ISLNK(VFS_I(ip)->i_mode);
      53   445425094 :         if (zero_terminate)
      54    30311911 :                 mem_size++;
      55             : 
      56   445425094 :         if (size) {
      57   445425094 :                 ifp->if_u1.if_data = kmem_alloc(mem_size, KM_NOFS);
      58   890917732 :                 memcpy(ifp->if_u1.if_data, data, size);
      59   445458866 :                 if (zero_terminate)
      60    30315876 :                         ifp->if_u1.if_data[size] = '\0';
      61             :         } else {
      62           0 :                 ifp->if_u1.if_data = NULL;
      63             :         }
      64             : 
      65   445458866 :         ifp->if_bytes = size;
      66   445458866 : }
      67             : 
      68             : /*
      69             :  * The file is in-lined in the on-disk inode.
      70             :  */
      71             : STATIC int
      72   433804115 : xfs_iformat_local(
      73             :         struct xfs_inode        *ip,
      74             :         struct xfs_dinode       *dip,
      75             :         int                     whichfork,
      76             :         int                     size)
      77             : {
      78             :         /*
      79             :          * If the size is unreasonable, then something
      80             :          * is wrong and we just bail out rather than crash in
      81             :          * kmem_alloc() or memcpy() below.
      82             :          */
      83   433804362 :         if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
      84           0 :                 xfs_warn(ip->i_mount,
      85             :         "corrupt inode %llu (bad size %d for local fork, size = %zd).",
      86             :                         (unsigned long long) ip->i_ino, size,
      87             :                         XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
      88           0 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
      89             :                                 "xfs_iformat_local", dip, sizeof(*dip),
      90           0 :                                 __this_address);
      91           0 :                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
      92           0 :                 return -EFSCORRUPTED;
      93             :         }
      94             : 
      95   867606654 :         xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
      96   433804115 :         return 0;
      97             : }
      98             : 
      99             : /*
     100             :  * The file consists of a set of extents all of which fit into the on-disk
     101             :  * inode.
     102             :  */
     103             : STATIC int
     104   177670491 : xfs_iformat_extents(
     105             :         struct xfs_inode        *ip,
     106             :         struct xfs_dinode       *dip,
     107             :         int                     whichfork)
     108             : {
     109   177670491 :         struct xfs_mount        *mp = ip->i_mount;
     110   177670491 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     111   177674275 :         int                     state = xfs_bmap_fork_to_state(whichfork);
     112   177674275 :         xfs_extnum_t            nex = xfs_dfork_nextents(dip, whichfork);
     113   177676776 :         int                     size = nex * sizeof(xfs_bmbt_rec_t);
     114   177676776 :         struct xfs_iext_cursor  icur;
     115   177676776 :         struct xfs_bmbt_rec     *dp;
     116   177676776 :         struct xfs_bmbt_irec    new;
     117   177676776 :         int                     i;
     118             : 
     119             :         /*
     120             :          * If the number of extents is unreasonable, then something is wrong and
     121             :          * we just bail out rather than crash in kmem_alloc() or memcpy() below.
     122             :          */
     123   177677367 :         if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, mp, whichfork))) {
     124           0 :                 xfs_warn(ip->i_mount, "corrupt inode %llu ((a)extents = %llu).",
     125             :                         ip->i_ino, nex);
     126           0 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
     127             :                                 "xfs_iformat_extents(1)", dip, sizeof(*dip),
     128           0 :                                 __this_address);
     129           0 :                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
     130           0 :                 return -EFSCORRUPTED;
     131             :         }
     132             : 
     133   177676776 :         ifp->if_bytes = 0;
     134   177676776 :         ifp->if_u1.if_root = NULL;
     135   177676776 :         ifp->if_height = 0;
     136   177676776 :         if (size) {
     137   220875942 :                 dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
     138             : 
     139   110438070 :                 xfs_iext_first(ifp, &icur);
     140   593547285 :                 for (i = 0; i < nex; i++, dp++) {
     141   372672329 :                         xfs_failaddr_t  fa;
     142             : 
     143   372672329 :                         xfs_bmbt_disk_get_all(dp, &new);
     144   372671278 :                         fa = xfs_bmap_validate_extent(ip, whichfork, &new);
     145   372670709 :                         if (fa) {
     146           0 :                                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
     147             :                                                 "xfs_iformat_extents(2)",
     148             :                                                 dp, sizeof(*dp), fa);
     149           0 :                                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
     150           0 :                                 return xfs_bmap_complain_bad_rec(ip, whichfork,
     151             :                                                 fa, &new);
     152             :                         }
     153             : 
     154   372670709 :                         xfs_iext_insert(ip, &icur, &new, state);
     155   372672634 :                         trace_xfs_read_extent(ip, &icur, state, _THIS_IP_);
     156   372672639 :                         xfs_iext_next(ifp, &icur);
     157             :                 }
     158             :         }
     159             :         return 0;
     160             : }
     161             : 
     162             : /*
     163             :  * The file has too many extents to fit into
     164             :  * the inode, so they are in B-tree format.
     165             :  * Allocate a buffer for the root of the B-tree
     166             :  * and copy the root into it.  The i_extents
     167             :  * field will remain NULL until all of the
     168             :  * extents are read in (when they are needed).
     169             :  */
     170             : STATIC int
     171    12989722 : xfs_iformat_btree(
     172             :         struct xfs_inode        *ip,
     173             :         struct xfs_dinode       *dip,
     174             :         int                     whichfork)
     175             : {
     176    12989722 :         struct xfs_mount        *mp = ip->i_mount;
     177    12989722 :         xfs_bmdr_block_t        *dfp;
     178    12989722 :         struct xfs_ifork        *ifp;
     179             :         /* REFERENCED */
     180    12989722 :         int                     nrecs;
     181    12989722 :         int                     size;
     182    12989722 :         int                     level;
     183             : 
     184    12989722 :         ifp = xfs_ifork_ptr(ip, whichfork);
     185    25979432 :         dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
     186    12989717 :         size = xfs_bmap_broot_space(mp, dfp);
     187    12989718 :         nrecs = be16_to_cpu(dfp->bb_numrecs);
     188    12989718 :         level = be16_to_cpu(dfp->bb_level);
     189             : 
     190             :         /*
     191             :          * blow out if -- fork has less extents than can fit in
     192             :          * fork (fork shouldn't be a btree format), root btree
     193             :          * block has more records than can fit into the fork,
     194             :          * or the number of extents is greater than the number of
     195             :          * blocks.
     196             :          */
     197    25979436 :         if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) ||
     198             :                      nrecs == 0 ||
     199             :                      xfs_bmdr_space_calc(nrecs) >
     200             :                                         XFS_DFORK_SIZE(dip, mp, whichfork) ||
     201    12989718 :                      ifp->if_nextents > ip->i_nblocks) ||
     202    12989718 :                      level == 0 || level > XFS_BM_MAXLEVELS(mp, whichfork)) {
     203           0 :                 xfs_warn(mp, "corrupt inode %llu (btree).",
     204             :                                         (unsigned long long) ip->i_ino);
     205           0 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
     206             :                                 "xfs_iformat_btree", dfp, size,
     207           0 :                                 __this_address);
     208           0 :                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
     209           0 :                 return -EFSCORRUPTED;
     210             :         }
     211             : 
     212    12989716 :         xfs_iroot_alloc(ip, whichfork, size);
     213    12989720 :         ASSERT(ifp->if_broot != NULL);
     214             :         /*
     215             :          * Copy and convert from the on-disk structure
     216             :          * to the in-memory structure.
     217             :          */
     218    12989720 :         xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
     219             :                          ifp->if_broot, size);
     220             : 
     221    12989715 :         ifp->if_bytes = 0;
     222    12989715 :         ifp->if_u1.if_root = NULL;
     223    12989715 :         ifp->if_height = 0;
     224    12989715 :         return 0;
     225             : }
     226             : 
     227             : int
     228   376231060 : xfs_iformat_data_fork(
     229             :         struct xfs_inode        *ip,
     230             :         struct xfs_dinode       *dip)
     231             : {
     232   376231060 :         struct inode            *inode = VFS_I(ip);
     233   376231060 :         int                     error;
     234             : 
     235             :         /*
     236             :          * Initialize the extent count early, as the per-format routines may
     237             :          * depend on it.  Use release semantics to set needextents /after/ we
     238             :          * set the format. This ensures that we can use acquire semantics on
     239             :          * needextents in xfs_need_iread_extents() and be guaranteed to see a
     240             :          * valid format value after that load.
     241             :          */
     242   376231060 :         ip->i_df.if_format = dip->di_format;
     243   376231060 :         ip->i_df.if_nextents = xfs_dfork_data_extents(dip);
     244   376231060 :         smp_store_release(&ip->i_df.if_needextents,
     245             :                            ip->i_df.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0);
     246             : 
     247   376211996 :         switch (inode->i_mode & S_IFMT) {
     248   124993801 :         case S_IFIFO:
     249             :         case S_IFCHR:
     250             :         case S_IFBLK:
     251             :         case S_IFSOCK:
     252   124993801 :                 ip->i_disk_size = 0;
     253   124993801 :                 inode->i_rdev = xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip));
     254   124993801 :                 return 0;
     255   251218195 :         case S_IFREG:
     256             :         case S_IFLNK:
     257             :         case S_IFDIR:
     258   251218195 :                 switch (ip->i_df.if_format) {
     259    62265280 :                 case XFS_DINODE_FMT_LOCAL:
     260    62265280 :                         error = xfs_iformat_local(ip, dip, XFS_DATA_FORK,
     261    62265280 :                                         be64_to_cpu(dip->di_size));
     262    62265659 :                         if (!error)
     263    62265675 :                                 error = xfs_ifork_verify_local_data(ip);
     264             :                         return error;
     265   175768641 :                 case XFS_DINODE_FMT_EXTENTS:
     266   175768641 :                         return xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
     267    12989562 :                 case XFS_DINODE_FMT_BTREE:
     268    12989562 :                         return xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
     269       97411 :                 case XFS_DINODE_FMT_RMAP:
     270       97411 :                         if (!xfs_has_rtrmapbt(ip->i_mount)) {
     271           0 :                                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
     272           0 :                                 return -EFSCORRUPTED;
     273             :                         }
     274       97411 :                         return xfs_iformat_rtrmap(ip, dip);
     275       97301 :                 case XFS_DINODE_FMT_REFCOUNT:
     276       97301 :                         if (!xfs_has_rtreflink(ip->i_mount)) {
     277           0 :                                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
     278           0 :                                 return -EFSCORRUPTED;
     279             :                         }
     280       97301 :                         return xfs_iformat_rtrefcount(ip, dip);
     281             :                 default:
     282           0 :                         xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__,
     283           0 :                                         dip, sizeof(*dip), __this_address);
     284           0 :                         xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
     285           0 :                         return -EFSCORRUPTED;
     286             :                 }
     287           0 :                 break;
     288             :         default:
     289           0 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
     290           0 :                                 sizeof(*dip), __this_address);
     291           0 :                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
     292           0 :                 return -EFSCORRUPTED;
     293             :         }
     294             : }
     295             : 
     296             : static uint16_t
     297             : xfs_dfork_attr_shortform_size(
     298             :         struct xfs_dinode               *dip)
     299             : {
     300   743064794 :         struct xfs_attr_shortform       *atp =
     301   743064794 :                 (struct xfs_attr_shortform *)XFS_DFORK_APTR(dip);
     302             : 
     303   371532397 :         return be16_to_cpu(atp->hdr.totsize);
     304             : }
     305             : 
     306             : void
     307   114590354 : xfs_ifork_init_attr(
     308             :         struct xfs_inode        *ip,
     309             :         enum xfs_dinode_fmt     format,
     310             :         xfs_extnum_t            nextents)
     311             : {
     312             :         /*
     313             :          * Initialize the extent count early, as the per-format routines may
     314             :          * depend on it.  Use release semantics to set needextents /after/ we
     315             :          * set the format. This ensures that we can use acquire semantics on
     316             :          * needextents in xfs_need_iread_extents() and be guaranteed to see a
     317             :          * valid format value after that load.
     318             :          */
     319   488032326 :         ip->i_af.if_format = format;
     320   488032326 :         ip->i_af.if_nextents = nextents;
     321   114590354 :         smp_store_release(&ip->i_af.if_needextents,
     322             :                            ip->i_af.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0);
     323   114519158 : }
     324             : 
     325             : void
     326   513432418 : xfs_ifork_zap_attr(
     327             :         struct xfs_inode        *ip)
     328             : {
     329   513432418 :         xfs_idestroy_fork(&ip->i_af);
     330   513796016 :         memset(&ip->i_af, 0, sizeof(struct xfs_ifork));
     331   513796016 :         ip->i_af.if_format = XFS_DINODE_FMT_EXTENTS;
     332   513796016 : }
     333             : 
     334             : int
     335   373441972 : xfs_iformat_attr_fork(
     336             :         struct xfs_inode        *ip,
     337             :         struct xfs_dinode       *dip)
     338             : {
     339   373441972 :         xfs_extnum_t            naextents = xfs_dfork_attr_extents(dip);
     340   373441972 :         int                     error = 0;
     341             : 
     342             :         /*
     343             :          * Initialize the extent count early, as the per-format routines may
     344             :          * depend on it.
     345             :          */
     346   373441972 :         xfs_ifork_init_attr(ip, dip->di_aformat, naextents);
     347             : 
     348   373427268 :         switch (ip->i_af.if_format) {
     349             :         case XFS_DINODE_FMT_LOCAL:
     350   743068952 :                 error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
     351             :                                 xfs_dfork_attr_shortform_size(dip));
     352   371531098 :                 if (!error)
     353   371531406 :                         error = xfs_ifork_verify_local_attr(ip);
     354             :                 break;
     355     1894717 :         case XFS_DINODE_FMT_EXTENTS:
     356     1894717 :                 error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
     357     1894717 :                 break;
     358         154 :         case XFS_DINODE_FMT_BTREE:
     359         154 :                 error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
     360         154 :                 break;
     361             :         default:
     362           0 :                 xfs_inode_verifier_error(ip, error, __func__, dip,
     363           0 :                                 sizeof(*dip), __this_address);
     364           0 :                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
     365           0 :                 error = -EFSCORRUPTED;
     366           0 :                 break;
     367             :         }
     368             : 
     369   373431955 :         if (error)
     370           0 :                 xfs_ifork_zap_attr(ip);
     371   373431955 :         return error;
     372             : }
     373             : 
     374             : /* Allocate a new incore ifork btree root. */
     375             : void
     376    17003627 : xfs_iroot_alloc(
     377             :         struct xfs_inode        *ip,
     378             :         int                     whichfork,
     379             :         size_t                  bytes)
     380             : {
     381    17003627 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     382             : 
     383    17003617 :         ifp->if_broot = kmem_alloc(bytes, KM_NOFS);
     384    17003642 :         ifp->if_broot_bytes = bytes;
     385    17003642 : }
     386             : 
     387             : /* Free all the memory and state associated with an incore ifork btree root. */
     388             : void
     389     2403501 : xfs_iroot_free(
     390             :         struct xfs_inode        *ip,
     391             :         int                     whichfork)
     392             : {
     393     2403501 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     394             : 
     395     2403498 :         ifp->if_broot_bytes = 0;
     396     2403498 :         kmem_free(ifp->if_broot);
     397     2403508 :         ifp->if_broot = NULL;
     398     2403508 : }
     399             : 
     400             : /*
     401             :  * Reallocate the space for if_broot based on the number of records
     402             :  * being added or deleted as indicated in rec_diff.  Move the records
     403             :  * and pointers in if_broot to fit the new size.  When shrinking this
     404             :  * will eliminate holes between the records and pointers created by
     405             :  * the caller.  When growing this will create holes to be filled in
     406             :  * by the caller.
     407             :  *
     408             :  * The caller must not request to add more records than would fit in
     409             :  * the on-disk inode root.  If the if_broot is currently NULL, then
     410             :  * if we are adding records, one will be allocated.  The caller must also
     411             :  * not request that the number of records go below zero, although
     412             :  * it can go to zero.
     413             :  */
     414             : void
     415     7893759 : xfs_iroot_realloc(
     416             :         struct xfs_inode                *ip,
     417             :         int                             whichfork,
     418             :         const struct xfs_ifork_broot_ops *ops,
     419             :         int                             rec_diff)
     420             : {
     421     7893759 :         struct xfs_mount                *mp = ip->i_mount;
     422     7893759 :         struct xfs_ifork                *ifp = xfs_ifork_ptr(ip, whichfork);
     423     7893760 :         struct xfs_btree_block          *new_broot;
     424     7893760 :         size_t                          new_size;
     425     7893760 :         size_t                          old_size = ifp->if_broot_bytes;
     426     7893760 :         unsigned int                    level;
     427     7893760 :         int                             cur_max;
     428     7893760 :         int                             new_max;
     429             : 
     430             :         /* Handle degenerate cases. */
     431     7893760 :         if (rec_diff == 0)
     432             :                 return;
     433             : 
     434             :         /*
     435             :          * If there wasn't any memory allocated before, just allocate it now
     436             :          * and get out.
     437             :          */
     438     7893760 :         if (old_size == 0) {
     439           0 :                 ASSERT(rec_diff > 0);
     440             : 
     441           0 :                 new_size = ops->size(mp, 0, rec_diff);
     442           0 :                 xfs_iroot_alloc(ip, whichfork, new_size);
     443           0 :                 return;
     444             :         }
     445             : 
     446             :         /* Compute the new and old record count and space requirements. */
     447     7893760 :         level = be16_to_cpu(ifp->if_broot->bb_level);
     448     7893760 :         cur_max = ops->maxrecs(mp, old_size, level == 0);
     449     7893760 :         new_max = cur_max + rec_diff;
     450     7893760 :         ASSERT(new_max >= 0);
     451     7893760 :         new_size = ops->size(mp, level, new_max);
     452             : 
     453     7893759 :         if (rec_diff > 0) {
     454             :                 /*
     455             :                  * If there is already an existing if_broot, then we need
     456             :                  * to realloc() it and shift the pointers to their new
     457             :                  * location.
     458             :                  */
     459     4114302 :                 ifp->if_broot = krealloc(ifp->if_broot, new_size,
     460             :                                          GFP_NOFS | __GFP_NOFAIL);
     461     4114303 :                 ifp->if_broot_bytes = new_size;
     462     4114303 :                 ops->move(ip, whichfork, ifp->if_broot, new_size,
     463             :                                 ifp->if_broot, old_size, level, cur_max);
     464     4114303 :                 return;
     465             :         }
     466             : 
     467             :         /*
     468             :          * rec_diff is less than 0.  In this case, we are shrinking the
     469             :          * if_broot buffer.  It must already exist.  If we go to zero
     470             :          * bytes, just get rid of the root and clear the status bit.
     471             :          */
     472     3779457 :         if (new_size == 0) {
     473           0 :                 xfs_iroot_free(ip, whichfork);
     474           0 :                 return;
     475             :         }
     476             : 
     477             :         /* Reallocate the btree root and move the contents. */
     478     3779457 :         new_broot = kmem_alloc(new_size, KM_NOFS);
     479     3779457 :         ops->move(ip, whichfork, new_broot, new_size, ifp->if_broot,
     480     3779457 :                         ifp->if_broot_bytes, level, new_max);
     481             : 
     482     3779457 :         kmem_free(ifp->if_broot);
     483     3779457 :         ifp->if_broot = new_broot;
     484     3779457 :         ifp->if_broot_bytes = new_size;
     485             : }
     486             : 
     487             : /*
     488             :  * This is called when the amount of space needed for if_data
     489             :  * is increased or decreased.  The change in size is indicated by
     490             :  * the number of bytes that need to be added or deleted in the
     491             :  * byte_diff parameter.
     492             :  *
     493             :  * If the amount of space needed has decreased below the size of the
     494             :  * inline buffer, then switch to using the inline buffer.  Otherwise,
     495             :  * use kmem_realloc() or kmem_alloc() to adjust the size of the buffer
     496             :  * to what is needed.
     497             :  *
     498             :  * ip -- the inode whose if_data area is changing
     499             :  * byte_diff -- the change in the number of bytes, positive or negative,
     500             :  *       requested for the if_data array.
     501             :  */
     502             : void
     503   663815852 : xfs_idata_realloc(
     504             :         struct xfs_inode        *ip,
     505             :         int64_t                 byte_diff,
     506             :         int                     whichfork)
     507             : {
     508   663815852 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     509   663756129 :         int64_t                 new_size = ifp->if_bytes + byte_diff;
     510             : 
     511   663756129 :         ASSERT(new_size >= 0);
     512   663756129 :         ASSERT(new_size <= xfs_inode_fork_size(ip, whichfork));
     513             : 
     514   663756129 :         if (byte_diff == 0)
     515             :                 return;
     516             : 
     517   663756123 :         if (new_size == 0) {
     518     8903494 :                 kmem_free(ifp->if_u1.if_data);
     519     8903908 :                 ifp->if_u1.if_data = NULL;
     520     8903908 :                 ifp->if_bytes = 0;
     521     8903908 :                 return;
     522             :         }
     523             : 
     524   654852629 :         ifp->if_u1.if_data = krealloc(ifp->if_u1.if_data, new_size,
     525             :                                       GFP_NOFS | __GFP_NOFAIL);
     526   654955612 :         ifp->if_bytes = new_size;
     527             : }
     528             : 
     529             : /* Free all memory and reset a fork back to its initial state. */
     530             : void
     531   904593234 : xfs_idestroy_fork(
     532             :         struct xfs_ifork        *ifp)
     533             : {
     534   904593234 :         if (ifp->if_broot != NULL) {
     535    14737157 :                 kmem_free(ifp->if_broot);
     536    14737446 :                 ifp->if_broot = NULL;
     537             :         }
     538             : 
     539   904593523 :         switch (ifp->if_format) {
     540   553191321 :         case XFS_DINODE_FMT_LOCAL:
     541   553191321 :                 kmem_free(ifp->if_u1.if_data);
     542   553832329 :                 ifp->if_u1.if_data = NULL;
     543   553832329 :                 break;
     544   351161842 :         case XFS_DINODE_FMT_EXTENTS:
     545             :         case XFS_DINODE_FMT_BTREE:
     546   351161842 :                 if (ifp->if_height)
     547   124000404 :                         xfs_iext_destroy(ifp);
     548             :                 break;
     549             :         }
     550   905235104 : }
     551             : 
     552             : /*
     553             :  * Convert in-core extents to on-disk form
     554             :  *
     555             :  * In the case of the data fork, the in-core and on-disk fork sizes can be
     556             :  * different due to delayed allocation extents. We only copy on-disk extents
     557             :  * here, so callers must always use the physical fork size to determine the
     558             :  * size of the buffer passed to this routine.  We will return the size actually
     559             :  * used.
     560             :  */
     561             : int
     562   737480463 : xfs_iextents_copy(
     563             :         struct xfs_inode        *ip,
     564             :         struct xfs_bmbt_rec     *dp,
     565             :         int                     whichfork)
     566             : {
     567   737480463 :         int                     state = xfs_bmap_fork_to_state(whichfork);
     568   737480463 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     569   737415659 :         struct xfs_iext_cursor  icur;
     570   737415659 :         struct xfs_bmbt_irec    rec;
     571   737415659 :         int64_t                 copied = 0;
     572             : 
     573   737415659 :         ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL | XFS_ILOCK_SHARED));
     574   737409317 :         ASSERT(ifp->if_bytes > 0);
     575             : 
     576  3825363015 :         for_each_xfs_iext(ifp, &icur, &rec) {
     577  3088043360 :                 if (isnullstartblock(rec.br_startblock))
     578    55920861 :                         continue;
     579  3032122499 :                 ASSERT(xfs_bmap_validate_extent(ip, whichfork, &rec) == NULL);
     580  3032092888 :                 xfs_bmbt_disk_set_all(dp, &rec);
     581  3032045496 :                 trace_xfs_write_extent(ip, &icur, state, _RET_IP_);
     582  3032032837 :                 copied += sizeof(struct xfs_bmbt_rec);
     583  3032032837 :                 dp++;
     584             :         }
     585             : 
     586   737401523 :         ASSERT(copied > 0);
     587   737401523 :         ASSERT(copied <= ifp->if_bytes);
     588   737401523 :         return copied;
     589             : }
     590             : 
     591             : /*
     592             :  * Each of the following cases stores data into the same region
     593             :  * of the on-disk inode, so only one of them can be valid at
     594             :  * any given time. While it is possible to have conflicting formats
     595             :  * and log flags, e.g. having XFS_ILOG_?DATA set when the fork is
     596             :  * in EXTENTS format, this can only happen when the fork has
     597             :  * changed formats after being modified but before being flushed.
     598             :  * In these cases, the format always takes precedence, because the
     599             :  * format indicates the current state of the fork.
     600             :  */
     601             : void
     602   712574623 : xfs_iflush_fork(
     603             :         struct xfs_inode        *ip,
     604             :         struct xfs_dinode       *dip,
     605             :         struct xfs_inode_log_item *iip,
     606             :         int                     whichfork)
     607             : {
     608   712574623 :         char                    *cp;
     609   712574623 :         struct xfs_ifork        *ifp;
     610   712574623 :         xfs_mount_t             *mp;
     611   712574623 :         static const short      brootflag[2] =
     612             :                 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
     613   712574623 :         static const short      dataflag[2] =
     614             :                 { XFS_ILOG_DDATA, XFS_ILOG_ADATA };
     615   712574623 :         static const short      extflag[2] =
     616             :                 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
     617             : 
     618   712574623 :         if (!iip)
     619             :                 return;
     620   712574623 :         ifp = xfs_ifork_ptr(ip, whichfork);
     621             :         /*
     622             :          * This can happen if we gave up in iformat in an error path,
     623             :          * for the attribute fork.
     624             :          */
     625   712574623 :         if (!ifp) {
     626           0 :                 ASSERT(whichfork == XFS_ATTR_FORK);
     627           0 :                 return;
     628             :         }
     629  1425147910 :         cp = XFS_DFORK_PTR(dip, whichfork);
     630   712574623 :         mp = ip->i_mount;
     631   712574623 :         switch (ifp->if_format) {
     632   341255616 :         case XFS_DINODE_FMT_LOCAL:
     633   341255616 :                 if ((iip->ili_fields & dataflag[whichfork]) &&
     634   210616001 :                     (ifp->if_bytes > 0)) {
     635   210616001 :                         ASSERT(ifp->if_u1.if_data != NULL);
     636   210616001 :                         ASSERT(ifp->if_bytes <= xfs_inode_fork_size(ip, whichfork));
     637   421232002 :                         memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
     638             :                 }
     639             :                 break;
     640             : 
     641   318804533 :         case XFS_DINODE_FMT_EXTENTS:
     642   318804533 :                 if ((iip->ili_fields & extflag[whichfork]) &&
     643    50908347 :                     (ifp->if_bytes > 0)) {
     644    50908347 :                         ASSERT(ifp->if_nextents > 0);
     645    50908347 :                         (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
     646             :                                 whichfork);
     647             :                 }
     648             :                 break;
     649             : 
     650    23679916 :         case XFS_DINODE_FMT_BTREE:
     651    23679916 :                 if ((iip->ili_fields & brootflag[whichfork]) &&
     652     3072905 :                     (ifp->if_broot_bytes > 0)) {
     653     3072905 :                         ASSERT(ifp->if_broot != NULL);
     654     3072905 :                         ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <=
     655             :                                 xfs_inode_fork_size(ip, whichfork));
     656     6145810 :                         xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes,
     657             :                                 (xfs_bmdr_block_t *)cp,
     658     3072905 :                                 XFS_DFORK_SIZE(dip, mp, whichfork));
     659             :                 }
     660             :                 break;
     661             : 
     662    28722599 :         case XFS_DINODE_FMT_DEV:
     663    28722599 :                 if (iip->ili_fields & XFS_ILOG_DEV) {
     664    14314522 :                         ASSERT(whichfork == XFS_DATA_FORK);
     665    14314522 :                         xfs_dinode_put_rdev(dip,
     666             :                                         linux_to_xfs_dev_t(VFS_I(ip)->i_rdev));
     667             :                 }
     668             :                 break;
     669             : 
     670       66641 :         case XFS_DINODE_FMT_RMAP:
     671       66641 :                 ASSERT(whichfork == XFS_DATA_FORK);
     672       66641 :                 if (iip->ili_fields & brootflag[whichfork])
     673       44700 :                         xfs_iflush_rtrmap(ip, dip);
     674             :                 break;
     675             : 
     676       45318 :         case XFS_DINODE_FMT_REFCOUNT:
     677       45318 :                 ASSERT(whichfork == XFS_DATA_FORK);
     678       45318 :                 if (iip->ili_fields & brootflag[whichfork])
     679       44743 :                         xfs_iflush_rtrefcount(ip, dip);
     680             :                 break;
     681             : 
     682           0 :         default:
     683           0 :                 ASSERT(0);
     684           0 :                 break;
     685             :         }
     686             : }
     687             : 
     688             : /* Convert bmap state flags to an inode fork. */
     689             : struct xfs_ifork *
     690  2311424842 : xfs_iext_state_to_fork(
     691             :         struct xfs_inode        *ip,
     692             :         int                     state)
     693             : {
     694  2311424842 :         if (state & BMAP_COWFORK)
     695    59880194 :                 return ip->i_cowfp;
     696  2251544648 :         else if (state & BMAP_ATTRFORK)
     697    16320489 :                 return &ip->i_af;
     698  2235224159 :         return &ip->i_df;
     699             : }
     700             : 
     701             : /*
     702             :  * Initialize an inode's copy-on-write fork.
     703             :  */
     704             : void
     705   100562985 : xfs_ifork_init_cow(
     706             :         struct xfs_inode        *ip)
     707             : {
     708   100562985 :         if (ip->i_cowfp)
     709             :                 return;
     710             : 
     711    96079634 :         ip->i_cowfp = kmem_cache_zalloc(xfs_ifork_cache,
     712             :                                        GFP_NOFS | __GFP_NOFAIL);
     713    96080215 :         ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS;
     714             : }
     715             : 
     716             : /* Verify the inline contents of the data fork of an inode. */
     717             : int
     718   141847586 : xfs_ifork_verify_local_data(
     719             :         struct xfs_inode        *ip)
     720             : {
     721   141847586 :         xfs_failaddr_t          fa = NULL;
     722             : 
     723   141847586 :         switch (VFS_I(ip)->i_mode & S_IFMT) {
     724   136107379 :         case S_IFDIR:
     725   136107379 :                 fa = xfs_dir2_sf_verify(ip);
     726   136107379 :                 break;
     727     5740207 :         case S_IFLNK:
     728     5740207 :                 fa = xfs_symlink_shortform_verify(ip);
     729     5740207 :                 break;
     730             :         default:
     731             :                 break;
     732             :         }
     733             : 
     734   141848283 :         if (fa) {
     735          22 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "data fork",
     736          22 :                                 ip->i_df.if_u1.if_data, ip->i_df.if_bytes, fa);
     737          22 :                 return -EFSCORRUPTED;
     738             :         }
     739             : 
     740             :         return 0;
     741             : }
     742             : 
     743             : /* Verify the inline contents of the attr fork of an inode. */
     744             : int
     745   633215366 : xfs_ifork_verify_local_attr(
     746             :         struct xfs_inode        *ip)
     747             : {
     748   633215366 :         struct xfs_ifork        *ifp = &ip->i_af;
     749   633215366 :         xfs_failaddr_t          fa;
     750             : 
     751   633215366 :         if (!xfs_inode_has_attr_fork(ip))
     752           0 :                 fa = __this_address;
     753             :         else
     754   633215366 :                 fa = xfs_attr_shortform_verify(ip);
     755             : 
     756   633210548 :         if (fa) {
     757           0 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "attr fork",
     758           0 :                                 ifp->if_u1.if_data, ifp->if_bytes, fa);
     759           0 :                 return -EFSCORRUPTED;
     760             :         }
     761             : 
     762             :         return 0;
     763             : }
     764             : 
     765             : int
     766   809058984 : xfs_iext_count_may_overflow(
     767             :         struct xfs_inode        *ip,
     768             :         int                     whichfork,
     769             :         int                     nr_to_add)
     770             : {
     771   809058984 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     772   808699755 :         uint64_t                max_exts;
     773   808699755 :         uint64_t                nr_exts;
     774             : 
     775   808699755 :         if (whichfork == XFS_COW_FORK)
     776             :                 return 0;
     777             : 
     778   802425440 :         max_exts = xfs_iext_max_nextents(xfs_inode_has_large_extent_counts(ip),
     779             :                                 whichfork);
     780             : 
     781   802472071 :         if (XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
     782        2156 :                 max_exts = 10;
     783             : 
     784   802372773 :         nr_exts = ifp->if_nextents + nr_to_add;
     785   802372773 :         if (nr_exts < ifp->if_nextents || nr_exts > max_exts)
     786         281 :                 return -EFBIG;
     787             : 
     788             :         return 0;
     789             : }
     790             : 
     791             : /*
     792             :  * Upgrade this inode's extent counter fields to be able to handle a potential
     793             :  * increase in the extent count by nr_to_add.  Normally this is the same
     794             :  * quantity that caused xfs_iext_count_may_overflow() to return -EFBIG.
     795             :  */
     796             : int
     797         281 : xfs_iext_count_upgrade(
     798             :         struct xfs_trans        *tp,
     799             :         struct xfs_inode        *ip,
     800             :         uint                    nr_to_add)
     801             : {
     802         281 :         ASSERT(nr_to_add <= XFS_MAX_EXTCNT_UPGRADE_NR);
     803             : 
     804         281 :         if (!xfs_has_large_extent_counts(ip->i_mount) ||
     805           0 :             xfs_inode_has_large_extent_counts(ip) ||
     806           0 :             XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
     807         281 :                 return -EFBIG;
     808             : 
     809           0 :         ip->i_diflags2 |= XFS_DIFLAG2_NREXT64;
     810           0 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     811             : 
     812           0 :         return 0;
     813             : }
     814             : 
     815             : /* Decide if a file mapping is on the realtime device or not. */
     816             : bool
     817  3137409352 : xfs_ifork_is_realtime(
     818             :         struct xfs_inode        *ip,
     819             :         int                     whichfork)
     820             : {
     821  3137409352 :         return XFS_IS_REALTIME_INODE(ip) && whichfork != XFS_ATTR_FORK;
     822             : }

Generated by: LCOV version 1.14