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

Generated by: LCOV version 1.14