LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_dir2_data.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 468 550 85.1 %
Date: 2023-07-31 20:08:12 Functions: 27 27 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
       4             :  * Copyright (c) 2013 Red Hat, Inc.
       5             :  * All Rights Reserved.
       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_dir2.h"
      16             : #include "xfs_dir2_priv.h"
      17             : #include "xfs_error.h"
      18             : #include "xfs_trans.h"
      19             : #include "xfs_buf_item.h"
      20             : #include "xfs_log.h"
      21             : #include "xfs_health.h"
      22             : 
      23             : static xfs_failaddr_t xfs_dir2_data_freefind_verify(
      24             :                 struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf,
      25             :                 struct xfs_dir2_data_unused *dup,
      26             :                 struct xfs_dir2_data_free **bf_ent);
      27             : 
      28             : struct xfs_dir2_data_free *
      29   119919488 : xfs_dir2_data_bestfree_p(
      30             :         struct xfs_mount                *mp,
      31             :         struct xfs_dir2_data_hdr        *hdr)
      32             : {
      33   119919488 :         if (xfs_has_crc(mp))
      34   885873094 :                 return ((struct xfs_dir3_data_hdr *)hdr)->best_free;
      35        6592 :         return hdr->bestfree;
      36             : }
      37             : 
      38             : /*
      39             :  * Pointer to an entry's tag word.
      40             :  */
      41             : __be16 *
      42 89185912567 : xfs_dir2_data_entry_tag_p(
      43             :         struct xfs_mount                *mp,
      44             :         struct xfs_dir2_data_entry      *dep)
      45             : {
      46 >17837*10^7 :         return (__be16 *)((char *)dep +
      47 89185912567 :                 xfs_dir2_data_entsize(mp, dep->namelen) - sizeof(__be16));
      48             : }
      49             : 
      50             : uint8_t
      51 47553203347 : xfs_dir2_data_get_ftype(
      52             :         struct xfs_mount                *mp,
      53             :         struct xfs_dir2_data_entry      *dep)
      54             : {
      55 47553203347 :         if (xfs_has_ftype(mp)) {
      56 >13360*10^7 :                 uint8_t                 ftype = dep->name[dep->namelen];
      57             : 
      58 >13360*10^7 :                 if (likely(ftype < XFS_DIR3_FT_MAX))
      59 47559070412 :                         return ftype;
      60             :         }
      61             : 
      62             :         return XFS_DIR3_FT_UNKNOWN;
      63             : }
      64             : 
      65             : void
      66    75601365 : xfs_dir2_data_put_ftype(
      67             :         struct xfs_mount                *mp,
      68             :         struct xfs_dir2_data_entry      *dep,
      69             :         uint8_t                         ftype)
      70             : {
      71    75601365 :         ASSERT(ftype < XFS_DIR3_FT_MAX);
      72    75601365 :         ASSERT(dep->namelen != 0);
      73             : 
      74    75601365 :         if (xfs_has_ftype(mp))
      75    75603157 :                 dep->name[dep->namelen] = ftype;
      76    75601365 : }
      77             : 
      78             : /*
      79             :  * The number of leaf entries is limited by the size of the block and the amount
      80             :  * of space used by the data entries.  We don't know how much space is used by
      81             :  * the data entries yet, so just ensure that the count falls somewhere inside
      82             :  * the block right now.
      83             :  */
      84             : static inline unsigned int
      85             : xfs_dir2_data_max_leaf_entries(
      86             :         struct xfs_da_geometry          *geo)
      87             : {
      88    75698638 :         return (geo->blksize - sizeof(struct xfs_dir2_block_tail) -
      89    75698638 :                 geo->data_entry_offset) /
      90             :                         sizeof(struct xfs_dir2_leaf_entry);
      91             : }
      92             : 
      93             : /*
      94             :  * Check the consistency of the data block.
      95             :  * The input can also be a block-format directory.
      96             :  * Return NULL if the buffer is good, otherwise the address of the error.
      97             :  */
      98             : xfs_failaddr_t
      99   615612779 : __xfs_dir3_data_check(
     100             :         struct xfs_inode        *dp,            /* incore inode pointer */
     101             :         struct xfs_buf          *bp)            /* data block's buffer */
     102             : {
     103   615612779 :         xfs_dir2_dataptr_t      addr;           /* addr for leaf lookup */
     104   615612779 :         xfs_dir2_data_free_t    *bf;            /* bestfree table */
     105   615612779 :         xfs_dir2_block_tail_t   *btp=NULL;      /* block tail */
     106   615612779 :         int                     count;          /* count of entries found */
     107   615612779 :         xfs_dir2_data_hdr_t     *hdr;           /* data block header */
     108   615612779 :         xfs_dir2_data_free_t    *dfp;           /* bestfree entry */
     109   615612779 :         int                     freeseen;       /* mask of bestfrees seen */
     110   615612779 :         xfs_dahash_t            hash;           /* hash of current name */
     111   615612779 :         int                     i;              /* leaf index */
     112   615612779 :         int                     lastfree;       /* last entry was unused */
     113   615612779 :         xfs_dir2_leaf_entry_t   *lep=NULL;      /* block leaf entries */
     114   615612779 :         struct xfs_mount        *mp = bp->b_mount;
     115   615612779 :         int                     stale;          /* count of stale leaves */
     116   615612779 :         struct xfs_name         name;
     117   615612779 :         unsigned int            offset;
     118   615612779 :         unsigned int            end;
     119   615612779 :         struct xfs_da_geometry  *geo = mp->m_dir_geo;
     120             : 
     121             :         /*
     122             :          * If this isn't a directory, something is seriously wrong.  Bail out.
     123             :          */
     124   615612779 :         if (dp && !S_ISDIR(VFS_I(dp)->i_mode))
     125           0 :                 return __this_address;
     126             : 
     127   615612779 :         hdr = bp->b_addr;
     128   615612779 :         offset = geo->data_entry_offset;
     129             : 
     130   615612779 :         switch (hdr->magic) {
     131             :         case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
     132             :         case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
     133    75698638 :                 btp = xfs_dir2_block_tail_p(geo, hdr);
     134    75698638 :                 lep = xfs_dir2_block_leaf_p(btp);
     135             : 
     136    75698638 :                 if (be32_to_cpu(btp->count) >=
     137             :                     xfs_dir2_data_max_leaf_entries(geo))
     138           0 :                         return __this_address;
     139             :                 break;
     140             :         case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
     141             :         case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
     142             :                 break;
     143             :         default:
     144           0 :                 return __this_address;
     145             :         }
     146   615612779 :         end = xfs_dir3_data_end_offset(geo, hdr);
     147   615612779 :         if (!end)
     148           0 :                 return __this_address;
     149             : 
     150             :         /*
     151             :          * Account for zero bestfree entries.
     152             :          */
     153   615612779 :         bf = xfs_dir2_data_bestfree_p(mp, hdr);
     154   615612779 :         count = lastfree = freeseen = 0;
     155   615612779 :         if (!bf[0].length) {
     156   178140465 :                 if (bf[0].offset)
     157           0 :                         return __this_address;
     158             :                 freeseen |= 1 << 0;
     159             :         }
     160   615612779 :         if (!bf[1].length) {
     161   297831848 :                 if (bf[1].offset)
     162           0 :                         return __this_address;
     163   297831848 :                 freeseen |= 1 << 1;
     164             :         }
     165   615612779 :         if (!bf[2].length) {
     166   343375626 :                 if (bf[2].offset)
     167           0 :                         return __this_address;
     168   343375626 :                 freeseen |= 1 << 2;
     169             :         }
     170             : 
     171   615612779 :         if (be16_to_cpu(bf[0].length) < be16_to_cpu(bf[1].length))
     172           0 :                 return __this_address;
     173   615612779 :         if (be16_to_cpu(bf[1].length) < be16_to_cpu(bf[2].length))
     174           0 :                 return __this_address;
     175             :         /*
     176             :          * Loop over the data/unused entries.
     177             :          */
     178 92524102642 :         while (offset < end) {
     179 91907216793 :                 struct xfs_dir2_data_unused     *dup = bp->b_addr + offset;
     180 91907216793 :                 struct xfs_dir2_data_entry      *dep = bp->b_addr + offset;
     181             : 
     182             :                 /*
     183             :                  * If it's unused, look for the space in the bestfree table.
     184             :                  * If we find it, account for that, else make sure it
     185             :                  * doesn't need to be there.
     186             :                  */
     187 91907216793 :                 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
     188  5628259178 :                         xfs_failaddr_t  fa;
     189             : 
     190  5628259178 :                         if (lastfree != 0)
     191           0 :                                 return __this_address;
     192  5628259178 :                         if (offset + be16_to_cpu(dup->length) > end)
     193           0 :                                 return __this_address;
     194  5628259178 :                         if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
     195             :                             offset)
     196           0 :                                 return __this_address;
     197  5628259178 :                         fa = xfs_dir2_data_freefind_verify(hdr, bf, dup, &dfp);
     198  5644149648 :                         if (fa)
     199           0 :                                 return fa;
     200  5644149648 :                         if (dfp) {
     201  1029062209 :                                 i = (int)(dfp - bf);
     202  1029062209 :                                 if ((freeseen & (1 << i)) != 0)
     203           0 :                                         return __this_address;
     204  1029062209 :                                 freeseen |= 1 << i;
     205             :                         } else {
     206  4615087439 :                                 if (be16_to_cpu(dup->length) >
     207  4615087439 :                                     be16_to_cpu(bf[2].length))
     208           0 :                                         return __this_address;
     209             :                         }
     210  5644149648 :                         offset += be16_to_cpu(dup->length);
     211  5644149648 :                         lastfree = 1;
     212  5644149648 :                         continue;
     213             :                 }
     214             :                 /*
     215             :                  * It's a real entry.  Validate the fields.
     216             :                  * If this is a block directory then make sure it's
     217             :                  * in the leaf section of the block.
     218             :                  * The linear search is crude but this is DEBUG code.
     219             :                  */
     220 86278957615 :                 if (dep->namelen == 0)
     221           0 :                         return __this_address;
     222 86278957615 :                 if (!xfs_verify_dir_ino(mp, be64_to_cpu(dep->inumber)))
     223           0 :                         return __this_address;
     224 >17238*10^7 :                 if (offset + xfs_dir2_data_entsize(mp, dep->namelen) > end)
     225           0 :                         return __this_address;
     226 86273157175 :                 if (be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep)) != offset)
     227           0 :                         return __this_address;
     228 >17232*10^7 :                 if (xfs_dir2_data_get_ftype(mp, dep) >= XFS_DIR3_FT_MAX)
     229           0 :                         return __this_address;
     230 86273157175 :                 count++;
     231 86273157175 :                 lastfree = 0;
     232 86273157175 :                 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
     233             :                     hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
     234  2734138244 :                         addr = xfs_dir2_db_off_to_dataptr(geo, geo->datablk,
     235             :                                                 (xfs_dir2_data_aoff_t)
     236  2734138244 :                                                 ((char *)dep - (char *)hdr));
     237  2730781707 :                         name.name = dep->name;
     238  2730781707 :                         name.len = dep->namelen;
     239  2730781707 :                         hash = xfs_dir2_hashname(mp, &name);
     240 >11534*10^7 :                         for (i = 0; i < be32_to_cpu(btp->count); i++) {
     241 >11263*10^7 :                                 if (be32_to_cpu(lep[i].address) == addr &&
     242  2742284985 :                                     be32_to_cpu(lep[i].hashval) == hash)
     243             :                                         break;
     244             :                         }
     245  2725321284 :                         if (i >= be32_to_cpu(btp->count))
     246           0 :                                 return __this_address;
     247             :                 }
     248 >17243*10^7 :                 offset += xfs_dir2_data_entsize(mp, dep->namelen);
     249             :         }
     250             :         /*
     251             :          * Need to have seen all the entries and all the bestfree slots.
     252             :          */
     253   616885849 :         if (freeseen != 7)
     254           0 :                 return __this_address;
     255   616885849 :         if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
     256             :             hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
     257  3101445044 :                 for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
     258  3025692829 :                         if (lep[i].address ==
     259             :                             cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
     260   268495697 :                                 stale++;
     261  3025692829 :                         if (i > 0 && be32_to_cpu(lep[i].hashval) <
     262  2949944846 :                                      be32_to_cpu(lep[i - 1].hashval))
     263           0 :                                 return __this_address;
     264             :                 }
     265    75752215 :                 if (count != be32_to_cpu(btp->count) - be32_to_cpu(btp->stale))
     266           0 :                         return __this_address;
     267    75752215 :                 if (stale != be32_to_cpu(btp->stale))
     268           0 :                         return __this_address;
     269             :         }
     270             :         return NULL;
     271             : }
     272             : 
     273             : #ifdef DEBUG
     274             : void
     275   524729517 : xfs_dir3_data_check(
     276             :         struct xfs_inode        *dp,
     277             :         struct xfs_buf          *bp)
     278             : {
     279   524729517 :         xfs_failaddr_t          fa;
     280             : 
     281   524729517 :         fa = __xfs_dir3_data_check(dp, bp);
     282   525405340 :         if (!fa)
     283             :                 return;
     284           0 :         xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,
     285           0 :                         bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__,
     286             :                         fa);
     287           0 :         ASSERT(0);
     288             : }
     289             : #endif
     290             : 
     291             : static xfs_failaddr_t
     292    89324923 : xfs_dir3_data_verify(
     293             :         struct xfs_buf          *bp)
     294             : {
     295    89324923 :         struct xfs_mount        *mp = bp->b_mount;
     296    89324923 :         struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
     297             : 
     298    89324923 :         if (!xfs_verify_magic(bp, hdr3->magic))
     299           0 :                 return __this_address;
     300             : 
     301    89235283 :         if (xfs_has_crc(mp)) {
     302    89252544 :                 if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
     303           0 :                         return __this_address;
     304    89280639 :                 if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp))
     305           0 :                         return __this_address;
     306    89280639 :                 if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
     307           0 :                         return __this_address;
     308             :         }
     309    89328236 :         return __xfs_dir3_data_check(NULL, bp);
     310             : }
     311             : 
     312             : /*
     313             :  * Readahead of the first block of the directory when it is opened is completely
     314             :  * oblivious to the format of the directory. Hence we can either get a block
     315             :  * format buffer or a data format buffer on readahead.
     316             :  */
     317             : static void
     318      125185 : xfs_dir3_data_reada_verify(
     319             :         struct xfs_buf          *bp)
     320             : {
     321      125185 :         struct xfs_dir2_data_hdr *hdr = bp->b_addr;
     322             : 
     323      125185 :         switch (hdr->magic) {
     324       10874 :         case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
     325             :         case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
     326       10874 :                 bp->b_ops = &xfs_dir3_block_buf_ops;
     327       10874 :                 bp->b_ops->verify_read(bp);
     328       10874 :                 return;
     329      114311 :         case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
     330             :         case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
     331      114311 :                 bp->b_ops = &xfs_dir3_data_buf_ops;
     332      114311 :                 bp->b_ops->verify_read(bp);
     333      114311 :                 return;
     334             :         default:
     335           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, __this_address);
     336           0 :                 break;
     337             :         }
     338             : }
     339             : 
     340             : static void
     341      300345 : xfs_dir3_data_read_verify(
     342             :         struct xfs_buf  *bp)
     343             : {
     344      300345 :         struct xfs_mount        *mp = bp->b_mount;
     345      300345 :         xfs_failaddr_t          fa;
     346             : 
     347      600690 :         if (xfs_has_crc(mp) &&
     348             :             !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
     349          90 :                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
     350             :         else {
     351      300255 :                 fa = xfs_dir3_data_verify(bp);
     352      300255 :                 if (fa)
     353           0 :                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     354             :         }
     355      300345 : }
     356             : 
     357             : static void
     358     1070930 : xfs_dir3_data_write_verify(
     359             :         struct xfs_buf  *bp)
     360             : {
     361     1070930 :         struct xfs_mount        *mp = bp->b_mount;
     362     1070930 :         struct xfs_buf_log_item *bip = bp->b_log_item;
     363     1070930 :         struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
     364     1070930 :         xfs_failaddr_t          fa;
     365             : 
     366     1070930 :         fa = xfs_dir3_data_verify(bp);
     367     1070930 :         if (fa) {
     368           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     369           0 :                 return;
     370             :         }
     371             : 
     372     1070930 :         if (!xfs_has_crc(mp))
     373             :                 return;
     374             : 
     375     1070930 :         if (bip)
     376     1070930 :                 hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
     377             : 
     378     1070930 :         xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF);
     379             : }
     380             : 
     381             : const struct xfs_buf_ops xfs_dir3_data_buf_ops = {
     382             :         .name = "xfs_dir3_data",
     383             :         .magic = { cpu_to_be32(XFS_DIR2_DATA_MAGIC),
     384             :                    cpu_to_be32(XFS_DIR3_DATA_MAGIC) },
     385             :         .verify_read = xfs_dir3_data_read_verify,
     386             :         .verify_write = xfs_dir3_data_write_verify,
     387             :         .verify_struct = xfs_dir3_data_verify,
     388             : };
     389             : 
     390             : static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = {
     391             :         .name = "xfs_dir3_data_reada",
     392             :         .magic = { cpu_to_be32(XFS_DIR2_DATA_MAGIC),
     393             :                    cpu_to_be32(XFS_DIR3_DATA_MAGIC) },
     394             :         .verify_read = xfs_dir3_data_reada_verify,
     395             :         .verify_write = xfs_dir3_data_write_verify,
     396             : };
     397             : 
     398             : xfs_failaddr_t
     399   640893365 : xfs_dir3_data_header_check(
     400             :         struct xfs_buf          *bp,
     401             :         xfs_ino_t               owner)
     402             : {
     403   640893365 :         struct xfs_mount        *mp = bp->b_mount;
     404             : 
     405   640893365 :         if (xfs_has_crc(mp)) {
     406   640893365 :                 struct xfs_dir3_data_hdr *hdr3 = bp->b_addr;
     407             : 
     408   640893365 :                 ASSERT(hdr3->hdr.magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
     409             : 
     410   640893365 :                 if (be64_to_cpu(hdr3->hdr.owner) != owner)
     411           0 :                         return __this_address;
     412             :         }
     413             : 
     414             :         return NULL;
     415             : }
     416             : 
     417             : int
     418   640699088 : xfs_dir3_data_read(
     419             :         struct xfs_trans        *tp,
     420             :         struct xfs_inode        *dp,
     421             :         xfs_ino_t               owner,
     422             :         xfs_dablk_t             bno,
     423             :         unsigned int            flags,
     424             :         struct xfs_buf          **bpp)
     425             : {
     426   640699088 :         xfs_failaddr_t          fa;
     427   640699088 :         int                     err;
     428             : 
     429   640699088 :         err = xfs_da_read_buf(tp, dp, bno, flags, bpp, XFS_DATA_FORK,
     430             :                         &xfs_dir3_data_buf_ops);
     431   640992483 :         if (err || !*bpp)
     432             :                 return err;
     433             : 
     434             :         /* Check things that we can't do in the verifier. */
     435   640991005 :         fa = xfs_dir3_data_header_check(*bpp, owner);
     436   640684817 :         if (fa) {
     437           0 :                 __xfs_buf_mark_corrupt(*bpp, fa);
     438           0 :                 xfs_trans_brelse(tp, *bpp);
     439           0 :                 *bpp = NULL;
     440           0 :                 xfs_dirattr_mark_sick(dp, XFS_DATA_FORK);
     441           0 :                 return -EFSCORRUPTED;
     442             :         }
     443             : 
     444   640684817 :         xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_DATA_BUF);
     445   640684817 :         return err;
     446             : }
     447             : 
     448             : int
     449   213803089 : xfs_dir3_data_readahead(
     450             :         struct xfs_inode        *dp,
     451             :         xfs_dablk_t             bno,
     452             :         unsigned int            flags)
     453             : {
     454   213803089 :         return xfs_da_reada_buf(dp, bno, flags, XFS_DATA_FORK,
     455             :                                 &xfs_dir3_data_reada_buf_ops);
     456             : }
     457             : 
     458             : /*
     459             :  * Find the bestfree entry that exactly coincides with unused directory space
     460             :  * or a verifier error because the bestfree data are bad.
     461             :  */
     462             : static xfs_failaddr_t
     463  5633362656 : xfs_dir2_data_freefind_verify(
     464             :         struct xfs_dir2_data_hdr        *hdr,
     465             :         struct xfs_dir2_data_free       *bf,
     466             :         struct xfs_dir2_data_unused     *dup,
     467             :         struct xfs_dir2_data_free       **bf_ent)
     468             : {
     469  5633362656 :         struct xfs_dir2_data_free       *dfp;
     470  5633362656 :         xfs_dir2_data_aoff_t            off;
     471  5633362656 :         bool                            matched = false;
     472  5633362656 :         bool                            seenzero = false;
     473             : 
     474  5633362656 :         *bf_ent = NULL;
     475  5633362656 :         off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
     476             : 
     477             :         /*
     478             :          * Validate some consistency in the bestfree table.
     479             :          * Check order, non-overlapping entries, and if we find the
     480             :          * one we're looking for it has to be exact.
     481             :          */
     482 22533726087 :         for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
     483 16900363431 :                 if (!dfp->offset) {
     484   331471989 :                         if (dfp->length)
     485           0 :                                 return __this_address;
     486   331471989 :                         seenzero = true;
     487   331471989 :                         continue;
     488             :                 }
     489 16568891442 :                 if (seenzero)
     490           0 :                         return __this_address;
     491 16568891442 :                 if (be16_to_cpu(dfp->offset) == off) {
     492  1028978587 :                         matched = true;
     493  1028978587 :                         if (dfp->length != dup->length)
     494           0 :                                 return __this_address;
     495 15539912855 :                 } else if (be16_to_cpu(dfp->offset) > off) {
     496  4801101608 :                         if (off + be16_to_cpu(dup->length) >
     497             :                                         be16_to_cpu(dfp->offset))
     498           0 :                                 return __this_address;
     499             :                 } else {
     500 10738811247 :                         if (be16_to_cpu(dfp->offset) +
     501 10738811247 :                                         be16_to_cpu(dfp->length) > off)
     502           0 :                                 return __this_address;
     503             :                 }
     504 15539912855 :                 if (!matched &&
     505 14663398732 :                     be16_to_cpu(dfp->length) < be16_to_cpu(dup->length))
     506           0 :                         return __this_address;
     507 16568891442 :                 if (dfp > &bf[0] &&
     508 10923354923 :                     be16_to_cpu(dfp[-1].length) < be16_to_cpu(dfp[0].length))
     509           0 :                         return __this_address;
     510             :         }
     511             : 
     512             :         /* Looks ok so far; now try to match up with a bestfree entry. */
     513  5633362656 :         *bf_ent = xfs_dir2_data_freefind(hdr, bf, dup);
     514  5633362656 :         return NULL;
     515             : }
     516             : 
     517             : /*
     518             :  * Given a data block and an unused entry from that block,
     519             :  * return the bestfree entry if any that corresponds to it.
     520             :  */
     521             : xfs_dir2_data_free_t *
     522  5740093628 : xfs_dir2_data_freefind(
     523             :         struct xfs_dir2_data_hdr *hdr,          /* data block header */
     524             :         struct xfs_dir2_data_free *bf,          /* bestfree table pointer */
     525             :         struct xfs_dir2_data_unused *dup)       /* unused space */
     526             : {
     527  5740093628 :         xfs_dir2_data_free_t    *dfp;           /* bestfree entry */
     528  5740093628 :         xfs_dir2_data_aoff_t    off;            /* offset value needed */
     529             : 
     530  5740093628 :         off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
     531             : 
     532             :         /*
     533             :          * If this is smaller than the smallest bestfree entry,
     534             :          * it can't be there since they're sorted.
     535             :          */
     536  5740093628 :         if (be16_to_cpu(dup->length) <
     537  5740093628 :             be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length))
     538             :                 return NULL;
     539             :         /*
     540             :          * Look at the three bestfree entries for our guy.
     541             :          */
     542 11955805572 :         for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
     543  9475735478 :                 if (!dfp->offset)
     544             :                         return NULL;
     545  9475735478 :                 if (be16_to_cpu(dfp->offset) == off)
     546  1124055671 :                         return dfp;
     547             :         }
     548             :         /*
     549             :          * Didn't find it.  This only happens if there are duplicate lengths.
     550             :          */
     551             :         return NULL;
     552             : }
     553             : 
     554             : /*
     555             :  * Insert an unused-space entry into the bestfree table.
     556             :  */
     557             : xfs_dir2_data_free_t *                          /* entry inserted */
     558   699059588 : xfs_dir2_data_freeinsert(
     559             :         struct xfs_dir2_data_hdr *hdr,          /* data block pointer */
     560             :         struct xfs_dir2_data_free *dfp,         /* bestfree table pointer */
     561             :         struct xfs_dir2_data_unused *dup,       /* unused space */
     562             :         int                     *loghead)       /* log the data header (out) */
     563             : {
     564   699059588 :         xfs_dir2_data_free_t    new;            /* new bestfree entry */
     565             : 
     566   699059588 :         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
     567             :                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
     568             :                hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
     569             :                hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
     570             : 
     571   699059588 :         new.length = dup->length;
     572   699059588 :         new.offset = cpu_to_be16((char *)dup - (char *)hdr);
     573             : 
     574             :         /*
     575             :          * Insert at position 0, 1, or 2; or not at all.
     576             :          */
     577   699059588 :         if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) {
     578   111796006 :                 dfp[2] = dfp[1];
     579   111796006 :                 dfp[1] = dfp[0];
     580   111796006 :                 dfp[0] = new;
     581   111796006 :                 *loghead = 1;
     582   111796006 :                 return &dfp[0];
     583             :         }
     584   587263582 :         if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) {
     585    45381023 :                 dfp[2] = dfp[1];
     586    45381023 :                 dfp[1] = new;
     587    45381023 :                 *loghead = 1;
     588    45381023 :                 return &dfp[1];
     589             :         }
     590   541882559 :         if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) {
     591    43733916 :                 dfp[2] = new;
     592    43733916 :                 *loghead = 1;
     593    43733916 :                 return &dfp[2];
     594             :         }
     595             :         return NULL;
     596             : }
     597             : 
     598             : /*
     599             :  * Remove a bestfree entry from the table.
     600             :  */
     601             : STATIC void
     602    84331655 : xfs_dir2_data_freeremove(
     603             :         struct xfs_dir2_data_hdr *hdr,          /* data block header */
     604             :         struct xfs_dir2_data_free *bf,          /* bestfree table pointer */
     605             :         struct xfs_dir2_data_free *dfp,         /* bestfree entry pointer */
     606             :         int                     *loghead)       /* out: log data header */
     607             : {
     608             : 
     609    84331655 :         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
     610             :                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
     611             :                hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
     612             :                hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
     613             : 
     614             :         /*
     615             :          * It's the first entry, slide the next 2 up.
     616             :          */
     617    84331655 :         if (dfp == &bf[0]) {
     618    79275691 :                 bf[0] = bf[1];
     619    79275691 :                 bf[1] = bf[2];
     620             :         }
     621             :         /*
     622             :          * It's the second entry, slide the 3rd entry up.
     623             :          */
     624     5055964 :         else if (dfp == &bf[1])
     625     4286729 :                 bf[1] = bf[2];
     626             :         /*
     627             :          * Must be the last entry.
     628             :          */
     629             :         else
     630      769235 :                 ASSERT(dfp == &bf[2]);
     631             :         /*
     632             :          * Clear the 3rd entry, must be zero now.
     633             :          */
     634    84331655 :         bf[2].length = 0;
     635    84331655 :         bf[2].offset = 0;
     636    84331655 :         *loghead = 1;
     637    84331655 : }
     638             : 
     639             : /*
     640             :  * Given a data block, reconstruct its bestfree map.
     641             :  */
     642             : void
     643    23339562 : xfs_dir2_data_freescan(
     644             :         struct xfs_mount                *mp,
     645             :         struct xfs_dir2_data_hdr        *hdr,
     646             :         int                             *loghead)
     647             : {
     648    23339562 :         struct xfs_da_geometry          *geo = mp->m_dir_geo;
     649    23339562 :         struct xfs_dir2_data_free       *bf = xfs_dir2_data_bestfree_p(mp, hdr);
     650    23339562 :         void                            *addr = hdr;
     651    23339562 :         unsigned int                    offset = geo->data_entry_offset;
     652    23339562 :         unsigned int                    end;
     653             : 
     654    23339562 :         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
     655             :                hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
     656             :                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
     657             :                hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
     658             : 
     659             :         /*
     660             :          * Start by clearing the table.
     661             :          */
     662    23339562 :         memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT);
     663    23339562 :         *loghead = 1;
     664             : 
     665    23339562 :         end = xfs_dir3_data_end_offset(geo, addr);
     666  3471021186 :         while (offset < end) {
     667  3447653651 :                 struct xfs_dir2_data_unused     *dup = addr + offset;
     668  3447653651 :                 struct xfs_dir2_data_entry      *dep = addr + offset;
     669             : 
     670             :                 /*
     671             :                  * If it's a free entry, insert it.
     672             :                  */
     673  3447653651 :                 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
     674   599390623 :                         ASSERT(offset ==
     675             :                                be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
     676   599390623 :                         xfs_dir2_data_freeinsert(hdr, bf, dup, loghead);
     677   599418596 :                         offset += be16_to_cpu(dup->length);
     678   599418596 :                         continue;
     679             :                 }
     680             : 
     681             :                 /*
     682             :                  * For active entries, check their tags and skip them.
     683             :                  */
     684  2848263028 :                 ASSERT(offset ==
     685             :                        be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep)));
     686  5696002309 :                 offset += xfs_dir2_data_entsize(mp, dep->namelen);
     687             :         }
     688    23367535 : }
     689             : 
     690             : /*
     691             :  * Initialize a data block at the given block number in the directory.
     692             :  * Give back the buffer for the created block.
     693             :  */
     694             : int                                             /* error */
     695      714872 : xfs_dir3_data_init(
     696             :         struct xfs_da_args              *args,  /* directory operation args */
     697             :         xfs_dir2_db_t                   blkno,  /* logical dir block number */
     698             :         struct xfs_buf                  **bpp)  /* output block buffer */
     699             : {
     700      714872 :         struct xfs_trans                *tp = args->trans;
     701      714872 :         struct xfs_inode                *dp = args->dp;
     702      714872 :         struct xfs_mount                *mp = dp->i_mount;
     703      714872 :         struct xfs_da_geometry          *geo = args->geo;
     704      714872 :         struct xfs_buf                  *bp;
     705      714872 :         struct xfs_dir2_data_hdr        *hdr;
     706      714872 :         struct xfs_dir2_data_unused     *dup;
     707      714872 :         struct xfs_dir2_data_free       *bf;
     708      714872 :         int                             error;
     709      714872 :         int                             i;
     710             : 
     711             :         /*
     712             :          * Get the buffer set up for the block.
     713             :          */
     714      714872 :         error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, blkno),
     715             :                                &bp, XFS_DATA_FORK);
     716      714887 :         if (error)
     717             :                 return error;
     718      714879 :         bp->b_ops = &xfs_dir3_data_buf_ops;
     719      714879 :         xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_DATA_BUF);
     720             : 
     721             :         /*
     722             :          * Initialize the header.
     723             :          */
     724      714864 :         hdr = bp->b_addr;
     725      714864 :         if (xfs_has_crc(mp)) {
     726      714842 :                 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
     727             : 
     728      714842 :                 memset(hdr3, 0, sizeof(*hdr3));
     729      714842 :                 hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);
     730      714842 :                 hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));
     731      714842 :                 hdr3->owner = cpu_to_be64(args->owner);
     732      714842 :                 uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
     733             : 
     734             :         } else
     735          22 :                 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
     736             : 
     737      714869 :         bf = xfs_dir2_data_bestfree_p(mp, hdr);
     738      714869 :         bf[0].offset = cpu_to_be16(geo->data_entry_offset);
     739      714869 :         bf[0].length = cpu_to_be16(geo->blksize - geo->data_entry_offset);
     740     2144607 :         for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
     741     1429738 :                 bf[i].length = 0;
     742     1429738 :                 bf[i].offset = 0;
     743             :         }
     744             : 
     745             :         /*
     746             :          * Set up an unused entry for the block's body.
     747             :          */
     748      714869 :         dup = bp->b_addr + geo->data_entry_offset;
     749      714869 :         dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
     750      714869 :         dup->length = bf[0].length;
     751      714869 :         *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr);
     752             : 
     753             :         /*
     754             :          * Log it and return it.
     755             :          */
     756      714869 :         xfs_dir2_data_log_header(args, bp);
     757      714903 :         xfs_dir2_data_log_unused(args, bp, dup);
     758      714902 :         *bpp = bp;
     759      714902 :         return 0;
     760             : }
     761             : 
     762             : /*
     763             :  * Log an active data entry from the block.
     764             :  */
     765             : void
     766    75578591 : xfs_dir2_data_log_entry(
     767             :         struct xfs_da_args      *args,
     768             :         struct xfs_buf          *bp,
     769             :         xfs_dir2_data_entry_t   *dep)           /* data entry pointer */
     770             : {
     771    75578591 :         struct xfs_mount        *mp = bp->b_mount;
     772    75578591 :         struct xfs_dir2_data_hdr *hdr = bp->b_addr;
     773             : 
     774    75578591 :         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
     775             :                hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
     776             :                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
     777             :                hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
     778             : 
     779    75578591 :         xfs_trans_log_buf(args->trans, bp, (uint)((char *)dep - (char *)hdr),
     780    75578591 :                 (uint)((char *)(xfs_dir2_data_entry_tag_p(mp, dep) + 1) -
     781    75578591 :                        (char *)hdr - 1));
     782    75863899 : }
     783             : 
     784             : /*
     785             :  * Log a data block header.
     786             :  */
     787             : void
     788   105134141 : xfs_dir2_data_log_header(
     789             :         struct xfs_da_args      *args,
     790             :         struct xfs_buf          *bp)
     791             : {
     792             : #ifdef DEBUG
     793   105134141 :         struct xfs_dir2_data_hdr *hdr = bp->b_addr;
     794             : 
     795   105134141 :         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
     796             :                hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
     797             :                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
     798             :                hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
     799             : #endif
     800             : 
     801   105134141 :         xfs_trans_log_buf(args->trans, bp, 0, args->geo->data_entry_offset - 1);
     802   105366473 : }
     803             : 
     804             : /*
     805             :  * Log a data unused entry.
     806             :  */
     807             : void
     808   109675982 : xfs_dir2_data_log_unused(
     809             :         struct xfs_da_args      *args,
     810             :         struct xfs_buf          *bp,
     811             :         xfs_dir2_data_unused_t  *dup)           /* data unused pointer */
     812             : {
     813   109675982 :         xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
     814             : 
     815   109675982 :         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
     816             :                hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
     817             :                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
     818             :                hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
     819             : 
     820             :         /*
     821             :          * Log the first part of the unused entry.
     822             :          */
     823   109675982 :         xfs_trans_log_buf(args->trans, bp, (uint)((char *)dup - (char *)hdr),
     824   109675982 :                 (uint)((char *)&dup->length + sizeof(dup->length) -
     825   109675982 :                        1 - (char *)hdr));
     826             :         /*
     827             :          * Log the end (tag) of the unused entry.
     828             :          */
     829   109800876 :         xfs_trans_log_buf(args->trans, bp,
     830             :                 (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr),
     831   109800876 :                 (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr +
     832             :                        sizeof(xfs_dir2_data_off_t) - 1));
     833   109849654 : }
     834             : 
     835             : /*
     836             :  * Make a byte range in the data block unused.
     837             :  * Its current contents are unimportant.
     838             :  */
     839             : void
     840    55108627 : xfs_dir2_data_make_free(
     841             :         struct xfs_da_args      *args,
     842             :         struct xfs_buf          *bp,
     843             :         xfs_dir2_data_aoff_t    offset,         /* starting byte offset */
     844             :         xfs_dir2_data_aoff_t    len,            /* length in bytes */
     845             :         int                     *needlogp,      /* out: log header */
     846             :         int                     *needscanp)     /* out: regen bestfree */
     847             : {
     848    55108627 :         xfs_dir2_data_hdr_t     *hdr;           /* data block pointer */
     849    55108627 :         xfs_dir2_data_free_t    *dfp;           /* bestfree pointer */
     850    55108627 :         int                     needscan;       /* need to regen bestfree */
     851    55108627 :         xfs_dir2_data_unused_t  *newdup;        /* new unused entry */
     852    55108627 :         xfs_dir2_data_unused_t  *postdup;       /* unused entry after us */
     853    55108627 :         xfs_dir2_data_unused_t  *prevdup;       /* unused entry before us */
     854    55108627 :         unsigned int            end;
     855    55108627 :         struct xfs_dir2_data_free *bf;
     856             : 
     857    55108627 :         hdr = bp->b_addr;
     858             : 
     859             :         /*
     860             :          * Figure out where the end of the data area is.
     861             :          */
     862    55108627 :         end = xfs_dir3_data_end_offset(args->geo, hdr);
     863    55108627 :         ASSERT(end != 0);
     864             : 
     865             :         /*
     866             :          * If this isn't the start of the block, then back up to
     867             :          * the previous entry and see if it's free.
     868             :          */
     869    55108627 :         if (offset > args->geo->data_entry_offset) {
     870    54884354 :                 __be16                  *tagp;  /* tag just before us */
     871             : 
     872    54884354 :                 tagp = (__be16 *)((char *)hdr + offset) - 1;
     873    54884354 :                 prevdup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
     874    54884354 :                 if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
     875    27285520 :                         prevdup = NULL;
     876             :         } else
     877             :                 prevdup = NULL;
     878             :         /*
     879             :          * If this isn't the end of the block, see if the entry after
     880             :          * us is free.
     881             :          */
     882    55108627 :         if (offset + len < end) {
     883    54894048 :                 postdup =
     884    54894048 :                         (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
     885    54894048 :                 if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
     886    47157442 :                         postdup = NULL;
     887             :         } else
     888             :                 postdup = NULL;
     889    55108627 :         ASSERT(*needscanp == 0);
     890    55108627 :         needscan = 0;
     891             :         /*
     892             :          * Previous and following entries are both free,
     893             :          * merge everything into a single free entry.
     894             :          */
     895    55108627 :         bf = xfs_dir2_data_bestfree_p(args->dp->i_mount, hdr);
     896    55108627 :         if (prevdup && postdup) {
     897     3112187 :                 xfs_dir2_data_free_t    *dfp2;  /* another bestfree pointer */
     898             : 
     899             :                 /*
     900             :                  * See if prevdup and/or postdup are in bestfree table.
     901             :                  */
     902     3112187 :                 dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);
     903     3112187 :                 dfp2 = xfs_dir2_data_freefind(hdr, bf, postdup);
     904             :                 /*
     905             :                  * We need a rescan unless there are exactly 2 free entries
     906             :                  * namely our two.  Then we know what's happening, otherwise
     907             :                  * since the third bestfree is there, there might be more
     908             :                  * entries.
     909             :                  */
     910     3112187 :                 needscan = (bf[2].length != 0);
     911             :                 /*
     912             :                  * Fix up the new big freespace.
     913             :                  */
     914     3112187 :                 be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length));
     915     3112187 :                 *xfs_dir2_data_unused_tag_p(prevdup) =
     916     3112187 :                         cpu_to_be16((char *)prevdup - (char *)hdr);
     917     3112187 :                 xfs_dir2_data_log_unused(args, bp, prevdup);
     918     3112279 :                 if (!needscan) {
     919             :                         /*
     920             :                          * Has to be the case that entries 0 and 1 are
     921             :                          * dfp and dfp2 (don't know which is which), and
     922             :                          * entry 2 is empty.
     923             :                          * Remove entry 1 first then entry 0.
     924             :                          */
     925      319233 :                         ASSERT(dfp && dfp2);
     926      319233 :                         if (dfp == &bf[1]) {
     927      248287 :                                 dfp = &bf[0];
     928      248287 :                                 ASSERT(dfp2 == dfp);
     929             :                                 dfp2 = &bf[1];
     930             :                         }
     931      319233 :                         xfs_dir2_data_freeremove(hdr, bf, dfp2, needlogp);
     932      319230 :                         xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
     933             :                         /*
     934             :                          * Now insert the new entry.
     935             :                          */
     936      319230 :                         dfp = xfs_dir2_data_freeinsert(hdr, bf, prevdup,
     937             :                                                        needlogp);
     938      319232 :                         ASSERT(dfp == &bf[0]);
     939      319232 :                         ASSERT(dfp->length == prevdup->length);
     940      319232 :                         ASSERT(!dfp[1].length);
     941      319232 :                         ASSERT(!dfp[2].length);
     942             :                 }
     943             :         }
     944             :         /*
     945             :          * The entry before us is free, merge with it.
     946             :          */
     947    51996440 :         else if (prevdup) {
     948    24486246 :                 dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);
     949    24486246 :                 be16_add_cpu(&prevdup->length, len);
     950    24486246 :                 *xfs_dir2_data_unused_tag_p(prevdup) =
     951    24486246 :                         cpu_to_be16((char *)prevdup - (char *)hdr);
     952    24486246 :                 xfs_dir2_data_log_unused(args, bp, prevdup);
     953             :                 /*
     954             :                  * If the previous entry was in the table, the new entry
     955             :                  * is longer, so it will be in the table too.  Remove
     956             :                  * the old one and add the new one.
     957             :                  */
     958    24490411 :                 if (dfp) {
     959    21414911 :                         xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
     960    21410941 :                         xfs_dir2_data_freeinsert(hdr, bf, prevdup, needlogp);
     961             :                 }
     962             :                 /*
     963             :                  * Otherwise we need a scan if the new entry is big enough.
     964             :                  */
     965             :                 else {
     966     3075500 :                         needscan = be16_to_cpu(prevdup->length) >
     967     3075500 :                                    be16_to_cpu(bf[2].length);
     968             :                 }
     969             :         }
     970             :         /*
     971             :          * The following entry is free, merge with it.
     972             :          */
     973    27510194 :         else if (postdup) {
     974     4624781 :                 dfp = xfs_dir2_data_freefind(hdr, bf, postdup);
     975     4624781 :                 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
     976     4624781 :                 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
     977     4624781 :                 newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
     978     4624781 :                 *xfs_dir2_data_unused_tag_p(newdup) =
     979     4624781 :                         cpu_to_be16((char *)newdup - (char *)hdr);
     980     4624781 :                 xfs_dir2_data_log_unused(args, bp, newdup);
     981             :                 /*
     982             :                  * If the following entry was in the table, the new entry
     983             :                  * is longer, so it will be in the table too.  Remove
     984             :                  * the old one and add the new one.
     985             :                  */
     986     4625164 :                 if (dfp) {
     987     1045658 :                         xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
     988     1045641 :                         xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);
     989             :                 }
     990             :                 /*
     991             :                  * Otherwise we need a scan if the new entry is big enough.
     992             :                  */
     993             :                 else {
     994     3579506 :                         needscan = be16_to_cpu(newdup->length) >
     995     3579506 :                                    be16_to_cpu(bf[2].length);
     996             :                 }
     997             :         }
     998             :         /*
     999             :          * Neither neighbor is free.  Make a new entry.
    1000             :          */
    1001             :         else {
    1002    22885413 :                 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
    1003    22885413 :                 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    1004    22885413 :                 newdup->length = cpu_to_be16(len);
    1005    22885413 :                 *xfs_dir2_data_unused_tag_p(newdup) =
    1006    22885413 :                         cpu_to_be16((char *)newdup - (char *)hdr);
    1007    22885413 :                 xfs_dir2_data_log_unused(args, bp, newdup);
    1008    22918005 :                 xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);
    1009             :         }
    1010    55123852 :         *needscanp = needscan;
    1011    55123852 : }
    1012             : 
    1013             : /* Check our free data for obvious signs of corruption. */
    1014             : static inline xfs_failaddr_t
    1015    70916985 : xfs_dir2_data_check_free(
    1016             :         struct xfs_dir2_data_hdr        *hdr,
    1017             :         struct xfs_dir2_data_unused     *dup,
    1018             :         xfs_dir2_data_aoff_t            offset,
    1019             :         xfs_dir2_data_aoff_t            len)
    1020             : {
    1021    70916985 :         if (hdr->magic != cpu_to_be32(XFS_DIR2_DATA_MAGIC) &&
    1022    13755998 :             hdr->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC) &&
    1023    13754062 :             hdr->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) &&
    1024             :             hdr->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC))
    1025           0 :                 return __this_address;
    1026    70916985 :         if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG)
    1027           0 :                 return __this_address;
    1028    70916985 :         if (offset < (char *)dup - (char *)hdr)
    1029           0 :                 return __this_address;
    1030    70916985 :         if (offset + len > (char *)dup + be16_to_cpu(dup->length) - (char *)hdr)
    1031           0 :                 return __this_address;
    1032    70916985 :         if ((char *)dup - (char *)hdr !=
    1033    70916985 :                         be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)))
    1034           0 :                 return __this_address;
    1035             :         return NULL;
    1036             : }
    1037             : 
    1038             : /* Sanity-check a new bestfree entry. */
    1039             : static inline xfs_failaddr_t
    1040    51161301 : xfs_dir2_data_check_new_free(
    1041             :         struct xfs_dir2_data_hdr        *hdr,
    1042             :         struct xfs_dir2_data_free       *dfp,
    1043             :         struct xfs_dir2_data_unused     *newdup)
    1044             : {
    1045    51161301 :         if (dfp == NULL)
    1046           0 :                 return __this_address;
    1047    51161301 :         if (dfp->length != newdup->length)
    1048           0 :                 return __this_address;
    1049    51161301 :         if (be16_to_cpu(dfp->offset) != (char *)newdup - (char *)hdr)
    1050           0 :                 return __this_address;
    1051             :         return NULL;
    1052             : }
    1053             : 
    1054             : /*
    1055             :  * Take a byte range out of an existing unused space and make it un-free.
    1056             :  */
    1057             : int
    1058    70918885 : xfs_dir2_data_use_free(
    1059             :         struct xfs_da_args      *args,
    1060             :         struct xfs_buf          *bp,
    1061             :         xfs_dir2_data_unused_t  *dup,           /* unused entry */
    1062             :         xfs_dir2_data_aoff_t    offset,         /* starting offset to use */
    1063             :         xfs_dir2_data_aoff_t    len,            /* length to use */
    1064             :         int                     *needlogp,      /* out: need to log header */
    1065             :         int                     *needscanp)     /* out: need regen bestfree */
    1066             : {
    1067    70918885 :         xfs_dir2_data_hdr_t     *hdr;           /* data block header */
    1068    70918885 :         xfs_dir2_data_free_t    *dfp;           /* bestfree pointer */
    1069    70918885 :         xfs_dir2_data_unused_t  *newdup;        /* new unused entry */
    1070    70918885 :         xfs_dir2_data_unused_t  *newdup2;       /* another new unused entry */
    1071    70918885 :         struct xfs_dir2_data_free *bf;
    1072    70918885 :         xfs_failaddr_t          fa;
    1073    70918885 :         int                     matchback;      /* matches end of freespace */
    1074    70918885 :         int                     matchfront;     /* matches start of freespace */
    1075    70918885 :         int                     needscan;       /* need to regen bestfree */
    1076    70918885 :         int                     oldlen;         /* old unused entry's length */
    1077             : 
    1078    70918885 :         hdr = bp->b_addr;
    1079    70918885 :         fa = xfs_dir2_data_check_free(hdr, dup, offset, len);
    1080    70866212 :         if (fa)
    1081           0 :                 goto corrupt;
    1082             :         /*
    1083             :          * Look up the entry in the bestfree table.
    1084             :          */
    1085    70866212 :         oldlen = be16_to_cpu(dup->length);
    1086    70866212 :         bf = xfs_dir2_data_bestfree_p(args->dp->i_mount, hdr);
    1087    70866212 :         dfp = xfs_dir2_data_freefind(hdr, bf, dup);
    1088    70866212 :         ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length));
    1089             :         /*
    1090             :          * Check for alignment with front and back of the entry.
    1091             :          */
    1092    70866212 :         matchfront = (char *)dup - (char *)hdr == offset;
    1093    70866212 :         matchback = (char *)dup + oldlen - (char *)hdr == offset + len;
    1094    70866212 :         ASSERT(*needscanp == 0);
    1095    70866212 :         needscan = 0;
    1096             :         /*
    1097             :          * If we matched it exactly we just need to get rid of it from
    1098             :          * the bestfree table.
    1099             :          */
    1100    70866212 :         if (matchfront && matchback) {
    1101    19489018 :                 if (dfp) {
    1102    19485742 :                         needscan = (bf[2].offset != 0);
    1103    19485742 :                         if (!needscan)
    1104     9910983 :                                 xfs_dir2_data_freeremove(hdr, bf, dfp,
    1105             :                                                          needlogp);
    1106             :                 }
    1107             :         }
    1108             :         /*
    1109             :          * We match the first part of the entry.
    1110             :          * Make a new entry with the remaining freespace.
    1111             :          */
    1112    51377194 :         else if (matchfront) {
    1113    45686204 :                 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
    1114    45686204 :                 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    1115    45686204 :                 newdup->length = cpu_to_be16(oldlen - len);
    1116    45686204 :                 *xfs_dir2_data_unused_tag_p(newdup) =
    1117    45686204 :                         cpu_to_be16((char *)newdup - (char *)hdr);
    1118    45686204 :                 xfs_dir2_data_log_unused(args, bp, newdup);
    1119             :                 /*
    1120             :                  * If it was in the table, remove it and add the new one.
    1121             :                  */
    1122    45835280 :                 if (dfp) {
    1123    45834548 :                         xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
    1124    45574298 :                         dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,
    1125             :                                                        needlogp);
    1126    45600498 :                         fa = xfs_dir2_data_check_new_free(hdr, dfp, newdup);
    1127    45467059 :                         if (fa)
    1128           0 :                                 goto corrupt;
    1129             :                         /*
    1130             :                          * If we got inserted at the last slot,
    1131             :                          * that means we don't know if there was a better
    1132             :                          * choice for the last slot, or not.  Rescan.
    1133             :                          */
    1134    45467059 :                         needscan = dfp == &bf[2];
    1135             :                 }
    1136             :         }
    1137             :         /*
    1138             :          * We match the last part of the entry.
    1139             :          * Trim the allocated space off the tail of the entry.
    1140             :          */
    1141     5690990 :         else if (matchback) {
    1142     5690990 :                 newdup = dup;
    1143     5690990 :                 newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
    1144     5690990 :                 *xfs_dir2_data_unused_tag_p(newdup) =
    1145     5690990 :                         cpu_to_be16((char *)newdup - (char *)hdr);
    1146     5690990 :                 xfs_dir2_data_log_unused(args, bp, newdup);
    1147             :                 /*
    1148             :                  * If it was in the table, remove it and add the new one.
    1149             :                  */
    1150     5695646 :                 if (dfp) {
    1151     5654226 :                         xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
    1152     5644105 :                         dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,
    1153             :                                                        needlogp);
    1154     5645385 :                         fa = xfs_dir2_data_check_new_free(hdr, dfp, newdup);
    1155     5643070 :                         if (fa)
    1156           0 :                                 goto corrupt;
    1157             :                         /*
    1158             :                          * If we got inserted at the last slot,
    1159             :                          * that means we don't know if there was a better
    1160             :                          * choice for the last slot, or not.  Rescan.
    1161             :                          */
    1162     5643070 :                         needscan = dfp == &bf[2];
    1163             :                 }
    1164             :         }
    1165             :         /*
    1166             :          * Poking out the middle of an entry.
    1167             :          * Make two new entries.
    1168             :          */
    1169             :         else {
    1170           0 :                 newdup = dup;
    1171           0 :                 newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
    1172           0 :                 *xfs_dir2_data_unused_tag_p(newdup) =
    1173           0 :                         cpu_to_be16((char *)newdup - (char *)hdr);
    1174           0 :                 xfs_dir2_data_log_unused(args, bp, newdup);
    1175           0 :                 newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
    1176           0 :                 newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    1177           0 :                 newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
    1178           0 :                 *xfs_dir2_data_unused_tag_p(newdup2) =
    1179           0 :                         cpu_to_be16((char *)newdup2 - (char *)hdr);
    1180           0 :                 xfs_dir2_data_log_unused(args, bp, newdup2);
    1181             :                 /*
    1182             :                  * If the old entry was in the table, we need to scan
    1183             :                  * if the 3rd entry was valid, since these entries
    1184             :                  * are smaller than the old one.
    1185             :                  * If we don't need to scan that means there were 1 or 2
    1186             :                  * entries in the table, and removing the old and adding
    1187             :                  * the 2 new will work.
    1188             :                  */
    1189           0 :                 if (dfp) {
    1190           0 :                         needscan = (bf[2].length != 0);
    1191           0 :                         if (!needscan) {
    1192           0 :                                 xfs_dir2_data_freeremove(hdr, bf, dfp,
    1193             :                                                          needlogp);
    1194           0 :                                 xfs_dir2_data_freeinsert(hdr, bf, newdup,
    1195             :                                                          needlogp);
    1196           0 :                                 xfs_dir2_data_freeinsert(hdr, bf, newdup2,
    1197             :                                                          needlogp);
    1198             :                         }
    1199             :                 }
    1200             :         }
    1201    70638115 :         *needscanp = needscan;
    1202    70638115 :         return 0;
    1203           0 : corrupt:
    1204           0 :         xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount,
    1205             :                         hdr, sizeof(*hdr), __FILE__, __LINE__, fa);
    1206           0 :         xfs_da_mark_sick(args);
    1207           0 :         return -EFSCORRUPTED;
    1208             : }
    1209             : 
    1210             : /* Find the end of the entry data in a data/block format dir block. */
    1211             : unsigned int
    1212   872123389 : xfs_dir3_data_end_offset(
    1213             :         struct xfs_da_geometry          *geo,
    1214             :         struct xfs_dir2_data_hdr        *hdr)
    1215             : {
    1216   872123389 :         void                            *p;
    1217             : 
    1218   872123389 :         switch (hdr->magic) {
    1219             :         case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
    1220             :         case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
    1221   170867130 :                 p = xfs_dir2_block_leaf_p(xfs_dir2_block_tail_p(geo, hdr));
    1222   170867130 :                 return p - (void *)hdr;
    1223   701256259 :         case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
    1224             :         case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
    1225   701256259 :                 return geo->blksize;
    1226             :         default:
    1227             :                 return 0;
    1228             :         }
    1229             : }

Generated by: LCOV version 1.14