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-rc4-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 470 550 85.5 %
Date: 2023-07-31 20:08:27 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    74037775 : xfs_dir2_data_bestfree_p(
      30             :         struct xfs_mount                *mp,
      31             :         struct xfs_dir2_data_hdr        *hdr)
      32             : {
      33    74037775 :         if (xfs_has_crc(mp))
      34   544829167 :                 return ((struct xfs_dir3_data_hdr *)hdr)->best_free;
      35       10808 :         return hdr->bestfree;
      36             : }
      37             : 
      38             : /*
      39             :  * Pointer to an entry's tag word.
      40             :  */
      41             : __be16 *
      42 55494753989 : xfs_dir2_data_entry_tag_p(
      43             :         struct xfs_mount                *mp,
      44             :         struct xfs_dir2_data_entry      *dep)
      45             : {
      46 >11098*10^7 :         return (__be16 *)((char *)dep +
      47 55494753989 :                 xfs_dir2_data_entsize(mp, dep->namelen) - sizeof(__be16));
      48             : }
      49             : 
      50             : uint8_t
      51 22784789576 : xfs_dir2_data_get_ftype(
      52             :         struct xfs_mount                *mp,
      53             :         struct xfs_dir2_data_entry      *dep)
      54             : {
      55 22784789576 :         if (xfs_has_ftype(mp)) {
      56 76314851066 :                 uint8_t                 ftype = dep->name[dep->namelen];
      57             : 
      58 76314851066 :                 if (likely(ftype < XFS_DIR3_FT_MAX))
      59 23031065606 :                         return ftype;
      60             :         }
      61             : 
      62             :         return XFS_DIR3_FT_UNKNOWN;
      63             : }
      64             : 
      65             : void
      66    46953129 : xfs_dir2_data_put_ftype(
      67             :         struct xfs_mount                *mp,
      68             :         struct xfs_dir2_data_entry      *dep,
      69             :         uint8_t                         ftype)
      70             : {
      71    46953129 :         ASSERT(ftype < XFS_DIR3_FT_MAX);
      72    46953129 :         ASSERT(dep->namelen != 0);
      73             : 
      74    46953129 :         if (xfs_has_ftype(mp))
      75    46952861 :                 dep->name[dep->namelen] = ftype;
      76    46953129 : }
      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    75030419 :         return (geo->blksize - sizeof(struct xfs_dir2_block_tail) -
      89    75030419 :                 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   375157693 : __xfs_dir3_data_check(
     100             :         struct xfs_inode        *dp,            /* incore inode pointer */
     101             :         struct xfs_buf          *bp)            /* data block's buffer */
     102             : {
     103   375157693 :         xfs_dir2_dataptr_t      addr;           /* addr for leaf lookup */
     104   375157693 :         xfs_dir2_data_free_t    *bf;            /* bestfree table */
     105   375157693 :         xfs_dir2_block_tail_t   *btp=NULL;      /* block tail */
     106   375157693 :         int                     count;          /* count of entries found */
     107   375157693 :         xfs_dir2_data_hdr_t     *hdr;           /* data block header */
     108   375157693 :         xfs_dir2_data_free_t    *dfp;           /* bestfree entry */
     109   375157693 :         int                     freeseen;       /* mask of bestfrees seen */
     110   375157693 :         xfs_dahash_t            hash;           /* hash of current name */
     111   375157693 :         int                     i;              /* leaf index */
     112   375157693 :         int                     lastfree;       /* last entry was unused */
     113   375157693 :         xfs_dir2_leaf_entry_t   *lep=NULL;      /* block leaf entries */
     114   375157693 :         struct xfs_mount        *mp = bp->b_mount;
     115   375157693 :         int                     stale;          /* count of stale leaves */
     116   375157693 :         struct xfs_name         name;
     117   375157693 :         unsigned int            offset;
     118   375157693 :         unsigned int            end;
     119   375157693 :         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   375157693 :         if (dp && !S_ISDIR(VFS_I(dp)->i_mode))
     125           0 :                 return __this_address;
     126             : 
     127   375157693 :         hdr = bp->b_addr;
     128   375157693 :         offset = geo->data_entry_offset;
     129             : 
     130   375157693 :         switch (hdr->magic) {
     131             :         case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
     132             :         case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
     133    75030419 :                 btp = xfs_dir2_block_tail_p(geo, hdr);
     134    75030419 :                 lep = xfs_dir2_block_leaf_p(btp);
     135             : 
     136   150060838 :                 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   375157693 :         end = xfs_dir3_data_end_offset(geo, hdr);
     147   375157693 :         if (!end)
     148           0 :                 return __this_address;
     149             : 
     150             :         /*
     151             :          * Account for zero bestfree entries.
     152             :          */
     153   375157693 :         bf = xfs_dir2_data_bestfree_p(mp, hdr);
     154   375157693 :         count = lastfree = freeseen = 0;
     155   375157693 :         if (!bf[0].length) {
     156    93799900 :                 if (bf[0].offset)
     157           0 :                         return __this_address;
     158             :                 freeseen |= 1 << 0;
     159             :         }
     160   375157693 :         if (!bf[1].length) {
     161   148827250 :                 if (bf[1].offset)
     162           0 :                         return __this_address;
     163   148827250 :                 freeseen |= 1 << 1;
     164             :         }
     165   375157693 :         if (!bf[2].length) {
     166   173421129 :                 if (bf[2].offset)
     167           0 :                         return __this_address;
     168   173421129 :                 freeseen |= 1 << 2;
     169             :         }
     170             : 
     171   375157693 :         if (be16_to_cpu(bf[0].length) < be16_to_cpu(bf[1].length))
     172           0 :                 return __this_address;
     173   375157693 :         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 57440680505 :         while (offset < end) {
     179 57065544722 :                 struct xfs_dir2_data_unused     *dup = bp->b_addr + offset;
     180 57065544722 :                 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 57065544722 :                 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
     188  3752853035 :                         xfs_failaddr_t  fa;
     189             : 
     190  3752853035 :                         if (lastfree != 0)
     191           0 :                                 return __this_address;
     192  3752853035 :                         if (offset + be16_to_cpu(dup->length) > end)
     193           0 :                                 return __this_address;
     194  3752853035 :                         if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
     195             :                             offset)
     196           0 :                                 return __this_address;
     197  3752853035 :                         fa = xfs_dir2_data_freefind_verify(hdr, bf, dup, &dfp);
     198  3750231946 :                         if (fa)
     199           0 :                                 return fa;
     200  3750231946 :                         if (dfp) {
     201   699844609 :                                 i = (int)(dfp - bf);
     202   699844609 :                                 if ((freeseen & (1 << i)) != 0)
     203           0 :                                         return __this_address;
     204   699844609 :                                 freeseen |= 1 << i;
     205             :                         } else {
     206  6100774674 :                                 if (be16_to_cpu(dup->length) >
     207  3050387337 :                                     be16_to_cpu(bf[2].length))
     208           0 :                                         return __this_address;
     209             :                         }
     210  3750231946 :                         offset += be16_to_cpu(dup->length);
     211  3750231946 :                         lastfree = 1;
     212  3750231946 :                         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 53312691687 :                 if (dep->namelen == 0)
     221           0 :                         return __this_address;
     222 53312691687 :                 if (!xfs_verify_dir_ino(mp, be64_to_cpu(dep->inumber)))
     223           0 :                         return __this_address;
     224 >10647*10^7 :                 if (offset + xfs_dir2_data_entsize(mp, dep->namelen) > end)
     225           0 :                         return __this_address;
     226 53312481198 :                 if (be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep)) != offset)
     227           0 :                         return __this_address;
     228 >10659*10^7 :                 if (xfs_dir2_data_get_ftype(mp, dep) >= XFS_DIR3_FT_MAX)
     229           0 :                         return __this_address;
     230 53312481198 :                 count++;
     231 53312481198 :                 lastfree = 0;
     232 53312481198 :                 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
     233             :                     hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
     234  1778311207 :                         addr = xfs_dir2_db_off_to_dataptr(geo, geo->datablk,
     235             :                                                 (xfs_dir2_data_aoff_t)
     236  1778311207 :                                                 ((char *)dep - (char *)hdr));
     237  1778311207 :                         name.name = dep->name;
     238  1778311207 :                         name.len = dep->namelen;
     239  1778311207 :                         hash = xfs_dir2_hashname(mp, &name);
     240 89942355505 :                         for (i = 0; i < be32_to_cpu(btp->count); i++) {
     241 89957971365 :                                 if (be32_to_cpu(lep[i].address) == addr &&
     242  1784574909 :                                     be32_to_cpu(lep[i].hashval) == hash)
     243             :                                         break;
     244             :                         }
     245  1781120875 :                         if (i >= be32_to_cpu(btp->count))
     246           0 :                                 return __this_address;
     247             :                 }
     248 >10652*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   375135783 :         if (freeseen != 7)
     254           0 :                 return __this_address;
     255   375135783 :         if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
     256             :             hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
     257  4030329052 :                 for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
     258  1940127420 :                         if (lep[i].address ==
     259             :                             cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
     260   148975493 :                                 stale++;
     261  3805125344 :                         if (i > 0 && be32_to_cpu(lep[i].hashval) <
     262  1864997924 :                                      be32_to_cpu(lep[i - 1].hashval))
     263           0 :                                 return __this_address;
     264             :                 }
     265   150074212 :                 if (count != be32_to_cpu(btp->count) - be32_to_cpu(btp->stale))
     266         159 :                         return __this_address;
     267    75037898 :                 if (stale != be32_to_cpu(btp->stale))
     268           0 :                         return __this_address;
     269             :         }
     270             :         return NULL;
     271             : }
     272             : 
     273             : #ifdef DEBUG
     274             : void
     275   329205584 : xfs_dir3_data_check(
     276             :         struct xfs_inode        *dp,
     277             :         struct xfs_buf          *bp)
     278             : {
     279   329205584 :         xfs_failaddr_t          fa;
     280             : 
     281   329205584 :         fa = __xfs_dir3_data_check(dp, bp);
     282   329171887 :         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    43213120 : xfs_dir3_data_verify(
     293             :         struct xfs_buf          *bp)
     294             : {
     295    43213120 :         struct xfs_mount        *mp = bp->b_mount;
     296    43213120 :         struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
     297             : 
     298    43213120 :         if (!xfs_verify_magic(bp, hdr3->magic))
     299           0 :                 return __this_address;
     300             : 
     301    43214602 :         if (xfs_has_crc(mp)) {
     302    43214214 :                 if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
     303           0 :                         return __this_address;
     304    43213062 :                 if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp))
     305           0 :                         return __this_address;
     306    43214553 :                 if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
     307           0 :                         return __this_address;
     308             :         }
     309    43215358 :         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       64329 : xfs_dir3_data_reada_verify(
     319             :         struct xfs_buf          *bp)
     320             : {
     321       64329 :         struct xfs_dir2_data_hdr *hdr = bp->b_addr;
     322             : 
     323       64329 :         switch (hdr->magic) {
     324       17743 :         case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
     325             :         case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
     326       17743 :                 bp->b_ops = &xfs_dir3_block_buf_ops;
     327       17743 :                 bp->b_ops->verify_read(bp);
     328       17743 :                 return;
     329       46586 :         case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
     330             :         case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
     331       46586 :                 bp->b_ops = &xfs_dir3_data_buf_ops;
     332       46586 :                 bp->b_ops->verify_read(bp);
     333       46586 :                 return;
     334             :         default:
     335           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, __this_address);
     336           0 :                 break;
     337             :         }
     338             : }
     339             : 
     340             : static void
     341      141897 : xfs_dir3_data_read_verify(
     342             :         struct xfs_buf  *bp)
     343             : {
     344      141897 :         struct xfs_mount        *mp = bp->b_mount;
     345      141897 :         xfs_failaddr_t          fa;
     346             : 
     347      283794 :         if (xfs_has_crc(mp) &&
     348             :             !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
     349          18 :                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
     350             :         else {
     351      141879 :                 fa = xfs_dir3_data_verify(bp);
     352      141879 :                 if (fa)
     353           0 :                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     354             :         }
     355      141897 : }
     356             : 
     357             : static void
     358     1172110 : xfs_dir3_data_write_verify(
     359             :         struct xfs_buf  *bp)
     360             : {
     361     1172110 :         struct xfs_mount        *mp = bp->b_mount;
     362     1172110 :         struct xfs_buf_log_item *bip = bp->b_log_item;
     363     1172110 :         struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
     364     1172110 :         xfs_failaddr_t          fa;
     365             : 
     366     1172110 :         fa = xfs_dir3_data_verify(bp);
     367     1172110 :         if (fa) {
     368           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     369           0 :                 return;
     370             :         }
     371             : 
     372     1172110 :         if (!xfs_has_crc(mp))
     373             :                 return;
     374             : 
     375     1172110 :         if (bip)
     376     1172110 :                 hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
     377             : 
     378     1172110 :         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   307019886 : xfs_dir3_data_header_check(
     400             :         struct xfs_buf          *bp,
     401             :         xfs_ino_t               owner)
     402             : {
     403   307019886 :         struct xfs_mount        *mp = bp->b_mount;
     404             : 
     405   307019886 :         if (xfs_has_crc(mp)) {
     406   307019886 :                 struct xfs_dir3_data_hdr *hdr3 = bp->b_addr;
     407             : 
     408   307019886 :                 ASSERT(hdr3->hdr.magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
     409             : 
     410   307019886 :                 if (be64_to_cpu(hdr3->hdr.owner) != owner)
     411           0 :                         return __this_address;
     412             :         }
     413             : 
     414             :         return NULL;
     415             : }
     416             : 
     417             : int
     418   306910786 : 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   306910786 :         xfs_failaddr_t          fa;
     427   306910786 :         int                     err;
     428             : 
     429   306910786 :         err = xfs_da_read_buf(tp, dp, bno, flags, bpp, XFS_DATA_FORK,
     430             :                         &xfs_dir3_data_buf_ops);
     431   307074798 :         if (err || !*bpp)
     432             :                 return err;
     433             : 
     434             :         /* Check things that we can't do in the verifier. */
     435   307071965 :         fa = xfs_dir3_data_header_check(*bpp, owner);
     436   307137060 :         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   307137060 :         xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_DATA_BUF);
     445   307137060 :         return err;
     446             : }
     447             : 
     448             : int
     449   118730182 : xfs_dir3_data_readahead(
     450             :         struct xfs_inode        *dp,
     451             :         xfs_dablk_t             bno,
     452             :         unsigned int            flags)
     453             : {
     454   118730182 :         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  3756222655 : 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  3756222655 :         struct xfs_dir2_data_free       *dfp;
     470  3756222655 :         xfs_dir2_data_aoff_t            off;
     471  3756222655 :         bool                            matched = false;
     472  3756222655 :         bool                            seenzero = false;
     473             : 
     474  3756222655 :         *bf_ent = NULL;
     475  3756222655 :         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 15028769601 :         for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
     483 11272546946 :                 if (!dfp->offset) {
     484   159252864 :                         if (dfp->length)
     485           0 :                                 return __this_address;
     486   159252864 :                         seenzero = true;
     487   159252864 :                         continue;
     488             :                 }
     489 11113294082 :                 if (seenzero)
     490           0 :                         return __this_address;
     491 11113294082 :                 if (be16_to_cpu(dfp->offset) == off) {
     492   709263566 :                         matched = true;
     493   709263566 :                         if (dfp->length != dup->length)
     494           0 :                                 return __this_address;
     495 10404030516 :                 } else if (be16_to_cpu(dfp->offset) > off) {
     496  3012649170 :                         if (off + be16_to_cpu(dup->length) >
     497             :                                         be16_to_cpu(dfp->offset))
     498           0 :                                 return __this_address;
     499             :                 } else {
     500 14782762692 :                         if (be16_to_cpu(dfp->offset) +
     501  7391381346 :                                         be16_to_cpu(dfp->length) > off)
     502           0 :                                 return __this_address;
     503             :                 }
     504 20176773530 :                 if (!matched &&
     505  9772743014 :                     be16_to_cpu(dfp->length) < be16_to_cpu(dup->length))
     506           0 :                         return __this_address;
     507 18464104846 :                 if (dfp > &bf[0] &&
     508  7350810764 :                     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  3756222655 :         *bf_ent = xfs_dir2_data_freefind(hdr, bf, dup);
     514  3756222655 :         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  3809634272 : 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  3809634272 :         xfs_dir2_data_free_t    *dfp;           /* bestfree entry */
     528  3809634272 :         xfs_dir2_data_aoff_t    off;            /* offset value needed */
     529             : 
     530  3809634272 :         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  7619268544 :         if (be16_to_cpu(dup->length) <
     537  3809634272 :             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  8589798235 :         for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
     543  6793479287 :                 if (!dfp->offset)
     544             :                         return NULL;
     545  6793479287 :                 if (be16_to_cpu(dfp->offset) == off)
     546   756450287 :                         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   536244924 : 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   536244924 :         xfs_dir2_data_free_t    new;            /* new bestfree entry */
     565             : 
     566   536244924 :         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   536244924 :         new.length = dup->length;
     572   536244924 :         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   536244924 :         if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) {
     578    61025703 :                 dfp[2] = dfp[1];
     579    61025703 :                 dfp[1] = dfp[0];
     580    61025703 :                 dfp[0] = new;
     581    61025703 :                 *loghead = 1;
     582    61025703 :                 return &dfp[0];
     583             :         }
     584   475219221 :         if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) {
     585    35057719 :                 dfp[2] = dfp[1];
     586    35057719 :                 dfp[1] = new;
     587    35057719 :                 *loghead = 1;
     588    35057719 :                 return &dfp[1];
     589             :         }
     590   440161502 :         if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) {
     591    34893829 :                 dfp[2] = new;
     592    34893829 :                 *loghead = 1;
     593    34893829 :                 return &dfp[2];
     594             :         }
     595             :         return NULL;
     596             : }
     597             : 
     598             : /*
     599             :  * Remove a bestfree entry from the table.
     600             :  */
     601             : STATIC void
     602    37790132 : 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    37790132 :         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    37790132 :         if (dfp == &bf[0]) {
     618    36139315 :                 bf[0] = bf[1];
     619    36139315 :                 bf[1] = bf[2];
     620             :         }
     621             :         /*
     622             :          * It's the second entry, slide the 3rd entry up.
     623             :          */
     624     1650817 :         else if (dfp == &bf[1])
     625     1276072 :                 bf[1] = bf[2];
     626             :         /*
     627             :          * Must be the last entry.
     628             :          */
     629             :         else
     630      374745 :                 ASSERT(dfp == &bf[2]);
     631             :         /*
     632             :          * Clear the 3rd entry, must be zero now.
     633             :          */
     634    37790132 :         bf[2].length = 0;
     635    37790132 :         bf[2].offset = 0;
     636    37790132 :         *loghead = 1;
     637    37790132 : }
     638             : 
     639             : /*
     640             :  * Given a data block, reconstruct its bestfree map.
     641             :  */
     642             : void
     643    19502730 : xfs_dir2_data_freescan(
     644             :         struct xfs_mount                *mp,
     645             :         struct xfs_dir2_data_hdr        *hdr,
     646             :         int                             *loghead)
     647             : {
     648    19502730 :         struct xfs_da_geometry          *geo = mp->m_dir_geo;
     649    19502730 :         struct xfs_dir2_data_free       *bf = xfs_dir2_data_bestfree_p(mp, hdr);
     650    19502730 :         void                            *addr = hdr;
     651    19502730 :         unsigned int                    offset = geo->data_entry_offset;
     652    19502730 :         unsigned int                    end;
     653             : 
     654    19502730 :         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    19502730 :         memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT);
     663    19502730 :         *loghead = 1;
     664             : 
     665    19502730 :         end = xfs_dir3_data_end_offset(geo, addr);
     666  3016450562 :         while (offset < end) {
     667  2996947393 :                 struct xfs_dir2_data_unused     *dup = addr + offset;
     668  2996947393 :                 struct xfs_dir2_data_entry      *dep = addr + offset;
     669             : 
     670             :                 /*
     671             :                  * If it's a free entry, insert it.
     672             :                  */
     673  2996947393 :                 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
     674   485678525 :                         ASSERT(offset ==
     675             :                                be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
     676   485678525 :                         xfs_dir2_data_freeinsert(hdr, bf, dup, loghead);
     677   485678964 :                         offset += be16_to_cpu(dup->length);
     678   485678964 :                         continue;
     679             :                 }
     680             : 
     681             :                 /*
     682             :                  * For active entries, check their tags and skip them.
     683             :                  */
     684  2511268868 :                 ASSERT(offset ==
     685             :                        be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep)));
     686  5023134071 :                 offset += xfs_dir2_data_entsize(mp, dep->namelen);
     687             :         }
     688    19503169 : }
     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      445995 : 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      445995 :         struct xfs_trans                *tp = args->trans;
     701      445995 :         struct xfs_inode                *dp = args->dp;
     702      445995 :         struct xfs_mount                *mp = dp->i_mount;
     703      445995 :         struct xfs_da_geometry          *geo = args->geo;
     704      445995 :         struct xfs_buf                  *bp;
     705      445995 :         struct xfs_dir2_data_hdr        *hdr;
     706      445995 :         struct xfs_dir2_data_unused     *dup;
     707      445995 :         struct xfs_dir2_data_free       *bf;
     708      445995 :         int                             error;
     709      445995 :         int                             i;
     710             : 
     711             :         /*
     712             :          * Get the buffer set up for the block.
     713             :          */
     714      445995 :         error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, blkno),
     715             :                                &bp, XFS_DATA_FORK);
     716      445996 :         if (error)
     717             :                 return error;
     718      445996 :         bp->b_ops = &xfs_dir3_data_buf_ops;
     719      445996 :         xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_DATA_BUF);
     720             : 
     721             :         /*
     722             :          * Initialize the header.
     723             :          */
     724      445996 :         hdr = bp->b_addr;
     725      445996 :         if (xfs_has_crc(mp)) {
     726      445992 :                 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
     727             : 
     728      445992 :                 memset(hdr3, 0, sizeof(*hdr3));
     729      445992 :                 hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);
     730      445992 :                 hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));
     731      445992 :                 hdr3->owner = cpu_to_be64(args->owner);
     732      445992 :                 uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
     733             : 
     734             :         } else
     735           4 :                 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
     736             : 
     737      445996 :         bf = xfs_dir2_data_bestfree_p(mp, hdr);
     738      445996 :         bf[0].offset = cpu_to_be16(geo->data_entry_offset);
     739      445996 :         bf[0].length = cpu_to_be16(geo->blksize - geo->data_entry_offset);
     740     1337988 :         for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
     741      891992 :                 bf[i].length = 0;
     742      891992 :                 bf[i].offset = 0;
     743             :         }
     744             : 
     745             :         /*
     746             :          * Set up an unused entry for the block's body.
     747             :          */
     748      445996 :         dup = bp->b_addr + geo->data_entry_offset;
     749      445996 :         dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
     750      445996 :         dup->length = bf[0].length;
     751      445996 :         *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr);
     752             : 
     753             :         /*
     754             :          * Log it and return it.
     755             :          */
     756      445996 :         xfs_dir2_data_log_header(args, bp);
     757      445996 :         xfs_dir2_data_log_unused(args, bp, dup);
     758      445996 :         *bpp = bp;
     759      445996 :         return 0;
     760             : }
     761             : 
     762             : /*
     763             :  * Log an active data entry from the block.
     764             :  */
     765             : void
     766    46952755 : 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    46952755 :         struct xfs_mount        *mp = bp->b_mount;
     772    46952755 :         struct xfs_dir2_data_hdr *hdr = bp->b_addr;
     773             : 
     774    46952755 :         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    46952755 :         xfs_trans_log_buf(args->trans, bp, (uint)((char *)dep - (char *)hdr),
     780    46952755 :                 (uint)((char *)(xfs_dir2_data_entry_tag_p(mp, dep) + 1) -
     781    46952755 :                        (char *)hdr - 1));
     782    46952131 : }
     783             : 
     784             : /*
     785             :  * Log a data block header.
     786             :  */
     787             : void
     788    61364627 : xfs_dir2_data_log_header(
     789             :         struct xfs_da_args      *args,
     790             :         struct xfs_buf          *bp)
     791             : {
     792             : #ifdef DEBUG
     793    61364627 :         struct xfs_dir2_data_hdr *hdr = bp->b_addr;
     794             : 
     795    61364627 :         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    61364627 :         xfs_trans_log_buf(args->trans, bp, 0, args->geo->data_entry_offset - 1);
     802    61365200 : }
     803             : 
     804             : /*
     805             :  * Log a data unused entry.
     806             :  */
     807             : void
     808    57752769 : 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    57752769 :         xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
     814             : 
     815    57752769 :         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    57752769 :         xfs_trans_log_buf(args->trans, bp, (uint)((char *)dup - (char *)hdr),
     824    57752769 :                 (uint)((char *)&dup->length + sizeof(dup->length) -
     825    57752769 :                        1 - (char *)hdr));
     826             :         /*
     827             :          * Log the end (tag) of the unused entry.
     828             :          */
     829    57752089 :         xfs_trans_log_buf(args->trans, bp,
     830    57752089 :                 (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr),
     831             :                 (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr +
     832             :                        sizeof(xfs_dir2_data_off_t) - 1));
     833    57755345 : }
     834             : 
     835             : /*
     836             :  * Make a byte range in the data block unused.
     837             :  * Its current contents are unimportant.
     838             :  */
     839             : void
     840    34356666 : 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    34356666 :         xfs_dir2_data_hdr_t     *hdr;           /* data block pointer */
     849    34356666 :         xfs_dir2_data_free_t    *dfp;           /* bestfree pointer */
     850    34356666 :         int                     needscan;       /* need to regen bestfree */
     851    34356666 :         xfs_dir2_data_unused_t  *newdup;        /* new unused entry */
     852    34356666 :         xfs_dir2_data_unused_t  *postdup;       /* unused entry after us */
     853    34356666 :         xfs_dir2_data_unused_t  *prevdup;       /* unused entry before us */
     854    34356666 :         unsigned int            end;
     855    34356666 :         struct xfs_dir2_data_free *bf;
     856             : 
     857    34356666 :         hdr = bp->b_addr;
     858             : 
     859             :         /*
     860             :          * Figure out where the end of the data area is.
     861             :          */
     862    34356666 :         end = xfs_dir3_data_end_offset(args->geo, hdr);
     863    34356666 :         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    34356666 :         if (offset > args->geo->data_entry_offset) {
     870    34170184 :                 __be16                  *tagp;  /* tag just before us */
     871             : 
     872    34170184 :                 tagp = (__be16 *)((char *)hdr + offset) - 1;
     873    34170184 :                 prevdup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
     874    34170184 :                 if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
     875    25927097 :                         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    34356666 :         if (offset + len < end) {
     883    34189912 :                 postdup =
     884    34189912 :                         (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
     885    34189912 :                 if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
     886    28519930 :                         postdup = NULL;
     887             :         } else
     888             :                 postdup = NULL;
     889    34356666 :         ASSERT(*needscanp == 0);
     890    34356666 :         needscan = 0;
     891             :         /*
     892             :          * Previous and following entries are both free,
     893             :          * merge everything into a single free entry.
     894             :          */
     895    34356666 :         bf = xfs_dir2_data_bestfree_p(args->dp->i_mount, hdr);
     896    34356666 :         if (prevdup && postdup) {
     897     1943626 :                 xfs_dir2_data_free_t    *dfp2;  /* another bestfree pointer */
     898             : 
     899             :                 /*
     900             :                  * See if prevdup and/or postdup are in bestfree table.
     901             :                  */
     902     1943626 :                 dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);
     903     1943626 :                 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     1943626 :                 needscan = (bf[2].length != 0);
     911             :                 /*
     912             :                  * Fix up the new big freespace.
     913             :                  */
     914     3887252 :                 be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length));
     915     3887250 :                 *xfs_dir2_data_unused_tag_p(prevdup) =
     916     1943625 :                         cpu_to_be16((char *)prevdup - (char *)hdr);
     917     1943625 :                 xfs_dir2_data_log_unused(args, bp, prevdup);
     918     1943649 :                 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       60546 :                         ASSERT(dfp && dfp2);
     926       60546 :                         if (dfp == &bf[1]) {
     927       49641 :                                 dfp = &bf[0];
     928       49641 :                                 ASSERT(dfp2 == dfp);
     929             :                                 dfp2 = &bf[1];
     930             :                         }
     931       60546 :                         xfs_dir2_data_freeremove(hdr, bf, dfp2, needlogp);
     932       60546 :                         xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
     933             :                         /*
     934             :                          * Now insert the new entry.
     935             :                          */
     936       60546 :                         dfp = xfs_dir2_data_freeinsert(hdr, bf, prevdup,
     937             :                                                        needlogp);
     938       60546 :                         ASSERT(dfp == &bf[0]);
     939       60546 :                         ASSERT(dfp->length == prevdup->length);
     940       60546 :                         ASSERT(!dfp[1].length);
     941       60546 :                         ASSERT(!dfp[2].length);
     942             :                 }
     943             :         }
     944             :         /*
     945             :          * The entry before us is free, merge with it.
     946             :          */
     947    32413040 :         else if (prevdup) {
     948     6300441 :                 dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);
     949     6300441 :                 be16_add_cpu(&prevdup->length, len);
     950    12600736 :                 *xfs_dir2_data_unused_tag_p(prevdup) =
     951     6300368 :                         cpu_to_be16((char *)prevdup - (char *)hdr);
     952     6300368 :                 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     6300489 :                 if (dfp) {
     959     4446140 :                         xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
     960     4446141 :                         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     3708698 :                         needscan = be16_to_cpu(prevdup->length) >
     967     1854349 :                                    be16_to_cpu(bf[2].length);
     968             :                 }
     969             :         }
     970             :         /*
     971             :          * The following entry is free, merge with it.
     972             :          */
     973    26112599 :         else if (postdup) {
     974     3726984 :                 dfp = xfs_dir2_data_freefind(hdr, bf, postdup);
     975     3726984 :                 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
     976     3726984 :                 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
     977     7453968 :                 newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
     978     7453968 :                 *xfs_dir2_data_unused_tag_p(newdup) =
     979     3726984 :                         cpu_to_be16((char *)newdup - (char *)hdr);
     980     3726984 :                 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     3726950 :                 if (dfp) {
     987      737181 :                         xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
     988      737181 :                         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     5979538 :                         needscan = be16_to_cpu(newdup->length) >
     995     2989769 :                                    be16_to_cpu(bf[2].length);
     996             :                 }
     997             :         }
     998             :         /*
     999             :          * Neither neighbor is free.  Make a new entry.
    1000             :          */
    1001             :         else {
    1002    22385615 :                 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
    1003    22385615 :                 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    1004    22385615 :                 newdup->length = cpu_to_be16(len);
    1005    44771230 :                 *xfs_dir2_data_unused_tag_p(newdup) =
    1006    22385615 :                         cpu_to_be16((char *)newdup - (char *)hdr);
    1007    22385615 :                 xfs_dir2_data_log_unused(args, bp, newdup);
    1008    22385682 :                 xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);
    1009             :         }
    1010    34357961 :         *needscanp = needscan;
    1011    34357961 : }
    1012             : 
    1013             : /* Check our free data for obvious signs of corruption. */
    1014             : static inline xfs_failaddr_t
    1015    41339172 : 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    41339172 :         if (hdr->magic != cpu_to_be32(XFS_DIR2_DATA_MAGIC) &&
    1022     5344302 :             hdr->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC) &&
    1023     5343950 :             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    41339172 :         if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG)
    1027           0 :                 return __this_address;
    1028    41339172 :         if (offset < (char *)dup - (char *)hdr)
    1029           0 :                 return __this_address;
    1030    41339172 :         if (offset + len > (char *)dup + be16_to_cpu(dup->length) - (char *)hdr)
    1031           0 :                 return __this_address;
    1032    41339172 :         if ((char *)dup - (char *)hdr !=
    1033    41339172 :                         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    20945535 : 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    20945535 :         if (dfp == NULL)
    1046           0 :                 return __this_address;
    1047    20945535 :         if (dfp->length != newdup->length)
    1048           0 :                 return __this_address;
    1049    20945535 :         if (be16_to_cpu(dfp->offset) != (char *)newdup - (char *)hdr)
    1050         116 :                 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    41337660 : 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    41337660 :         xfs_dir2_data_hdr_t     *hdr;           /* data block header */
    1068    41337660 :         xfs_dir2_data_free_t    *dfp;           /* bestfree pointer */
    1069    41337660 :         xfs_dir2_data_unused_t  *newdup;        /* new unused entry */
    1070    41337660 :         xfs_dir2_data_unused_t  *newdup2;       /* another new unused entry */
    1071    41337660 :         struct xfs_dir2_data_free *bf;
    1072    41337660 :         xfs_failaddr_t          fa;
    1073    41337660 :         int                     matchback;      /* matches end of freespace */
    1074    41337660 :         int                     matchfront;     /* matches start of freespace */
    1075    41337660 :         int                     needscan;       /* need to regen bestfree */
    1076    41337660 :         int                     oldlen;         /* old unused entry's length */
    1077             : 
    1078    41337660 :         hdr = bp->b_addr;
    1079    41337660 :         fa = xfs_dir2_data_check_free(hdr, dup, offset, len);
    1080    41339104 :         if (fa)
    1081           0 :                 goto corrupt;
    1082             :         /*
    1083             :          * Look up the entry in the bestfree table.
    1084             :          */
    1085    41339104 :         oldlen = be16_to_cpu(dup->length);
    1086    41339104 :         bf = xfs_dir2_data_bestfree_p(args->dp->i_mount, hdr);
    1087    41339104 :         dfp = xfs_dir2_data_freefind(hdr, bf, dup);
    1088    41339104 :         ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length));
    1089             :         /*
    1090             :          * Check for alignment with front and back of the entry.
    1091             :          */
    1092    41339104 :         matchfront = (char *)dup - (char *)hdr == offset;
    1093    41339104 :         matchback = (char *)dup + oldlen - (char *)hdr == offset + len;
    1094    41339104 :         ASSERT(*needscanp == 0);
    1095    41339104 :         needscan = 0;
    1096             :         /*
    1097             :          * If we matched it exactly we just need to get rid of it from
    1098             :          * the bestfree table.
    1099             :          */
    1100    41339104 :         if (matchfront && matchback) {
    1101    20375905 :                 if (dfp) {
    1102    20374718 :                         needscan = (bf[2].offset != 0);
    1103    20374718 :                         if (!needscan)
    1104    11539012 :                                 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    20963199 :         else if (matchfront) {
    1113    18825191 :                 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
    1114    18825191 :                 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    1115    18825191 :                 newdup->length = cpu_to_be16(oldlen - len);
    1116    37650382 :                 *xfs_dir2_data_unused_tag_p(newdup) =
    1117    18825191 :                         cpu_to_be16((char *)newdup - (char *)hdr);
    1118    18825191 :                 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    18825160 :                 if (dfp) {
    1123    18824866 :                         xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
    1124    18824149 :                         dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,
    1125             :                                                        needlogp);
    1126    18824411 :                         fa = xfs_dir2_data_check_new_free(hdr, dfp, newdup);
    1127    18825006 :                         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    18825006 :                         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     2138008 :         else if (matchback) {
    1142     2138008 :                 newdup = dup;
    1143     2138008 :                 newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
    1144     4276016 :                 *xfs_dir2_data_unused_tag_p(newdup) =
    1145     2138008 :                         cpu_to_be16((char *)newdup - (char *)hdr);
    1146     2138008 :                 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     2138038 :                 if (dfp) {
    1151     2121572 :                         xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
    1152     2121519 :                         dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,
    1153             :                                                        needlogp);
    1154     2121524 :                         fa = xfs_dir2_data_check_new_free(hdr, dfp, newdup);
    1155     2121583 :                         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     2121583 :                         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    41339270 :         *needscanp = needscan;
    1202    41339270 :         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   486020970 : xfs_dir3_data_end_offset(
    1213             :         struct xfs_da_geometry          *geo,
    1214             :         struct xfs_dir2_data_hdr        *hdr)
    1215             : {
    1216   486020970 :         void                            *p;
    1217             : 
    1218   486020970 :         switch (hdr->magic) {
    1219             :         case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
    1220             :         case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
    1221    93009297 :                 p = xfs_dir2_block_leaf_p(xfs_dir2_block_tail_p(geo, hdr));
    1222    93009297 :                 return p - (void *)hdr;
    1223   393011673 :         case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
    1224             :         case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
    1225   393011673 :                 return geo->blksize;
    1226             :         default:
    1227             :                 return 0;
    1228             :         }
    1229             : }

Generated by: LCOV version 1.14