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-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 294 342 86.0 %
Date: 2023-07-31 20:08:07 Functions: 21 21 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   506225183 : xfs_init_local_fork(
      35             :         struct xfs_inode        *ip,
      36             :         int                     whichfork,
      37             :         const void              *data,
      38             :         int64_t                 size)
      39             : {
      40   506225183 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
      41   506233887 :         int                     mem_size = size;
      42   506233887 :         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   506233887 :         zero_terminate = S_ISLNK(VFS_I(ip)->i_mode);
      51   506233887 :         if (zero_terminate)
      52    38262002 :                 mem_size++;
      53             : 
      54   506233887 :         if (size) {
      55   506233887 :                 ifp->if_u1.if_data = kmem_alloc(mem_size, KM_NOFS);
      56  1012483346 :                 memcpy(ifp->if_u1.if_data, data, size);
      57   506241673 :                 if (zero_terminate)
      58    38261995 :                         ifp->if_u1.if_data[size] = '\0';
      59             :         } else {
      60           0 :                 ifp->if_u1.if_data = NULL;
      61             :         }
      62             : 
      63   506241673 :         ifp->if_bytes = size;
      64   506241673 : }
      65             : 
      66             : /*
      67             :  * The file is in-lined in the on-disk inode.
      68             :  */
      69             : STATIC int
      70   499036415 : 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   499036461 :         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   998075586 :         xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
      94   499036415 :         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   169596715 : xfs_iformat_extents(
     103             :         struct xfs_inode        *ip,
     104             :         struct xfs_dinode       *dip,
     105             :         int                     whichfork)
     106             : {
     107   169596715 :         struct xfs_mount        *mp = ip->i_mount;
     108   169596715 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     109   169597781 :         int                     state = xfs_bmap_fork_to_state(whichfork);
     110   169597781 :         xfs_extnum_t            nex = xfs_dfork_nextents(dip, whichfork);
     111   169598056 :         int                     size = nex * sizeof(xfs_bmbt_rec_t);
     112   169598056 :         struct xfs_iext_cursor  icur;
     113   169598056 :         struct xfs_bmbt_rec     *dp;
     114   169598056 :         struct xfs_bmbt_irec    new;
     115   169598056 :         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   169598166 :         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   169598056 :         ifp->if_bytes = 0;
     132   169598056 :         ifp->if_u1.if_root = NULL;
     133   169598056 :         ifp->if_height = 0;
     134   169598056 :         if (size) {
     135   235550032 :                 dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
     136             : 
     137   117775393 :                 xfs_iext_first(ifp, &icur);
     138   630305851 :                 for (i = 0; i < nex; i++, dp++) {
     139   394755232 :                         xfs_failaddr_t  fa;
     140             : 
     141   394755232 :                         xfs_bmbt_disk_get_all(dp, &new);
     142   394751932 :                         fa = xfs_bmap_validate_extent(ip, whichfork, &new);
     143   394749777 :                         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   394749777 :                         xfs_iext_insert(ip, &icur, &new, state);
     153   394750351 :                         trace_xfs_read_extent(ip, &icur, state, _THIS_IP_);
     154   394755040 :                         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    11005985 : xfs_iformat_btree(
     170             :         struct xfs_inode        *ip,
     171             :         struct xfs_dinode       *dip,
     172             :         int                     whichfork)
     173             : {
     174    11005985 :         struct xfs_mount        *mp = ip->i_mount;
     175    11005985 :         xfs_bmdr_block_t        *dfp;
     176    11005985 :         struct xfs_ifork        *ifp;
     177             :         /* REFERENCED */
     178    11005985 :         int                     nrecs;
     179    11005985 :         int                     size;
     180    11005985 :         int                     level;
     181             : 
     182    11005985 :         ifp = xfs_ifork_ptr(ip, whichfork);
     183    22011981 :         dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
     184    11005990 :         size = XFS_BMAP_BROOT_SPACE(mp, dfp);
     185    11005990 :         nrecs = be16_to_cpu(dfp->bb_numrecs);
     186    11005990 :         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    11005990 :         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    11005990 :                      ifp->if_nextents > ip->i_nblocks) ||
     200    11005990 :                      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    11005990 :         ifp->if_broot_bytes = size;
     211    11005990 :         ifp->if_broot = kmem_alloc(size, KM_NOFS);
     212    11005993 :         ASSERT(ifp->if_broot != NULL);
     213             :         /*
     214             :          * Copy and convert from the on-disk structure
     215             :          * to the in-memory structure.
     216             :          */
     217    11005993 :         xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
     218             :                          ifp->if_broot, size);
     219             : 
     220    11005990 :         ifp->if_bytes = 0;
     221    11005990 :         ifp->if_u1.if_root = NULL;
     222    11005990 :         ifp->if_height = 0;
     223    11005990 :         return 0;
     224             : }
     225             : 
     226             : int
     227   430482771 : xfs_iformat_data_fork(
     228             :         struct xfs_inode        *ip,
     229             :         struct xfs_dinode       *dip)
     230             : {
     231   430482771 :         struct inode            *inode = VFS_I(ip);
     232   430482771 :         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   430482771 :         ip->i_df.if_format = dip->di_format;
     242   430482771 :         ip->i_df.if_nextents = xfs_dfork_data_extents(dip);
     243   849959585 :         smp_store_release(&ip->i_df.if_needextents,
     244             :                            ip->i_df.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0);
     245             : 
     246   430501531 :         switch (inode->i_mode & S_IFMT) {
     247   181225588 :         case S_IFIFO:
     248             :         case S_IFCHR:
     249             :         case S_IFBLK:
     250             :         case S_IFSOCK:
     251   181225588 :                 ip->i_disk_size = 0;
     252   181225588 :                 inode->i_rdev = xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip));
     253   181225588 :                 return 0;
     254   249275943 :         case S_IFREG:
     255             :         case S_IFLNK:
     256             :         case S_IFDIR:
     257   249275943 :                 switch (ip->i_df.if_format) {
     258    70034885 :                 case XFS_DINODE_FMT_LOCAL:
     259    70034885 :                         error = xfs_iformat_local(ip, dip, XFS_DATA_FORK,
     260    70034885 :                                         be64_to_cpu(dip->di_size));
     261    70034936 :                         if (!error)
     262    70034984 :                                 error = xfs_ifork_verify_local_data(ip);
     263             :                         return error;
     264   168235101 :                 case XFS_DINODE_FMT_EXTENTS:
     265   168235101 :                         return xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
     266    11005957 :                 case XFS_DINODE_FMT_BTREE:
     267    11005957 :                         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   429007195 : xfs_dfork_attr_shortform_size(
     285             :         struct xfs_dinode               *dip)
     286             : {
     287   858014390 :         struct xfs_attr_shortform       *atp =
     288   429007195 :                 (struct xfs_attr_shortform *)XFS_DFORK_APTR(dip);
     289             : 
     290   429007195 :         return be16_to_cpu(atp->hdr.totsize);
     291             : }
     292             : 
     293             : void
     294    61497432 : 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   491858618 :         ip->i_af.if_format = format;
     307   491858618 :         ip->i_af.if_nextents = nextents;
     308   553356050 :         smp_store_release(&ip->i_af.if_needextents,
     309             :                            ip->i_af.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0);
     310    61494143 : }
     311             : 
     312             : void
     313   495232761 : xfs_ifork_zap_attr(
     314             :         struct xfs_inode        *ip)
     315             : {
     316   495232761 :         xfs_idestroy_fork(&ip->i_af);
     317   495724426 :         memset(&ip->i_af, 0, sizeof(struct xfs_ifork));
     318   495724426 :         ip->i_af.if_format = XFS_DINODE_FMT_EXTENTS;
     319   495724426 : }
     320             : 
     321             : int
     322   430361186 : xfs_iformat_attr_fork(
     323             :         struct xfs_inode        *ip,
     324             :         struct xfs_dinode       *dip)
     325             : {
     326   430361186 :         xfs_extnum_t            naextents = xfs_dfork_attr_extents(dip);
     327   430361186 :         int                     error = 0;
     328             : 
     329             :         /*
     330             :          * Initialize the extent count early, as the per-format routines may
     331             :          * depend on it.
     332             :          */
     333   430361186 :         xfs_ifork_init_attr(ip, dip->di_aformat, naextents);
     334             : 
     335   430370251 :         switch (ip->i_af.if_format) {
     336   429007526 :         case XFS_DINODE_FMT_LOCAL:
     337   429007526 :                 error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
     338   429007526 :                                 xfs_dfork_attr_shortform_size(dip));
     339   429008213 :                 if (!error)
     340   429010919 :                         error = xfs_ifork_verify_local_attr(ip);
     341             :                 break;
     342     1362684 :         case XFS_DINODE_FMT_EXTENTS:
     343     1362684 :                 error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
     344     1362684 :                 break;
     345          41 :         case XFS_DINODE_FMT_BTREE:
     346          41 :                 error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
     347          41 :                 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   430365481 :         if (error)
     357           0 :                 xfs_ifork_zap_attr(ip);
     358   430365481 :         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     1362693 : xfs_iroot_realloc(
     381             :         xfs_inode_t             *ip,
     382             :         int                     rec_diff,
     383             :         int                     whichfork)
     384             : {
     385     1362693 :         struct xfs_mount        *mp = ip->i_mount;
     386     1362693 :         int                     cur_max;
     387     1362693 :         struct xfs_ifork        *ifp;
     388     1362693 :         struct xfs_btree_block  *new_broot;
     389     1362693 :         int                     new_max;
     390     1362693 :         size_t                  new_size;
     391     1362693 :         char                    *np;
     392     1362693 :         char                    *op;
     393             : 
     394             :         /*
     395             :          * Handle the degenerate case quietly.
     396             :          */
     397     1362693 :         if (rec_diff == 0) {
     398             :                 return;
     399             :         }
     400             : 
     401     1362692 :         ifp = xfs_ifork_ptr(ip, whichfork);
     402     1362694 :         if (rec_diff > 0) {
     403             :                 /*
     404             :                  * If there wasn't any memory allocated before, just
     405             :                  * allocate it now and get out.
     406             :                  */
     407      889764 :                 if (ifp->if_broot_bytes == 0) {
     408      858298 :                         new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff);
     409      858298 :                         ifp->if_broot = kmem_alloc(new_size, KM_NOFS);
     410      858298 :                         ifp->if_broot_bytes = (int)new_size;
     411      858298 :                         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       31466 :                 cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
     421       31466 :                 new_max = cur_max + rec_diff;
     422       31466 :                 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
     423       31466 :                 ifp->if_broot = krealloc(ifp->if_broot, new_size,
     424             :                                          GFP_NOFS | __GFP_NOFAIL);
     425       31466 :                 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
     426             :                                                      ifp->if_broot_bytes);
     427       31466 :                 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
     428             :                                                      (int)new_size);
     429       31466 :                 ifp->if_broot_bytes = (int)new_size;
     430       31466 :                 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
     431             :                         xfs_inode_fork_size(ip, whichfork));
     432       62932 :                 memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t));
     433       31466 :                 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      472930 :         ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
     442      472930 :         cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
     443      472930 :         new_max = cur_max + rec_diff;
     444      472930 :         ASSERT(new_max >= 0);
     445      472930 :         if (new_max > 0)
     446       26251 :                 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
     447             :         else
     448             :                 new_size = 0;
     449       26251 :         if (new_size > 0) {
     450       26251 :                 new_broot = kmem_alloc(new_size, KM_NOFS);
     451             :                 /*
     452             :                  * First copy over the btree block header.
     453             :                  */
     454       52502 :                 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      472930 :         if (new_max > 0) {
     464             :                 /*
     465             :                  * First copy the records.
     466             :                  */
     467       26251 :                 op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1);
     468       26251 :                 np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1);
     469       52502 :                 memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t));
     470             : 
     471             :                 /*
     472             :                  * Then copy the pointers.
     473             :                  */
     474       26251 :                 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
     475             :                                                      ifp->if_broot_bytes);
     476       26251 :                 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1,
     477             :                                                      (int)new_size);
     478       52502 :                 memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
     479             :         }
     480      472930 :         kmem_free(ifp->if_broot);
     481      472930 :         ifp->if_broot = new_broot;
     482      472930 :         ifp->if_broot_bytes = (int)new_size;
     483      472930 :         if (ifp->if_broot)
     484       26251 :                 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   372534421 : xfs_idata_realloc(
     507             :         struct xfs_inode        *ip,
     508             :         int64_t                 byte_diff,
     509             :         int                     whichfork)
     510             : {
     511   372534421 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     512   372537321 :         int64_t                 new_size = ifp->if_bytes + byte_diff;
     513             : 
     514   372537321 :         ASSERT(new_size >= 0);
     515   372537321 :         ASSERT(new_size <= xfs_inode_fork_size(ip, whichfork));
     516             : 
     517   372537321 :         if (byte_diff == 0)
     518             :                 return;
     519             : 
     520   372537321 :         if (new_size == 0) {
     521     4578107 :                 kmem_free(ifp->if_u1.if_data);
     522     4578110 :                 ifp->if_u1.if_data = NULL;
     523     4578110 :                 ifp->if_bytes = 0;
     524     4578110 :                 return;
     525             :         }
     526             : 
     527   367959214 :         ifp->if_u1.if_data = krealloc(ifp->if_u1.if_data, new_size,
     528             :                                       GFP_NOFS | __GFP_NOFAIL);
     529   367963077 :         ifp->if_bytes = new_size;
     530             : }
     531             : 
     532             : /* Free all memory and reset a fork back to its initial state. */
     533             : void
     534   855799965 : xfs_idestroy_fork(
     535             :         struct xfs_ifork        *ifp)
     536             : {
     537   855799965 :         if (ifp->if_broot != NULL) {
     538    11422145 :                 kmem_free(ifp->if_broot);
     539    11422362 :                 ifp->if_broot = NULL;
     540             :         }
     541             : 
     542   855800182 :         switch (ifp->if_format) {
     543   561397770 :         case XFS_DINODE_FMT_LOCAL:
     544   561397770 :                 kmem_free(ifp->if_u1.if_data);
     545   562321976 :                 ifp->if_u1.if_data = NULL;
     546   562321976 :                 break;
     547   294402412 :         case XFS_DINODE_FMT_EXTENTS:
     548             :         case XFS_DINODE_FMT_BTREE:
     549   294402412 :                 if (ifp->if_height)
     550   124060215 :                         xfs_iext_destroy(ifp);
     551             :                 break;
     552             :         }
     553   856784762 : }
     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   311684282 : xfs_iextents_copy(
     566             :         struct xfs_inode        *ip,
     567             :         struct xfs_bmbt_rec     *dp,
     568             :         int                     whichfork)
     569             : {
     570   311684282 :         int                     state = xfs_bmap_fork_to_state(whichfork);
     571   311684282 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     572   311693465 :         struct xfs_iext_cursor  icur;
     573   311693465 :         struct xfs_bmbt_irec    rec;
     574   311693465 :         int64_t                 copied = 0;
     575             : 
     576   311693465 :         ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL | XFS_ILOCK_SHARED));
     577   311694745 :         ASSERT(ifp->if_bytes > 0);
     578             : 
     579  1258867483 :         for_each_xfs_iext(ifp, &icur, &rec) {
     580   947134637 :                 if (isnullstartblock(rec.br_startblock))
     581    15075519 :                         continue;
     582   932059118 :                 ASSERT(xfs_bmap_validate_extent(ip, whichfork, &rec) == NULL);
     583   932076369 :                 xfs_bmbt_disk_set_all(dp, &rec);
     584   932083072 :                 trace_xfs_write_extent(ip, &icur, state, _RET_IP_);
     585   932097219 :                 copied += sizeof(struct xfs_bmbt_rec);
     586   932097219 :                 dp++;
     587             :         }
     588             : 
     589   311693220 :         ASSERT(copied > 0);
     590   311693220 :         ASSERT(copied <= ifp->if_bytes);
     591   311693220 :         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   368274613 : 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   368274613 :         char                    *cp;
     612   368274613 :         struct xfs_ifork        *ifp;
     613   368274613 :         xfs_mount_t             *mp;
     614   368274613 :         static const short      brootflag[2] =
     615             :                 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
     616   368274613 :         static const short      dataflag[2] =
     617             :                 { XFS_ILOG_DDATA, XFS_ILOG_ADATA };
     618   368274613 :         static const short      extflag[2] =
     619             :                 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
     620             : 
     621   368274613 :         if (!iip)
     622             :                 return;
     623   368274613 :         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   368274613 :         if (!ifp) {
     629           0 :                 ASSERT(whichfork == XFS_ATTR_FORK);
     630           0 :                 return;
     631             :         }
     632   736548982 :         cp = XFS_DFORK_PTR(dip, whichfork);
     633   368274613 :         mp = ip->i_mount;
     634   368274613 :         switch (ifp->if_format) {
     635   188822211 :         case XFS_DINODE_FMT_LOCAL:
     636   188822211 :                 if ((iip->ili_fields & dataflag[whichfork]) &&
     637   117626052 :                     (ifp->if_bytes > 0)) {
     638   117626052 :                         ASSERT(ifp->if_u1.if_data != NULL);
     639   117626052 :                         ASSERT(ifp->if_bytes <= xfs_inode_fork_size(ip, whichfork));
     640   235252104 :                         memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
     641             :                 }
     642             :                 break;
     643             : 
     644   158114709 :         case XFS_DINODE_FMT_EXTENTS:
     645   158114709 :                 if ((iip->ili_fields & extflag[whichfork]) &&
     646    22920813 :                     (ifp->if_bytes > 0)) {
     647    22920813 :                         ASSERT(ifp->if_nextents > 0);
     648    22920813 :                         (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
     649             :                                 whichfork);
     650             :                 }
     651             :                 break;
     652             : 
     653     5493027 :         case XFS_DINODE_FMT_BTREE:
     654     5493027 :                 if ((iip->ili_fields & brootflag[whichfork]) &&
     655      678778 :                     (ifp->if_broot_bytes > 0)) {
     656      678778 :                         ASSERT(ifp->if_broot != NULL);
     657      678778 :                         ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
     658             :                                 xfs_inode_fork_size(ip, whichfork));
     659     1357556 :                         xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes,
     660             :                                 (xfs_bmdr_block_t *)cp,
     661      678778 :                                 XFS_DFORK_SIZE(dip, mp, whichfork));
     662             :                 }
     663             :                 break;
     664             : 
     665    15844666 :         case XFS_DINODE_FMT_DEV:
     666    15844666 :                 if (iip->ili_fields & XFS_ILOG_DEV) {
     667     7353198 :                         ASSERT(whichfork == XFS_DATA_FORK);
     668     7353198 :                         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  1656472357 : xfs_iext_state_to_fork(
     682             :         struct xfs_inode        *ip,
     683             :         int                     state)
     684             : {
     685  1656472357 :         if (state & BMAP_COWFORK)
     686     5969122 :                 return ip->i_cowfp;
     687  1650503235 :         else if (state & BMAP_ATTRFORK)
     688     8979720 :                 return &ip->i_af;
     689  1641523515 :         return &ip->i_df;
     690             : }
     691             : 
     692             : /*
     693             :  * Initialize an inode's copy-on-write fork.
     694             :  */
     695             : void
     696    97643670 : xfs_ifork_init_cow(
     697             :         struct xfs_inode        *ip)
     698             : {
     699    97643670 :         if (ip->i_cowfp)
     700             :                 return;
     701             : 
     702    96881222 :         ip->i_cowfp = kmem_cache_zalloc(xfs_ifork_cache,
     703             :                                        GFP_NOFS | __GFP_NOFAIL);
     704    96881500 :         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   120107834 : xfs_ifork_verify_local_data(
     710             :         struct xfs_inode        *ip)
     711             : {
     712   120107834 :         xfs_failaddr_t          fa = NULL;
     713             : 
     714   120107834 :         switch (VFS_I(ip)->i_mode & S_IFMT) {
     715   113950151 :         case S_IFDIR:
     716   113950151 :                 fa = xfs_dir2_sf_verify(ip);
     717   113950151 :                 break;
     718     6157683 :         case S_IFLNK:
     719     6157683 :                 fa = xfs_symlink_shortform_verify(ip);
     720     6157683 :                 break;
     721             :         default:
     722             :                 break;
     723             :         }
     724             : 
     725   120108597 :         if (fa) {
     726           4 :                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "data fork",
     727           4 :                                 ip->i_df.if_u1.if_data, ip->i_df.if_bytes, fa);
     728           4 :                 return -EFSCORRUPTED;
     729             :         }
     730             : 
     731             :         return 0;
     732             : }
     733             : 
     734             : /* Verify the inline contents of the attr fork of an inode. */
     735             : int
     736   567728552 : xfs_ifork_verify_local_attr(
     737             :         struct xfs_inode        *ip)
     738             : {
     739   567728552 :         struct xfs_ifork        *ifp = &ip->i_af;
     740   567728552 :         xfs_failaddr_t          fa;
     741             : 
     742   567728552 :         if (!xfs_inode_has_attr_fork(ip))
     743           0 :                 fa = __this_address;
     744             :         else
     745   567728552 :                 fa = xfs_attr_shortform_verify(ip);
     746             : 
     747   567715762 :         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   295337638 : xfs_iext_count_may_overflow(
     758             :         struct xfs_inode        *ip,
     759             :         int                     whichfork,
     760             :         int                     nr_to_add)
     761             : {
     762   295337638 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     763   295350807 :         uint64_t                max_exts;
     764   295350807 :         uint64_t                nr_exts;
     765             : 
     766   295350807 :         if (whichfork == XFS_COW_FORK)
     767             :                 return 0;
     768             : 
     769   295100298 :         max_exts = xfs_iext_max_nextents(xfs_inode_has_large_extent_counts(ip),
     770             :                                 whichfork);
     771             : 
     772   295106063 :         if (XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
     773         421 :                 max_exts = 10;
     774             : 
     775   295111546 :         nr_exts = ifp->if_nextents + nr_to_add;
     776   295111546 :         if (nr_exts < ifp->if_nextents || nr_exts > max_exts)
     777          56 :                 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          56 : xfs_iext_count_upgrade(
     789             :         struct xfs_trans        *tp,
     790             :         struct xfs_inode        *ip,
     791             :         uint                    nr_to_add)
     792             : {
     793          56 :         ASSERT(nr_to_add <= XFS_MAX_EXTCNT_UPGRADE_NR);
     794             : 
     795          56 :         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          56 :                 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   562183964 : xfs_ifork_is_realtime(
     809             :         struct xfs_inode        *ip,
     810             :         int                     whichfork)
     811             : {
     812   562183964 :         return XFS_IS_REALTIME_INODE(ip) && whichfork != XFS_ATTR_FORK;
     813             : }

Generated by: LCOV version 1.14