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-rc3-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 289 330 87.6 %
Date: 2023-07-31 20:08:22 Functions: 19 19 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             : 
      29             : struct kmem_cache *xfs_ifork_cache;
      30             : 
      31             : void
      32   121057354 : xfs_init_local_fork(
      33             :         struct xfs_inode        *ip,
      34             :         int                     whichfork,
      35             :         const void              *data,
      36             :         int64_t                 size)
      37             : {
      38   121057354 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
      39   121052458 :         int                     mem_size = size;
      40   121052458 :         bool                    zero_terminate;
      41             : 
      42             :         /*
      43             :          * If we are using the local fork to store a symlink body we need to
      44             :          * zero-terminate it so that we can pass it back to the VFS directly.
      45             :          * Overallocate the in-memory fork by one for that and add a zero
      46             :          * to terminate it below.
      47             :          */
      48   121052458 :         zero_terminate = S_ISLNK(VFS_I(ip)->i_mode);
      49   121052458 :         if (zero_terminate)
      50    15311837 :                 mem_size++;
      51             : 
      52   121052458 :         if (size) {
      53   121052458 :                 ifp->if_u1.if_data = kmem_alloc(mem_size, KM_NOFS);
      54   242121666 :                 memcpy(ifp->if_u1.if_data, data, size);
      55   121060833 :                 if (zero_terminate)
      56    15317654 :                         ifp->if_u1.if_data[size] = '\0';
      57             :         } else {
      58           0 :                 ifp->if_u1.if_data = NULL;
      59             :         }
      60             : 
      61   121060833 :         ifp->if_bytes = size;
      62   121060833 : }
      63             : 
      64             : /*
      65             :  * The file is in-lined in the on-disk inode.
      66             :  */
      67             : STATIC int
      68   112437240 : xfs_iformat_local(
      69             :         struct xfs_inode        *ip,
      70             :         struct xfs_dinode       *dip,
      71             :         int                     whichfork,
      72             :         int                     size)
      73             : {
      74             :         /*
      75             :          * If the size is unreasonable, then something
      76             :          * is wrong and we just bail out rather than crash in
      77             :          * kmem_alloc() or memcpy() below.
      78             :          */
      79   112437457 :         if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
      80           0 :                 xfs_warn(ip->i_mount,
      81             :         "corrupt inode %llu (bad size %d for local fork, size = %zd).",
      82             :                         (unsigned long long) ip->i_ino, size,
      83             :                         XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
      84           0 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
      85             :                                 "xfs_iformat_local", dip, sizeof(*dip),
      86           0 :                                 __this_address);
      87           0 :                 return -EFSCORRUPTED;
      88             :         }
      89             : 
      90   224874115 :         xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
      91   112437240 :         return 0;
      92             : }
      93             : 
      94             : /*
      95             :  * The file consists of a set of extents all of which fit into the on-disk
      96             :  * inode.
      97             :  */
      98             : STATIC int
      99   187159494 : xfs_iformat_extents(
     100             :         struct xfs_inode        *ip,
     101             :         struct xfs_dinode       *dip,
     102             :         int                     whichfork)
     103             : {
     104   187159494 :         struct xfs_mount        *mp = ip->i_mount;
     105   187159494 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     106   187153194 :         int                     state = xfs_bmap_fork_to_state(whichfork);
     107   187153194 :         xfs_extnum_t            nex = xfs_dfork_nextents(dip, whichfork);
     108   187166931 :         int                     size = nex * sizeof(xfs_bmbt_rec_t);
     109   187166931 :         struct xfs_iext_cursor  icur;
     110   187166931 :         struct xfs_bmbt_rec     *dp;
     111   187166931 :         struct xfs_bmbt_irec    new;
     112   187166931 :         int                     i;
     113             : 
     114             :         /*
     115             :          * If the number of extents is unreasonable, then something is wrong and
     116             :          * we just bail out rather than crash in kmem_alloc() or memcpy() below.
     117             :          */
     118   187167417 :         if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, mp, whichfork))) {
     119           0 :                 xfs_warn(ip->i_mount, "corrupt inode %llu ((a)extents = %llu).",
     120             :                         ip->i_ino, nex);
     121           0 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
     122             :                                 "xfs_iformat_extents(1)", dip, sizeof(*dip),
     123           0 :                                 __this_address);
     124           0 :                 return -EFSCORRUPTED;
     125             :         }
     126             : 
     127   187166931 :         ifp->if_bytes = 0;
     128   187166931 :         ifp->if_u1.if_root = NULL;
     129   187166931 :         ifp->if_height = 0;
     130   187166931 :         if (size) {
     131   241198254 :                 dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
     132             : 
     133   120600821 :                 xfs_iext_first(ifp, &icur);
     134   747221392 :                 for (i = 0; i < nex; i++, dp++) {
     135   506028943 :                         xfs_failaddr_t  fa;
     136             : 
     137   506028943 :                         xfs_bmbt_disk_get_all(dp, &new);
     138   506032384 :                         fa = xfs_bmap_validate_extent(ip, whichfork, &new);
     139   506031345 :                         if (fa) {
     140           0 :                                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
     141             :                                                 "xfs_iformat_extents(2)",
     142             :                                                 dp, sizeof(*dp), fa);
     143           0 :                                 return xfs_bmap_complain_bad_rec(ip, whichfork,
     144             :                                                 fa, &new);
     145             :                         }
     146             : 
     147   506031345 :                         xfs_iext_insert(ip, &icur, &new, state);
     148   506024780 :                         trace_xfs_read_extent(ip, &icur, state, _THIS_IP_);
     149   506025455 :                         xfs_iext_next(ifp, &icur);
     150             :                 }
     151             :         }
     152             :         return 0;
     153             : }
     154             : 
     155             : /*
     156             :  * The file has too many extents to fit into
     157             :  * the inode, so they are in B-tree format.
     158             :  * Allocate a buffer for the root of the B-tree
     159             :  * and copy the root into it.  The i_extents
     160             :  * field will remain NULL until all of the
     161             :  * extents are read in (when they are needed).
     162             :  */
     163             : STATIC int
     164     5927595 : xfs_iformat_btree(
     165             :         struct xfs_inode        *ip,
     166             :         struct xfs_dinode       *dip,
     167             :         int                     whichfork)
     168             : {
     169     5927595 :         struct xfs_mount        *mp = ip->i_mount;
     170     5927595 :         xfs_bmdr_block_t        *dfp;
     171     5927595 :         struct xfs_ifork        *ifp;
     172             :         /* REFERENCED */
     173     5927595 :         int                     nrecs;
     174     5927595 :         int                     size;
     175     5927595 :         int                     level;
     176             : 
     177     5927595 :         ifp = xfs_ifork_ptr(ip, whichfork);
     178    11855189 :         dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
     179     5927595 :         size = XFS_BMAP_BROOT_SPACE(mp, dfp);
     180     5927595 :         nrecs = be16_to_cpu(dfp->bb_numrecs);
     181     5927595 :         level = be16_to_cpu(dfp->bb_level);
     182             : 
     183             :         /*
     184             :          * blow out if -- fork has less extents than can fit in
     185             :          * fork (fork shouldn't be a btree format), root btree
     186             :          * block has more records than can fit into the fork,
     187             :          * or the number of extents is greater than the number of
     188             :          * blocks.
     189             :          */
     190     5927595 :         if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) ||
     191             :                      nrecs == 0 ||
     192             :                      XFS_BMDR_SPACE_CALC(nrecs) >
     193             :                                         XFS_DFORK_SIZE(dip, mp, whichfork) ||
     194     5927595 :                      ifp->if_nextents > ip->i_nblocks) ||
     195     5927595 :                      level == 0 || level > XFS_BM_MAXLEVELS(mp, whichfork)) {
     196           0 :                 xfs_warn(mp, "corrupt inode %llu (btree).",
     197             :                                         (unsigned long long) ip->i_ino);
     198           0 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
     199             :                                 "xfs_iformat_btree", dfp, size,
     200           0 :                                 __this_address);
     201           0 :                 return -EFSCORRUPTED;
     202             :         }
     203             : 
     204     5927596 :         ifp->if_broot_bytes = size;
     205     5927596 :         ifp->if_broot = kmem_alloc(size, KM_NOFS);
     206     5927598 :         ASSERT(ifp->if_broot != NULL);
     207             :         /*
     208             :          * Copy and convert from the on-disk structure
     209             :          * to the in-memory structure.
     210             :          */
     211     5927598 :         xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
     212             :                          ifp->if_broot, size);
     213             : 
     214     5927594 :         ifp->if_bytes = 0;
     215     5927594 :         ifp->if_u1.if_root = NULL;
     216     5927594 :         ifp->if_height = 0;
     217     5927594 :         return 0;
     218             : }
     219             : 
     220             : int
     221   392485702 : xfs_iformat_data_fork(
     222             :         struct xfs_inode        *ip,
     223             :         struct xfs_dinode       *dip)
     224             : {
     225   392485702 :         struct inode            *inode = VFS_I(ip);
     226   392485702 :         int                     error;
     227             : 
     228             :         /*
     229             :          * Initialize the extent count early, as the per-format routines may
     230             :          * depend on it.  Use release semantics to set needextents /after/ we
     231             :          * set the format. This ensures that we can use acquire semantics on
     232             :          * needextents in xfs_need_iread_extents() and be guaranteed to see a
     233             :          * valid format value after that load.
     234             :          */
     235   392485702 :         ip->i_df.if_format = dip->di_format;
     236   392485702 :         ip->i_df.if_nextents = xfs_dfork_data_extents(dip);
     237   392485702 :         smp_store_release(&ip->i_df.if_needextents,
     238             :                            ip->i_df.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0);
     239             : 
     240   392431570 :         switch (inode->i_mode & S_IFMT) {
     241   131276379 :         case S_IFIFO:
     242             :         case S_IFCHR:
     243             :         case S_IFBLK:
     244             :         case S_IFSOCK:
     245   131276379 :                 ip->i_disk_size = 0;
     246   131276379 :                 inode->i_rdev = xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip));
     247   131276379 :                 return 0;
     248   261155191 :         case S_IFREG:
     249             :         case S_IFLNK:
     250             :         case S_IFDIR:
     251   261155191 :                 switch (ip->i_df.if_format) {
     252    70162985 :                 case XFS_DINODE_FMT_LOCAL:
     253    70162985 :                         error = xfs_iformat_local(ip, dip, XFS_DATA_FORK,
     254    70162985 :                                         be64_to_cpu(dip->di_size));
     255    70163872 :                         if (!error)
     256    70163857 :                                 error = xfs_ifork_verify_local_data(ip);
     257             :                         return error;
     258   185064652 :                 case XFS_DINODE_FMT_EXTENTS:
     259   185064652 :                         return xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
     260     5927554 :                 case XFS_DINODE_FMT_BTREE:
     261     5927554 :                         return xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
     262             :                 default:
     263           0 :                         xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__,
     264           0 :                                         dip, sizeof(*dip), __this_address);
     265           0 :                         return -EFSCORRUPTED;
     266             :                 }
     267           0 :                 break;
     268             :         default:
     269           0 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
     270           0 :                                 sizeof(*dip), __this_address);
     271           0 :                 return -EFSCORRUPTED;
     272             :         }
     273             : }
     274             : 
     275             : static uint16_t
     276             : xfs_dfork_attr_shortform_size(
     277             :         struct xfs_dinode               *dip)
     278             : {
     279    84547862 :         struct xfs_attr_shortform       *atp =
     280    84547862 :                 (struct xfs_attr_shortform *)XFS_DFORK_APTR(dip);
     281             : 
     282    42273931 :         return be16_to_cpu(atp->hdr.totsize);
     283             : }
     284             : 
     285             : void
     286     4927275 : xfs_ifork_init_attr(
     287             :         struct xfs_inode        *ip,
     288             :         enum xfs_dinode_fmt     format,
     289             :         xfs_extnum_t            nextents)
     290             : {
     291             :         /*
     292             :          * Initialize the extent count early, as the per-format routines may
     293             :          * depend on it.  Use release semantics to set needextents /after/ we
     294             :          * set the format. This ensures that we can use acquire semantics on
     295             :          * needextents in xfs_need_iread_extents() and be guaranteed to see a
     296             :          * valid format value after that load.
     297             :          */
     298    49270691 :         ip->i_af.if_format = format;
     299    49270691 :         ip->i_af.if_nextents = nextents;
     300     4927275 :         smp_store_release(&ip->i_af.if_needextents,
     301             :                            ip->i_af.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0);
     302     4927031 : }
     303             : 
     304             : void
     305   441885893 : xfs_ifork_zap_attr(
     306             :         struct xfs_inode        *ip)
     307             : {
     308   441885893 :         xfs_idestroy_fork(&ip->i_af);
     309   441935904 :         memset(&ip->i_af, 0, sizeof(struct xfs_ifork));
     310   441935904 :         ip->i_af.if_format = XFS_DINODE_FMT_EXTENTS;
     311   441935904 : }
     312             : 
     313             : int
     314    44343416 : xfs_iformat_attr_fork(
     315             :         struct xfs_inode        *ip,
     316             :         struct xfs_dinode       *dip)
     317             : {
     318    44343416 :         xfs_extnum_t            naextents = xfs_dfork_attr_extents(dip);
     319    44343416 :         int                     error = 0;
     320             : 
     321             :         /*
     322             :          * Initialize the extent count early, as the per-format routines may
     323             :          * depend on it.
     324             :          */
     325    44343416 :         xfs_ifork_init_attr(ip, dip->di_aformat, naextents);
     326             : 
     327    44343354 :         switch (ip->i_af.if_format) {
     328             :         case XFS_DINODE_FMT_LOCAL:
     329    84547856 :                 error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
     330             :                                 xfs_dfork_attr_shortform_size(dip));
     331    42273897 :                 if (!error)
     332    42273899 :                         error = xfs_ifork_verify_local_attr(ip);
     333             :                 break;
     334     2069383 :         case XFS_DINODE_FMT_EXTENTS:
     335     2069383 :                 error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
     336     2069383 :                 break;
     337          40 :         case XFS_DINODE_FMT_BTREE:
     338          40 :                 error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
     339          40 :                 break;
     340             :         default:
     341           0 :                 xfs_inode_verifier_error(ip, error, __func__, dip,
     342           0 :                                 sizeof(*dip), __this_address);
     343           0 :                 error = -EFSCORRUPTED;
     344           0 :                 break;
     345             :         }
     346             : 
     347    44343361 :         if (error)
     348           0 :                 xfs_ifork_zap_attr(ip);
     349    44343361 :         return error;
     350             : }
     351             : 
     352             : /*
     353             :  * Reallocate the space for if_broot based on the number of records
     354             :  * being added or deleted as indicated in rec_diff.  Move the records
     355             :  * and pointers in if_broot to fit the new size.  When shrinking this
     356             :  * will eliminate holes between the records and pointers created by
     357             :  * the caller.  When growing this will create holes to be filled in
     358             :  * by the caller.
     359             :  *
     360             :  * The caller must not request to add more records than would fit in
     361             :  * the on-disk inode root.  If the if_broot is currently NULL, then
     362             :  * if we are adding records, one will be allocated.  The caller must also
     363             :  * not request that the number of records go below zero, although
     364             :  * it can go to zero.
     365             :  *
     366             :  * ip -- the inode whose if_broot area is changing
     367             :  * ext_diff -- the change in the number of records, positive or negative,
     368             :  *       requested for the if_broot array.
     369             :  */
     370             : void
     371     1451201 : xfs_iroot_realloc(
     372             :         xfs_inode_t             *ip,
     373             :         int                     rec_diff,
     374             :         int                     whichfork)
     375             : {
     376     1451201 :         struct xfs_mount        *mp = ip->i_mount;
     377     1451201 :         int                     cur_max;
     378     1451201 :         struct xfs_ifork        *ifp;
     379     1451201 :         struct xfs_btree_block  *new_broot;
     380     1451201 :         int                     new_max;
     381     1451201 :         size_t                  new_size;
     382     1451201 :         char                    *np;
     383     1451201 :         char                    *op;
     384             : 
     385             :         /*
     386             :          * Handle the degenerate case quietly.
     387             :          */
     388     1451201 :         if (rec_diff == 0) {
     389             :                 return;
     390             :         }
     391             : 
     392     1451201 :         ifp = xfs_ifork_ptr(ip, whichfork);
     393     1451196 :         if (rec_diff > 0) {
     394             :                 /*
     395             :                  * If there wasn't any memory allocated before, just
     396             :                  * allocate it now and get out.
     397             :                  */
     398      897155 :                 if (ifp->if_broot_bytes == 0) {
     399      814701 :                         new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff);
     400      814701 :                         ifp->if_broot = kmem_alloc(new_size, KM_NOFS);
     401      814704 :                         ifp->if_broot_bytes = (int)new_size;
     402      814704 :                         return;
     403             :                 }
     404             : 
     405             :                 /*
     406             :                  * If there is already an existing if_broot, then we need
     407             :                  * to realloc() it and shift the pointers to their new
     408             :                  * location.  The records don't change location because
     409             :                  * they are kept butted up against the btree block header.
     410             :                  */
     411       82454 :                 cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
     412       82454 :                 new_max = cur_max + rec_diff;
     413       82454 :                 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
     414       82454 :                 ifp->if_broot = krealloc(ifp->if_broot, new_size,
     415             :                                          GFP_NOFS | __GFP_NOFAIL);
     416       82455 :                 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
     417             :                                                      ifp->if_broot_bytes);
     418       82454 :                 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
     419             :                                                      (int)new_size);
     420       82455 :                 ifp->if_broot_bytes = (int)new_size;
     421       82455 :                 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
     422             :                         xfs_inode_fork_size(ip, whichfork));
     423      164910 :                 memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t));
     424       82455 :                 return;
     425             :         }
     426             : 
     427             :         /*
     428             :          * rec_diff is less than 0.  In this case, we are shrinking the
     429             :          * if_broot buffer.  It must already exist.  If we go to zero
     430             :          * records, just get rid of the root and clear the status bit.
     431             :          */
     432      554041 :         ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
     433      554041 :         cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
     434      554041 :         new_max = cur_max + rec_diff;
     435      554041 :         ASSERT(new_max >= 0);
     436      554041 :         if (new_max > 0)
     437       60313 :                 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
     438             :         else
     439             :                 new_size = 0;
     440       60313 :         if (new_size > 0) {
     441       60313 :                 new_broot = kmem_alloc(new_size, KM_NOFS);
     442             :                 /*
     443             :                  * First copy over the btree block header.
     444             :                  */
     445      120626 :                 memcpy(new_broot, ifp->if_broot,
     446             :                         XFS_BMBT_BLOCK_LEN(ip->i_mount));
     447             :         } else {
     448             :                 new_broot = NULL;
     449             :         }
     450             : 
     451             :         /*
     452             :          * Only copy the records and pointers if there are any.
     453             :          */
     454      554041 :         if (new_max > 0) {
     455             :                 /*
     456             :                  * First copy the records.
     457             :                  */
     458       60313 :                 op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1);
     459       60313 :                 np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1);
     460      120626 :                 memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t));
     461             : 
     462             :                 /*
     463             :                  * Then copy the pointers.
     464             :                  */
     465       60313 :                 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
     466             :                                                      ifp->if_broot_bytes);
     467       60313 :                 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1,
     468             :                                                      (int)new_size);
     469      120626 :                 memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
     470             :         }
     471      554041 :         kmem_free(ifp->if_broot);
     472      554042 :         ifp->if_broot = new_broot;
     473      554042 :         ifp->if_broot_bytes = (int)new_size;
     474      554042 :         if (ifp->if_broot)
     475       60313 :                 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
     476             :                         xfs_inode_fork_size(ip, whichfork));
     477             :         return;
     478             : }
     479             : 
     480             : 
     481             : /*
     482             :  * This is called when the amount of space needed for if_data
     483             :  * is increased or decreased.  The change in size is indicated by
     484             :  * the number of bytes that need to be added or deleted in the
     485             :  * byte_diff parameter.
     486             :  *
     487             :  * If the amount of space needed has decreased below the size of the
     488             :  * inline buffer, then switch to using the inline buffer.  Otherwise,
     489             :  * use kmem_realloc() or kmem_alloc() to adjust the size of the buffer
     490             :  * to what is needed.
     491             :  *
     492             :  * ip -- the inode whose if_data area is changing
     493             :  * byte_diff -- the change in the number of bytes, positive or negative,
     494             :  *       requested for the if_data array.
     495             :  */
     496             : void
     497   145412865 : xfs_idata_realloc(
     498             :         struct xfs_inode        *ip,
     499             :         int64_t                 byte_diff,
     500             :         int                     whichfork)
     501             : {
     502   145412865 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     503   145384953 :         int64_t                 new_size = ifp->if_bytes + byte_diff;
     504             : 
     505   145384953 :         ASSERT(new_size >= 0);
     506   145384953 :         ASSERT(new_size <= xfs_inode_fork_size(ip, whichfork));
     507             : 
     508   145384953 :         if (byte_diff == 0)
     509             :                 return;
     510             : 
     511   145384953 :         if (new_size == 0) {
     512     3041396 :                 kmem_free(ifp->if_u1.if_data);
     513     3041545 :                 ifp->if_u1.if_data = NULL;
     514     3041545 :                 ifp->if_bytes = 0;
     515     3041545 :                 return;
     516             :         }
     517             : 
     518   142343557 :         ifp->if_u1.if_data = krealloc(ifp->if_u1.if_data, new_size,
     519             :                                       GFP_NOFS | __GFP_NOFAIL);
     520   142386331 :         ifp->if_bytes = new_size;
     521             : }
     522             : 
     523             : void
     524   819946671 : xfs_idestroy_fork(
     525             :         struct xfs_ifork        *ifp)
     526             : {
     527   819946671 :         if (ifp->if_broot != NULL) {
     528     6248341 :                 kmem_free(ifp->if_broot);
     529     6248392 :                 ifp->if_broot = NULL;
     530             :         }
     531             : 
     532   819946722 :         switch (ifp->if_format) {
     533   121815467 :         case XFS_DINODE_FMT_LOCAL:
     534   121815467 :                 kmem_free(ifp->if_u1.if_data);
     535   121839258 :                 ifp->if_u1.if_data = NULL;
     536   121839258 :                 break;
     537   698131255 :         case XFS_DINODE_FMT_EXTENTS:
     538             :         case XFS_DINODE_FMT_BTREE:
     539   698131255 :                 if (ifp->if_height)
     540   128478376 :                         xfs_iext_destroy(ifp);
     541             :                 break;
     542             :         }
     543   819962848 : }
     544             : 
     545             : /*
     546             :  * Convert in-core extents to on-disk form
     547             :  *
     548             :  * In the case of the data fork, the in-core and on-disk fork sizes can be
     549             :  * different due to delayed allocation extents. We only copy on-disk extents
     550             :  * here, so callers must always use the physical fork size to determine the
     551             :  * size of the buffer passed to this routine.  We will return the size actually
     552             :  * used.
     553             :  */
     554             : int
     555   498277719 : xfs_iextents_copy(
     556             :         struct xfs_inode        *ip,
     557             :         struct xfs_bmbt_rec     *dp,
     558             :         int                     whichfork)
     559             : {
     560   498277719 :         int                     state = xfs_bmap_fork_to_state(whichfork);
     561   498277719 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     562   498124534 :         struct xfs_iext_cursor  icur;
     563   498124534 :         struct xfs_bmbt_irec    rec;
     564   498124534 :         int64_t                 copied = 0;
     565             : 
     566   498124534 :         ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL | XFS_ILOCK_SHARED));
     567   498161245 :         ASSERT(ifp->if_bytes > 0);
     568             : 
     569  3545642388 :         for_each_xfs_iext(ifp, &icur, &rec) {
     570  3047549223 :                 if (isnullstartblock(rec.br_startblock))
     571    51830772 :                         continue;
     572  2995718451 :                 ASSERT(xfs_bmap_validate_extent(ip, whichfork, &rec) == NULL);
     573  2995672366 :                 xfs_bmbt_disk_set_all(dp, &rec);
     574  2995641761 :                 trace_xfs_write_extent(ip, &icur, state, _RET_IP_);
     575  2995650371 :                 copied += sizeof(struct xfs_bmbt_rec);
     576  2995650371 :                 dp++;
     577             :         }
     578             : 
     579   498194247 :         ASSERT(copied > 0);
     580   498194247 :         ASSERT(copied <= ifp->if_bytes);
     581   498194247 :         return copied;
     582             : }
     583             : 
     584             : /*
     585             :  * Each of the following cases stores data into the same region
     586             :  * of the on-disk inode, so only one of them can be valid at
     587             :  * any given time. While it is possible to have conflicting formats
     588             :  * and log flags, e.g. having XFS_ILOG_?DATA set when the fork is
     589             :  * in EXTENTS format, this can only happen when the fork has
     590             :  * changed formats after being modified but before being flushed.
     591             :  * In these cases, the format always takes precedence, because the
     592             :  * format indicates the current state of the fork.
     593             :  */
     594             : void
     595   222245326 : xfs_iflush_fork(
     596             :         struct xfs_inode        *ip,
     597             :         struct xfs_dinode       *dip,
     598             :         struct xfs_inode_log_item *iip,
     599             :         int                     whichfork)
     600             : {
     601   222245326 :         char                    *cp;
     602   222245326 :         struct xfs_ifork        *ifp;
     603   222245326 :         xfs_mount_t             *mp;
     604   222245326 :         static const short      brootflag[2] =
     605             :                 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
     606   222245326 :         static const short      dataflag[2] =
     607             :                 { XFS_ILOG_DDATA, XFS_ILOG_ADATA };
     608   222245326 :         static const short      extflag[2] =
     609             :                 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
     610             : 
     611   222245326 :         if (!iip)
     612             :                 return;
     613   222245326 :         ifp = xfs_ifork_ptr(ip, whichfork);
     614             :         /*
     615             :          * This can happen if we gave up in iformat in an error path,
     616             :          * for the attribute fork.
     617             :          */
     618   222245326 :         if (!ifp) {
     619           0 :                 ASSERT(whichfork == XFS_ATTR_FORK);
     620           0 :                 return;
     621             :         }
     622   444489356 :         cp = XFS_DFORK_PTR(dip, whichfork);
     623   222245326 :         mp = ip->i_mount;
     624   222245326 :         switch (ifp->if_format) {
     625    64370532 :         case XFS_DINODE_FMT_LOCAL:
     626    64370532 :                 if ((iip->ili_fields & dataflag[whichfork]) &&
     627    51165980 :                     (ifp->if_bytes > 0)) {
     628    51165980 :                         ASSERT(ifp->if_u1.if_data != NULL);
     629    51165980 :                         ASSERT(ifp->if_bytes <= xfs_inode_fork_size(ip, whichfork));
     630   102331960 :                         memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
     631             :                 }
     632             :                 break;
     633             : 
     634   142042007 :         case XFS_DINODE_FMT_EXTENTS:
     635   142042007 :                 if ((iip->ili_fields & extflag[whichfork]) &&
     636    31847972 :                     (ifp->if_bytes > 0)) {
     637    31847972 :                         ASSERT(ifp->if_nextents > 0);
     638    31847972 :                         (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
     639             :                                 whichfork);
     640             :                 }
     641             :                 break;
     642             : 
     643     3873897 :         case XFS_DINODE_FMT_BTREE:
     644     3873897 :                 if ((iip->ili_fields & brootflag[whichfork]) &&
     645      621941 :                     (ifp->if_broot_bytes > 0)) {
     646      621941 :                         ASSERT(ifp->if_broot != NULL);
     647      621941 :                         ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
     648             :                                 xfs_inode_fork_size(ip, whichfork));
     649     1243882 :                         xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes,
     650             :                                 (xfs_bmdr_block_t *)cp,
     651      621941 :                                 XFS_DFORK_SIZE(dip, mp, whichfork));
     652             :                 }
     653             :                 break;
     654             : 
     655    11958890 :         case XFS_DINODE_FMT_DEV:
     656    11958890 :                 if (iip->ili_fields & XFS_ILOG_DEV) {
     657     6883891 :                         ASSERT(whichfork == XFS_DATA_FORK);
     658     6883891 :                         xfs_dinode_put_rdev(dip,
     659             :                                         linux_to_xfs_dev_t(VFS_I(ip)->i_rdev));
     660             :                 }
     661             :                 break;
     662             : 
     663           0 :         default:
     664           0 :                 ASSERT(0);
     665           0 :                 break;
     666             :         }
     667             : }
     668             : 
     669             : /* Convert bmap state flags to an inode fork. */
     670             : struct xfs_ifork *
     671  2163822195 : xfs_iext_state_to_fork(
     672             :         struct xfs_inode        *ip,
     673             :         int                     state)
     674             : {
     675  2163822195 :         if (state & BMAP_COWFORK)
     676    41878109 :                 return ip->i_cowfp;
     677  2121944086 :         else if (state & BMAP_ATTRFORK)
     678     6876090 :                 return &ip->i_af;
     679  2115067996 :         return &ip->i_df;
     680             : }
     681             : 
     682             : /*
     683             :  * Initialize an inode's copy-on-write fork.
     684             :  */
     685             : void
     686    97767897 : xfs_ifork_init_cow(
     687             :         struct xfs_inode        *ip)
     688             : {
     689    97767897 :         if (ip->i_cowfp)
     690             :                 return;
     691             : 
     692    97148155 :         ip->i_cowfp = kmem_cache_zalloc(xfs_ifork_cache,
     693             :                                        GFP_NOFS | __GFP_NOFAIL);
     694    97148279 :         ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS;
     695             : }
     696             : 
     697             : /* Verify the inline contents of the data fork of an inode. */
     698             : int
     699   112355177 : xfs_ifork_verify_local_data(
     700             :         struct xfs_inode        *ip)
     701             : {
     702   112355177 :         xfs_failaddr_t          fa = NULL;
     703             : 
     704   112355177 :         switch (VFS_I(ip)->i_mode & S_IFMT) {
     705   103235007 :         case S_IFDIR:
     706   103235007 :                 fa = xfs_dir2_sf_verify(ip);
     707   103235007 :                 break;
     708     9120170 :         case S_IFLNK:
     709     9120170 :                 fa = xfs_symlink_shortform_verify(ip);
     710     9120170 :                 break;
     711             :         default:
     712             :                 break;
     713             :         }
     714             : 
     715   112356718 :         if (fa) {
     716          22 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "data fork",
     717          22 :                                 ip->i_df.if_u1.if_data, ip->i_df.if_bytes, fa);
     718          22 :                 return -EFSCORRUPTED;
     719             :         }
     720             : 
     721             :         return 0;
     722             : }
     723             : 
     724             : /* Verify the inline contents of the attr fork of an inode. */
     725             : int
     726    64453099 : xfs_ifork_verify_local_attr(
     727             :         struct xfs_inode        *ip)
     728             : {
     729    64453099 :         struct xfs_ifork        *ifp = &ip->i_af;
     730    64453099 :         xfs_failaddr_t          fa;
     731             : 
     732    64453099 :         if (!xfs_inode_has_attr_fork(ip))
     733           0 :                 fa = __this_address;
     734             :         else
     735    64453099 :                 fa = xfs_attr_shortform_verify(ip);
     736             : 
     737    64453084 :         if (fa) {
     738           0 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "attr fork",
     739           0 :                                 ifp->if_u1.if_data, ifp->if_bytes, fa);
     740           0 :                 return -EFSCORRUPTED;
     741             :         }
     742             : 
     743             :         return 0;
     744             : }
     745             : 
     746             : int
     747   416320828 : xfs_iext_count_may_overflow(
     748             :         struct xfs_inode        *ip,
     749             :         int                     whichfork,
     750             :         int                     nr_to_add)
     751             : {
     752   416320828 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     753   416191229 :         uint64_t                max_exts;
     754   416191229 :         uint64_t                nr_exts;
     755             : 
     756   416191229 :         if (whichfork == XFS_COW_FORK)
     757             :                 return 0;
     758             : 
     759   411935940 :         max_exts = xfs_iext_max_nextents(xfs_inode_has_large_extent_counts(ip),
     760             :                                 whichfork);
     761             : 
     762   411906790 :         if (XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
     763        1823 :                 max_exts = 10;
     764             : 
     765   411859761 :         nr_exts = ifp->if_nextents + nr_to_add;
     766   411859761 :         if (nr_exts < ifp->if_nextents || nr_exts > max_exts)
     767         255 :                 return -EFBIG;
     768             : 
     769             :         return 0;
     770             : }
     771             : 
     772             : /*
     773             :  * Upgrade this inode's extent counter fields to be able to handle a potential
     774             :  * increase in the extent count by nr_to_add.  Normally this is the same
     775             :  * quantity that caused xfs_iext_count_may_overflow() to return -EFBIG.
     776             :  */
     777             : int
     778         255 : xfs_iext_count_upgrade(
     779             :         struct xfs_trans        *tp,
     780             :         struct xfs_inode        *ip,
     781             :         uint                    nr_to_add)
     782             : {
     783         255 :         ASSERT(nr_to_add <= XFS_MAX_EXTCNT_UPGRADE_NR);
     784             : 
     785         255 :         if (!xfs_has_large_extent_counts(ip->i_mount) ||
     786           0 :             xfs_inode_has_large_extent_counts(ip) ||
     787           0 :             XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
     788         255 :                 return -EFBIG;
     789             : 
     790           0 :         ip->i_diflags2 |= XFS_DIFLAG2_NREXT64;
     791           0 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     792             : 
     793           0 :         return 0;
     794             : }

Generated by: LCOV version 1.14