Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
0004  * Copyright (c) 2013 Red Hat, Inc.
0005  * All Rights Reserved.
0006  */
0007 #include "xfs.h"
0008 #include "xfs_fs.h"
0009 #include "xfs_shared.h"
0010 #include "xfs_format.h"
0011 #include "xfs_log_format.h"
0012 #include "xfs_trans_resv.h"
0013 #include "xfs_mount.h"
0014 #include "xfs_inode.h"
0015 #include "xfs_dir2.h"
0016 #include "xfs_dir2_priv.h"
0017 #include "xfs_error.h"
0018 #include "xfs_trans.h"
0019 #include "xfs_buf_item.h"
0020 #include "xfs_log.h"
0021 
0022 static xfs_failaddr_t xfs_dir2_data_freefind_verify(
0023         struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf,
0024         struct xfs_dir2_data_unused *dup,
0025         struct xfs_dir2_data_free **bf_ent);
0026 
0027 struct xfs_dir2_data_free *
0028 xfs_dir2_data_bestfree_p(
0029     struct xfs_mount        *mp,
0030     struct xfs_dir2_data_hdr    *hdr)
0031 {
0032     if (xfs_has_crc(mp))
0033         return ((struct xfs_dir3_data_hdr *)hdr)->best_free;
0034     return hdr->bestfree;
0035 }
0036 
0037 /*
0038  * Pointer to an entry's tag word.
0039  */
0040 __be16 *
0041 xfs_dir2_data_entry_tag_p(
0042     struct xfs_mount        *mp,
0043     struct xfs_dir2_data_entry  *dep)
0044 {
0045     return (__be16 *)((char *)dep +
0046         xfs_dir2_data_entsize(mp, dep->namelen) - sizeof(__be16));
0047 }
0048 
0049 uint8_t
0050 xfs_dir2_data_get_ftype(
0051     struct xfs_mount        *mp,
0052     struct xfs_dir2_data_entry  *dep)
0053 {
0054     if (xfs_has_ftype(mp)) {
0055         uint8_t         ftype = dep->name[dep->namelen];
0056 
0057         if (likely(ftype < XFS_DIR3_FT_MAX))
0058             return ftype;
0059     }
0060 
0061     return XFS_DIR3_FT_UNKNOWN;
0062 }
0063 
0064 void
0065 xfs_dir2_data_put_ftype(
0066     struct xfs_mount        *mp,
0067     struct xfs_dir2_data_entry  *dep,
0068     uint8_t             ftype)
0069 {
0070     ASSERT(ftype < XFS_DIR3_FT_MAX);
0071     ASSERT(dep->namelen != 0);
0072 
0073     if (xfs_has_ftype(mp))
0074         dep->name[dep->namelen] = ftype;
0075 }
0076 
0077 /*
0078  * The number of leaf entries is limited by the size of the block and the amount
0079  * of space used by the data entries.  We don't know how much space is used by
0080  * the data entries yet, so just ensure that the count falls somewhere inside
0081  * the block right now.
0082  */
0083 static inline unsigned int
0084 xfs_dir2_data_max_leaf_entries(
0085     struct xfs_da_geometry      *geo)
0086 {
0087     return (geo->blksize - sizeof(struct xfs_dir2_block_tail) -
0088         geo->data_entry_offset) /
0089             sizeof(struct xfs_dir2_leaf_entry);
0090 }
0091 
0092 /*
0093  * Check the consistency of the data block.
0094  * The input can also be a block-format directory.
0095  * Return NULL if the buffer is good, otherwise the address of the error.
0096  */
0097 xfs_failaddr_t
0098 __xfs_dir3_data_check(
0099     struct xfs_inode    *dp,        /* incore inode pointer */
0100     struct xfs_buf      *bp)        /* data block's buffer */
0101 {
0102     xfs_dir2_dataptr_t  addr;       /* addr for leaf lookup */
0103     xfs_dir2_data_free_t    *bf;        /* bestfree table */
0104     xfs_dir2_block_tail_t   *btp=NULL;  /* block tail */
0105     int         count;      /* count of entries found */
0106     xfs_dir2_data_hdr_t *hdr;       /* data block header */
0107     xfs_dir2_data_free_t    *dfp;       /* bestfree entry */
0108     int         freeseen;   /* mask of bestfrees seen */
0109     xfs_dahash_t        hash;       /* hash of current name */
0110     int         i;      /* leaf index */
0111     int         lastfree;   /* last entry was unused */
0112     xfs_dir2_leaf_entry_t   *lep=NULL;  /* block leaf entries */
0113     struct xfs_mount    *mp = bp->b_mount;
0114     int         stale;      /* count of stale leaves */
0115     struct xfs_name     name;
0116     unsigned int        offset;
0117     unsigned int        end;
0118     struct xfs_da_geometry  *geo = mp->m_dir_geo;
0119 
0120     /*
0121      * If this isn't a directory, something is seriously wrong.  Bail out.
0122      */
0123     if (dp && !S_ISDIR(VFS_I(dp)->i_mode))
0124         return __this_address;
0125 
0126     hdr = bp->b_addr;
0127     offset = geo->data_entry_offset;
0128 
0129     switch (hdr->magic) {
0130     case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
0131     case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
0132         btp = xfs_dir2_block_tail_p(geo, hdr);
0133         lep = xfs_dir2_block_leaf_p(btp);
0134 
0135         if (be32_to_cpu(btp->count) >=
0136             xfs_dir2_data_max_leaf_entries(geo))
0137             return __this_address;
0138         break;
0139     case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
0140     case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
0141         break;
0142     default:
0143         return __this_address;
0144     }
0145     end = xfs_dir3_data_end_offset(geo, hdr);
0146     if (!end)
0147         return __this_address;
0148 
0149     /*
0150      * Account for zero bestfree entries.
0151      */
0152     bf = xfs_dir2_data_bestfree_p(mp, hdr);
0153     count = lastfree = freeseen = 0;
0154     if (!bf[0].length) {
0155         if (bf[0].offset)
0156             return __this_address;
0157         freeseen |= 1 << 0;
0158     }
0159     if (!bf[1].length) {
0160         if (bf[1].offset)
0161             return __this_address;
0162         freeseen |= 1 << 1;
0163     }
0164     if (!bf[2].length) {
0165         if (bf[2].offset)
0166             return __this_address;
0167         freeseen |= 1 << 2;
0168     }
0169 
0170     if (be16_to_cpu(bf[0].length) < be16_to_cpu(bf[1].length))
0171         return __this_address;
0172     if (be16_to_cpu(bf[1].length) < be16_to_cpu(bf[2].length))
0173         return __this_address;
0174     /*
0175      * Loop over the data/unused entries.
0176      */
0177     while (offset < end) {
0178         struct xfs_dir2_data_unused *dup = bp->b_addr + offset;
0179         struct xfs_dir2_data_entry  *dep = bp->b_addr + offset;
0180 
0181         /*
0182          * If it's unused, look for the space in the bestfree table.
0183          * If we find it, account for that, else make sure it
0184          * doesn't need to be there.
0185          */
0186         if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
0187             xfs_failaddr_t  fa;
0188 
0189             if (lastfree != 0)
0190                 return __this_address;
0191             if (offset + be16_to_cpu(dup->length) > end)
0192                 return __this_address;
0193             if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
0194                 offset)
0195                 return __this_address;
0196             fa = xfs_dir2_data_freefind_verify(hdr, bf, dup, &dfp);
0197             if (fa)
0198                 return fa;
0199             if (dfp) {
0200                 i = (int)(dfp - bf);
0201                 if ((freeseen & (1 << i)) != 0)
0202                     return __this_address;
0203                 freeseen |= 1 << i;
0204             } else {
0205                 if (be16_to_cpu(dup->length) >
0206                     be16_to_cpu(bf[2].length))
0207                     return __this_address;
0208             }
0209             offset += be16_to_cpu(dup->length);
0210             lastfree = 1;
0211             continue;
0212         }
0213         /*
0214          * It's a real entry.  Validate the fields.
0215          * If this is a block directory then make sure it's
0216          * in the leaf section of the block.
0217          * The linear search is crude but this is DEBUG code.
0218          */
0219         if (dep->namelen == 0)
0220             return __this_address;
0221         if (!xfs_verify_dir_ino(mp, be64_to_cpu(dep->inumber)))
0222             return __this_address;
0223         if (offset + xfs_dir2_data_entsize(mp, dep->namelen) > end)
0224             return __this_address;
0225         if (be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep)) != offset)
0226             return __this_address;
0227         if (xfs_dir2_data_get_ftype(mp, dep) >= XFS_DIR3_FT_MAX)
0228             return __this_address;
0229         count++;
0230         lastfree = 0;
0231         if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
0232             hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
0233             addr = xfs_dir2_db_off_to_dataptr(geo, geo->datablk,
0234                         (xfs_dir2_data_aoff_t)
0235                         ((char *)dep - (char *)hdr));
0236             name.name = dep->name;
0237             name.len = dep->namelen;
0238             hash = xfs_dir2_hashname(mp, &name);
0239             for (i = 0; i < be32_to_cpu(btp->count); i++) {
0240                 if (be32_to_cpu(lep[i].address) == addr &&
0241                     be32_to_cpu(lep[i].hashval) == hash)
0242                     break;
0243             }
0244             if (i >= be32_to_cpu(btp->count))
0245                 return __this_address;
0246         }
0247         offset += xfs_dir2_data_entsize(mp, dep->namelen);
0248     }
0249     /*
0250      * Need to have seen all the entries and all the bestfree slots.
0251      */
0252     if (freeseen != 7)
0253         return __this_address;
0254     if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
0255         hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
0256         for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
0257             if (lep[i].address ==
0258                 cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
0259                 stale++;
0260             if (i > 0 && be32_to_cpu(lep[i].hashval) <
0261                      be32_to_cpu(lep[i - 1].hashval))
0262                 return __this_address;
0263         }
0264         if (count != be32_to_cpu(btp->count) - be32_to_cpu(btp->stale))
0265             return __this_address;
0266         if (stale != be32_to_cpu(btp->stale))
0267             return __this_address;
0268     }
0269     return NULL;
0270 }
0271 
0272 #ifdef DEBUG
0273 void
0274 xfs_dir3_data_check(
0275     struct xfs_inode    *dp,
0276     struct xfs_buf      *bp)
0277 {
0278     xfs_failaddr_t      fa;
0279 
0280     fa = __xfs_dir3_data_check(dp, bp);
0281     if (!fa)
0282         return;
0283     xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,
0284             bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__,
0285             fa);
0286     ASSERT(0);
0287 }
0288 #endif
0289 
0290 static xfs_failaddr_t
0291 xfs_dir3_data_verify(
0292     struct xfs_buf      *bp)
0293 {
0294     struct xfs_mount    *mp = bp->b_mount;
0295     struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
0296 
0297     if (!xfs_verify_magic(bp, hdr3->magic))
0298         return __this_address;
0299 
0300     if (xfs_has_crc(mp)) {
0301         if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
0302             return __this_address;
0303         if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp))
0304             return __this_address;
0305         if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
0306             return __this_address;
0307     }
0308     return __xfs_dir3_data_check(NULL, bp);
0309 }
0310 
0311 /*
0312  * Readahead of the first block of the directory when it is opened is completely
0313  * oblivious to the format of the directory. Hence we can either get a block
0314  * format buffer or a data format buffer on readahead.
0315  */
0316 static void
0317 xfs_dir3_data_reada_verify(
0318     struct xfs_buf      *bp)
0319 {
0320     struct xfs_dir2_data_hdr *hdr = bp->b_addr;
0321 
0322     switch (hdr->magic) {
0323     case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
0324     case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
0325         bp->b_ops = &xfs_dir3_block_buf_ops;
0326         bp->b_ops->verify_read(bp);
0327         return;
0328     case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
0329     case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
0330         bp->b_ops = &xfs_dir3_data_buf_ops;
0331         bp->b_ops->verify_read(bp);
0332         return;
0333     default:
0334         xfs_verifier_error(bp, -EFSCORRUPTED, __this_address);
0335         break;
0336     }
0337 }
0338 
0339 static void
0340 xfs_dir3_data_read_verify(
0341     struct xfs_buf  *bp)
0342 {
0343     struct xfs_mount    *mp = bp->b_mount;
0344     xfs_failaddr_t      fa;
0345 
0346     if (xfs_has_crc(mp) &&
0347         !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
0348         xfs_verifier_error(bp, -EFSBADCRC, __this_address);
0349     else {
0350         fa = xfs_dir3_data_verify(bp);
0351         if (fa)
0352             xfs_verifier_error(bp, -EFSCORRUPTED, fa);
0353     }
0354 }
0355 
0356 static void
0357 xfs_dir3_data_write_verify(
0358     struct xfs_buf  *bp)
0359 {
0360     struct xfs_mount    *mp = bp->b_mount;
0361     struct xfs_buf_log_item *bip = bp->b_log_item;
0362     struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
0363     xfs_failaddr_t      fa;
0364 
0365     fa = xfs_dir3_data_verify(bp);
0366     if (fa) {
0367         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
0368         return;
0369     }
0370 
0371     if (!xfs_has_crc(mp))
0372         return;
0373 
0374     if (bip)
0375         hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
0376 
0377     xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF);
0378 }
0379 
0380 const struct xfs_buf_ops xfs_dir3_data_buf_ops = {
0381     .name = "xfs_dir3_data",
0382     .magic = { cpu_to_be32(XFS_DIR2_DATA_MAGIC),
0383            cpu_to_be32(XFS_DIR3_DATA_MAGIC) },
0384     .verify_read = xfs_dir3_data_read_verify,
0385     .verify_write = xfs_dir3_data_write_verify,
0386     .verify_struct = xfs_dir3_data_verify,
0387 };
0388 
0389 static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = {
0390     .name = "xfs_dir3_data_reada",
0391     .magic = { cpu_to_be32(XFS_DIR2_DATA_MAGIC),
0392            cpu_to_be32(XFS_DIR3_DATA_MAGIC) },
0393     .verify_read = xfs_dir3_data_reada_verify,
0394     .verify_write = xfs_dir3_data_write_verify,
0395 };
0396 
0397 static xfs_failaddr_t
0398 xfs_dir3_data_header_check(
0399     struct xfs_inode    *dp,
0400     struct xfs_buf      *bp)
0401 {
0402     struct xfs_mount    *mp = dp->i_mount;
0403 
0404     if (xfs_has_crc(mp)) {
0405         struct xfs_dir3_data_hdr *hdr3 = bp->b_addr;
0406 
0407         if (be64_to_cpu(hdr3->hdr.owner) != dp->i_ino)
0408             return __this_address;
0409     }
0410 
0411     return NULL;
0412 }
0413 
0414 int
0415 xfs_dir3_data_read(
0416     struct xfs_trans    *tp,
0417     struct xfs_inode    *dp,
0418     xfs_dablk_t     bno,
0419     unsigned int        flags,
0420     struct xfs_buf      **bpp)
0421 {
0422     xfs_failaddr_t      fa;
0423     int         err;
0424 
0425     err = xfs_da_read_buf(tp, dp, bno, flags, bpp, XFS_DATA_FORK,
0426             &xfs_dir3_data_buf_ops);
0427     if (err || !*bpp)
0428         return err;
0429 
0430     /* Check things that we can't do in the verifier. */
0431     fa = xfs_dir3_data_header_check(dp, *bpp);
0432     if (fa) {
0433         __xfs_buf_mark_corrupt(*bpp, fa);
0434         xfs_trans_brelse(tp, *bpp);
0435         *bpp = NULL;
0436         return -EFSCORRUPTED;
0437     }
0438 
0439     xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_DATA_BUF);
0440     return err;
0441 }
0442 
0443 int
0444 xfs_dir3_data_readahead(
0445     struct xfs_inode    *dp,
0446     xfs_dablk_t     bno,
0447     unsigned int        flags)
0448 {
0449     return xfs_da_reada_buf(dp, bno, flags, XFS_DATA_FORK,
0450                 &xfs_dir3_data_reada_buf_ops);
0451 }
0452 
0453 /*
0454  * Find the bestfree entry that exactly coincides with unused directory space
0455  * or a verifier error because the bestfree data are bad.
0456  */
0457 static xfs_failaddr_t
0458 xfs_dir2_data_freefind_verify(
0459     struct xfs_dir2_data_hdr    *hdr,
0460     struct xfs_dir2_data_free   *bf,
0461     struct xfs_dir2_data_unused *dup,
0462     struct xfs_dir2_data_free   **bf_ent)
0463 {
0464     struct xfs_dir2_data_free   *dfp;
0465     xfs_dir2_data_aoff_t        off;
0466     bool                matched = false;
0467     bool                seenzero = false;
0468 
0469     *bf_ent = NULL;
0470     off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
0471 
0472     /*
0473      * Validate some consistency in the bestfree table.
0474      * Check order, non-overlapping entries, and if we find the
0475      * one we're looking for it has to be exact.
0476      */
0477     for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
0478         if (!dfp->offset) {
0479             if (dfp->length)
0480                 return __this_address;
0481             seenzero = true;
0482             continue;
0483         }
0484         if (seenzero)
0485             return __this_address;
0486         if (be16_to_cpu(dfp->offset) == off) {
0487             matched = true;
0488             if (dfp->length != dup->length)
0489                 return __this_address;
0490         } else if (be16_to_cpu(dfp->offset) > off) {
0491             if (off + be16_to_cpu(dup->length) >
0492                     be16_to_cpu(dfp->offset))
0493                 return __this_address;
0494         } else {
0495             if (be16_to_cpu(dfp->offset) +
0496                     be16_to_cpu(dfp->length) > off)
0497                 return __this_address;
0498         }
0499         if (!matched &&
0500             be16_to_cpu(dfp->length) < be16_to_cpu(dup->length))
0501             return __this_address;
0502         if (dfp > &bf[0] &&
0503             be16_to_cpu(dfp[-1].length) < be16_to_cpu(dfp[0].length))
0504             return __this_address;
0505     }
0506 
0507     /* Looks ok so far; now try to match up with a bestfree entry. */
0508     *bf_ent = xfs_dir2_data_freefind(hdr, bf, dup);
0509     return NULL;
0510 }
0511 
0512 /*
0513  * Given a data block and an unused entry from that block,
0514  * return the bestfree entry if any that corresponds to it.
0515  */
0516 xfs_dir2_data_free_t *
0517 xfs_dir2_data_freefind(
0518     struct xfs_dir2_data_hdr *hdr,      /* data block header */
0519     struct xfs_dir2_data_free *bf,      /* bestfree table pointer */
0520     struct xfs_dir2_data_unused *dup)   /* unused space */
0521 {
0522     xfs_dir2_data_free_t    *dfp;       /* bestfree entry */
0523     xfs_dir2_data_aoff_t    off;        /* offset value needed */
0524 
0525     off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
0526 
0527     /*
0528      * If this is smaller than the smallest bestfree entry,
0529      * it can't be there since they're sorted.
0530      */
0531     if (be16_to_cpu(dup->length) <
0532         be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length))
0533         return NULL;
0534     /*
0535      * Look at the three bestfree entries for our guy.
0536      */
0537     for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
0538         if (!dfp->offset)
0539             return NULL;
0540         if (be16_to_cpu(dfp->offset) == off)
0541             return dfp;
0542     }
0543     /*
0544      * Didn't find it.  This only happens if there are duplicate lengths.
0545      */
0546     return NULL;
0547 }
0548 
0549 /*
0550  * Insert an unused-space entry into the bestfree table.
0551  */
0552 xfs_dir2_data_free_t *              /* entry inserted */
0553 xfs_dir2_data_freeinsert(
0554     struct xfs_dir2_data_hdr *hdr,      /* data block pointer */
0555     struct xfs_dir2_data_free *dfp,     /* bestfree table pointer */
0556     struct xfs_dir2_data_unused *dup,   /* unused space */
0557     int         *loghead)   /* log the data header (out) */
0558 {
0559     xfs_dir2_data_free_t    new;        /* new bestfree entry */
0560 
0561     ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
0562            hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
0563            hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
0564            hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
0565 
0566     new.length = dup->length;
0567     new.offset = cpu_to_be16((char *)dup - (char *)hdr);
0568 
0569     /*
0570      * Insert at position 0, 1, or 2; or not at all.
0571      */
0572     if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) {
0573         dfp[2] = dfp[1];
0574         dfp[1] = dfp[0];
0575         dfp[0] = new;
0576         *loghead = 1;
0577         return &dfp[0];
0578     }
0579     if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) {
0580         dfp[2] = dfp[1];
0581         dfp[1] = new;
0582         *loghead = 1;
0583         return &dfp[1];
0584     }
0585     if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) {
0586         dfp[2] = new;
0587         *loghead = 1;
0588         return &dfp[2];
0589     }
0590     return NULL;
0591 }
0592 
0593 /*
0594  * Remove a bestfree entry from the table.
0595  */
0596 STATIC void
0597 xfs_dir2_data_freeremove(
0598     struct xfs_dir2_data_hdr *hdr,      /* data block header */
0599     struct xfs_dir2_data_free *bf,      /* bestfree table pointer */
0600     struct xfs_dir2_data_free *dfp,     /* bestfree entry pointer */
0601     int         *loghead)   /* out: log data header */
0602 {
0603 
0604     ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
0605            hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
0606            hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
0607            hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
0608 
0609     /*
0610      * It's the first entry, slide the next 2 up.
0611      */
0612     if (dfp == &bf[0]) {
0613         bf[0] = bf[1];
0614         bf[1] = bf[2];
0615     }
0616     /*
0617      * It's the second entry, slide the 3rd entry up.
0618      */
0619     else if (dfp == &bf[1])
0620         bf[1] = bf[2];
0621     /*
0622      * Must be the last entry.
0623      */
0624     else
0625         ASSERT(dfp == &bf[2]);
0626     /*
0627      * Clear the 3rd entry, must be zero now.
0628      */
0629     bf[2].length = 0;
0630     bf[2].offset = 0;
0631     *loghead = 1;
0632 }
0633 
0634 /*
0635  * Given a data block, reconstruct its bestfree map.
0636  */
0637 void
0638 xfs_dir2_data_freescan(
0639     struct xfs_mount        *mp,
0640     struct xfs_dir2_data_hdr    *hdr,
0641     int             *loghead)
0642 {
0643     struct xfs_da_geometry      *geo = mp->m_dir_geo;
0644     struct xfs_dir2_data_free   *bf = xfs_dir2_data_bestfree_p(mp, hdr);
0645     void                *addr = hdr;
0646     unsigned int            offset = geo->data_entry_offset;
0647     unsigned int            end;
0648 
0649     ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
0650            hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
0651            hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
0652            hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
0653 
0654     /*
0655      * Start by clearing the table.
0656      */
0657     memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT);
0658     *loghead = 1;
0659 
0660     end = xfs_dir3_data_end_offset(geo, addr);
0661     while (offset < end) {
0662         struct xfs_dir2_data_unused *dup = addr + offset;
0663         struct xfs_dir2_data_entry  *dep = addr + offset;
0664 
0665         /*
0666          * If it's a free entry, insert it.
0667          */
0668         if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
0669             ASSERT(offset ==
0670                    be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
0671             xfs_dir2_data_freeinsert(hdr, bf, dup, loghead);
0672             offset += be16_to_cpu(dup->length);
0673             continue;
0674         }
0675 
0676         /*
0677          * For active entries, check their tags and skip them.
0678          */
0679         ASSERT(offset ==
0680                be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep)));
0681         offset += xfs_dir2_data_entsize(mp, dep->namelen);
0682     }
0683 }
0684 
0685 /*
0686  * Initialize a data block at the given block number in the directory.
0687  * Give back the buffer for the created block.
0688  */
0689 int                     /* error */
0690 xfs_dir3_data_init(
0691     struct xfs_da_args      *args,  /* directory operation args */
0692     xfs_dir2_db_t           blkno,  /* logical dir block number */
0693     struct xfs_buf          **bpp)  /* output block buffer */
0694 {
0695     struct xfs_trans        *tp = args->trans;
0696     struct xfs_inode        *dp = args->dp;
0697     struct xfs_mount        *mp = dp->i_mount;
0698     struct xfs_da_geometry      *geo = args->geo;
0699     struct xfs_buf          *bp;
0700     struct xfs_dir2_data_hdr    *hdr;
0701     struct xfs_dir2_data_unused *dup;
0702     struct xfs_dir2_data_free   *bf;
0703     int             error;
0704     int             i;
0705 
0706     /*
0707      * Get the buffer set up for the block.
0708      */
0709     error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, blkno),
0710                    &bp, XFS_DATA_FORK);
0711     if (error)
0712         return error;
0713     bp->b_ops = &xfs_dir3_data_buf_ops;
0714     xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_DATA_BUF);
0715 
0716     /*
0717      * Initialize the header.
0718      */
0719     hdr = bp->b_addr;
0720     if (xfs_has_crc(mp)) {
0721         struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
0722 
0723         memset(hdr3, 0, sizeof(*hdr3));
0724         hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);
0725         hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));
0726         hdr3->owner = cpu_to_be64(dp->i_ino);
0727         uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
0728 
0729     } else
0730         hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
0731 
0732     bf = xfs_dir2_data_bestfree_p(mp, hdr);
0733     bf[0].offset = cpu_to_be16(geo->data_entry_offset);
0734     bf[0].length = cpu_to_be16(geo->blksize - geo->data_entry_offset);
0735     for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
0736         bf[i].length = 0;
0737         bf[i].offset = 0;
0738     }
0739 
0740     /*
0741      * Set up an unused entry for the block's body.
0742      */
0743     dup = bp->b_addr + geo->data_entry_offset;
0744     dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
0745     dup->length = bf[0].length;
0746     *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr);
0747 
0748     /*
0749      * Log it and return it.
0750      */
0751     xfs_dir2_data_log_header(args, bp);
0752     xfs_dir2_data_log_unused(args, bp, dup);
0753     *bpp = bp;
0754     return 0;
0755 }
0756 
0757 /*
0758  * Log an active data entry from the block.
0759  */
0760 void
0761 xfs_dir2_data_log_entry(
0762     struct xfs_da_args  *args,
0763     struct xfs_buf      *bp,
0764     xfs_dir2_data_entry_t   *dep)       /* data entry pointer */
0765 {
0766     struct xfs_mount    *mp = bp->b_mount;
0767     struct xfs_dir2_data_hdr *hdr = bp->b_addr;
0768 
0769     ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
0770            hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
0771            hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
0772            hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
0773 
0774     xfs_trans_log_buf(args->trans, bp, (uint)((char *)dep - (char *)hdr),
0775         (uint)((char *)(xfs_dir2_data_entry_tag_p(mp, dep) + 1) -
0776                (char *)hdr - 1));
0777 }
0778 
0779 /*
0780  * Log a data block header.
0781  */
0782 void
0783 xfs_dir2_data_log_header(
0784     struct xfs_da_args  *args,
0785     struct xfs_buf      *bp)
0786 {
0787 #ifdef DEBUG
0788     struct xfs_dir2_data_hdr *hdr = bp->b_addr;
0789 
0790     ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
0791            hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
0792            hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
0793            hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
0794 #endif
0795 
0796     xfs_trans_log_buf(args->trans, bp, 0, args->geo->data_entry_offset - 1);
0797 }
0798 
0799 /*
0800  * Log a data unused entry.
0801  */
0802 void
0803 xfs_dir2_data_log_unused(
0804     struct xfs_da_args  *args,
0805     struct xfs_buf      *bp,
0806     xfs_dir2_data_unused_t  *dup)       /* data unused pointer */
0807 {
0808     xfs_dir2_data_hdr_t *hdr = bp->b_addr;
0809 
0810     ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
0811            hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
0812            hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
0813            hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
0814 
0815     /*
0816      * Log the first part of the unused entry.
0817      */
0818     xfs_trans_log_buf(args->trans, bp, (uint)((char *)dup - (char *)hdr),
0819         (uint)((char *)&dup->length + sizeof(dup->length) -
0820                1 - (char *)hdr));
0821     /*
0822      * Log the end (tag) of the unused entry.
0823      */
0824     xfs_trans_log_buf(args->trans, bp,
0825         (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr),
0826         (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr +
0827                sizeof(xfs_dir2_data_off_t) - 1));
0828 }
0829 
0830 /*
0831  * Make a byte range in the data block unused.
0832  * Its current contents are unimportant.
0833  */
0834 void
0835 xfs_dir2_data_make_free(
0836     struct xfs_da_args  *args,
0837     struct xfs_buf      *bp,
0838     xfs_dir2_data_aoff_t    offset,     /* starting byte offset */
0839     xfs_dir2_data_aoff_t    len,        /* length in bytes */
0840     int         *needlogp,  /* out: log header */
0841     int         *needscanp) /* out: regen bestfree */
0842 {
0843     xfs_dir2_data_hdr_t *hdr;       /* data block pointer */
0844     xfs_dir2_data_free_t    *dfp;       /* bestfree pointer */
0845     int         needscan;   /* need to regen bestfree */
0846     xfs_dir2_data_unused_t  *newdup;    /* new unused entry */
0847     xfs_dir2_data_unused_t  *postdup;   /* unused entry after us */
0848     xfs_dir2_data_unused_t  *prevdup;   /* unused entry before us */
0849     unsigned int        end;
0850     struct xfs_dir2_data_free *bf;
0851 
0852     hdr = bp->b_addr;
0853 
0854     /*
0855      * Figure out where the end of the data area is.
0856      */
0857     end = xfs_dir3_data_end_offset(args->geo, hdr);
0858     ASSERT(end != 0);
0859 
0860     /*
0861      * If this isn't the start of the block, then back up to
0862      * the previous entry and see if it's free.
0863      */
0864     if (offset > args->geo->data_entry_offset) {
0865         __be16          *tagp;  /* tag just before us */
0866 
0867         tagp = (__be16 *)((char *)hdr + offset) - 1;
0868         prevdup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
0869         if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
0870             prevdup = NULL;
0871     } else
0872         prevdup = NULL;
0873     /*
0874      * If this isn't the end of the block, see if the entry after
0875      * us is free.
0876      */
0877     if (offset + len < end) {
0878         postdup =
0879             (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
0880         if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
0881             postdup = NULL;
0882     } else
0883         postdup = NULL;
0884     ASSERT(*needscanp == 0);
0885     needscan = 0;
0886     /*
0887      * Previous and following entries are both free,
0888      * merge everything into a single free entry.
0889      */
0890     bf = xfs_dir2_data_bestfree_p(args->dp->i_mount, hdr);
0891     if (prevdup && postdup) {
0892         xfs_dir2_data_free_t    *dfp2;  /* another bestfree pointer */
0893 
0894         /*
0895          * See if prevdup and/or postdup are in bestfree table.
0896          */
0897         dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);
0898         dfp2 = xfs_dir2_data_freefind(hdr, bf, postdup);
0899         /*
0900          * We need a rescan unless there are exactly 2 free entries
0901          * namely our two.  Then we know what's happening, otherwise
0902          * since the third bestfree is there, there might be more
0903          * entries.
0904          */
0905         needscan = (bf[2].length != 0);
0906         /*
0907          * Fix up the new big freespace.
0908          */
0909         be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length));
0910         *xfs_dir2_data_unused_tag_p(prevdup) =
0911             cpu_to_be16((char *)prevdup - (char *)hdr);
0912         xfs_dir2_data_log_unused(args, bp, prevdup);
0913         if (!needscan) {
0914             /*
0915              * Has to be the case that entries 0 and 1 are
0916              * dfp and dfp2 (don't know which is which), and
0917              * entry 2 is empty.
0918              * Remove entry 1 first then entry 0.
0919              */
0920             ASSERT(dfp && dfp2);
0921             if (dfp == &bf[1]) {
0922                 dfp = &bf[0];
0923                 ASSERT(dfp2 == dfp);
0924                 dfp2 = &bf[1];
0925             }
0926             xfs_dir2_data_freeremove(hdr, bf, dfp2, needlogp);
0927             xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
0928             /*
0929              * Now insert the new entry.
0930              */
0931             dfp = xfs_dir2_data_freeinsert(hdr, bf, prevdup,
0932                                needlogp);
0933             ASSERT(dfp == &bf[0]);
0934             ASSERT(dfp->length == prevdup->length);
0935             ASSERT(!dfp[1].length);
0936             ASSERT(!dfp[2].length);
0937         }
0938     }
0939     /*
0940      * The entry before us is free, merge with it.
0941      */
0942     else if (prevdup) {
0943         dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);
0944         be16_add_cpu(&prevdup->length, len);
0945         *xfs_dir2_data_unused_tag_p(prevdup) =
0946             cpu_to_be16((char *)prevdup - (char *)hdr);
0947         xfs_dir2_data_log_unused(args, bp, prevdup);
0948         /*
0949          * If the previous entry was in the table, the new entry
0950          * is longer, so it will be in the table too.  Remove
0951          * the old one and add the new one.
0952          */
0953         if (dfp) {
0954             xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
0955             xfs_dir2_data_freeinsert(hdr, bf, prevdup, needlogp);
0956         }
0957         /*
0958          * Otherwise we need a scan if the new entry is big enough.
0959          */
0960         else {
0961             needscan = be16_to_cpu(prevdup->length) >
0962                    be16_to_cpu(bf[2].length);
0963         }
0964     }
0965     /*
0966      * The following entry is free, merge with it.
0967      */
0968     else if (postdup) {
0969         dfp = xfs_dir2_data_freefind(hdr, bf, postdup);
0970         newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
0971         newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
0972         newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
0973         *xfs_dir2_data_unused_tag_p(newdup) =
0974             cpu_to_be16((char *)newdup - (char *)hdr);
0975         xfs_dir2_data_log_unused(args, bp, newdup);
0976         /*
0977          * If the following entry was in the table, the new entry
0978          * is longer, so it will be in the table too.  Remove
0979          * the old one and add the new one.
0980          */
0981         if (dfp) {
0982             xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
0983             xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);
0984         }
0985         /*
0986          * Otherwise we need a scan if the new entry is big enough.
0987          */
0988         else {
0989             needscan = be16_to_cpu(newdup->length) >
0990                    be16_to_cpu(bf[2].length);
0991         }
0992     }
0993     /*
0994      * Neither neighbor is free.  Make a new entry.
0995      */
0996     else {
0997         newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
0998         newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
0999         newdup->length = cpu_to_be16(len);
1000         *xfs_dir2_data_unused_tag_p(newdup) =
1001             cpu_to_be16((char *)newdup - (char *)hdr);
1002         xfs_dir2_data_log_unused(args, bp, newdup);
1003         xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);
1004     }
1005     *needscanp = needscan;
1006 }
1007 
1008 /* Check our free data for obvious signs of corruption. */
1009 static inline xfs_failaddr_t
1010 xfs_dir2_data_check_free(
1011     struct xfs_dir2_data_hdr    *hdr,
1012     struct xfs_dir2_data_unused *dup,
1013     xfs_dir2_data_aoff_t        offset,
1014     xfs_dir2_data_aoff_t        len)
1015 {
1016     if (hdr->magic != cpu_to_be32(XFS_DIR2_DATA_MAGIC) &&
1017         hdr->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC) &&
1018         hdr->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) &&
1019         hdr->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC))
1020         return __this_address;
1021     if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG)
1022         return __this_address;
1023     if (offset < (char *)dup - (char *)hdr)
1024         return __this_address;
1025     if (offset + len > (char *)dup + be16_to_cpu(dup->length) - (char *)hdr)
1026         return __this_address;
1027     if ((char *)dup - (char *)hdr !=
1028             be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)))
1029         return __this_address;
1030     return NULL;
1031 }
1032 
1033 /* Sanity-check a new bestfree entry. */
1034 static inline xfs_failaddr_t
1035 xfs_dir2_data_check_new_free(
1036     struct xfs_dir2_data_hdr    *hdr,
1037     struct xfs_dir2_data_free   *dfp,
1038     struct xfs_dir2_data_unused *newdup)
1039 {
1040     if (dfp == NULL)
1041         return __this_address;
1042     if (dfp->length != newdup->length)
1043         return __this_address;
1044     if (be16_to_cpu(dfp->offset) != (char *)newdup - (char *)hdr)
1045         return __this_address;
1046     return NULL;
1047 }
1048 
1049 /*
1050  * Take a byte range out of an existing unused space and make it un-free.
1051  */
1052 int
1053 xfs_dir2_data_use_free(
1054     struct xfs_da_args  *args,
1055     struct xfs_buf      *bp,
1056     xfs_dir2_data_unused_t  *dup,       /* unused entry */
1057     xfs_dir2_data_aoff_t    offset,     /* starting offset to use */
1058     xfs_dir2_data_aoff_t    len,        /* length to use */
1059     int         *needlogp,  /* out: need to log header */
1060     int         *needscanp) /* out: need regen bestfree */
1061 {
1062     xfs_dir2_data_hdr_t *hdr;       /* data block header */
1063     xfs_dir2_data_free_t    *dfp;       /* bestfree pointer */
1064     xfs_dir2_data_unused_t  *newdup;    /* new unused entry */
1065     xfs_dir2_data_unused_t  *newdup2;   /* another new unused entry */
1066     struct xfs_dir2_data_free *bf;
1067     xfs_failaddr_t      fa;
1068     int         matchback;  /* matches end of freespace */
1069     int         matchfront; /* matches start of freespace */
1070     int         needscan;   /* need to regen bestfree */
1071     int         oldlen;     /* old unused entry's length */
1072 
1073     hdr = bp->b_addr;
1074     fa = xfs_dir2_data_check_free(hdr, dup, offset, len);
1075     if (fa)
1076         goto corrupt;
1077     /*
1078      * Look up the entry in the bestfree table.
1079      */
1080     oldlen = be16_to_cpu(dup->length);
1081     bf = xfs_dir2_data_bestfree_p(args->dp->i_mount, hdr);
1082     dfp = xfs_dir2_data_freefind(hdr, bf, dup);
1083     ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length));
1084     /*
1085      * Check for alignment with front and back of the entry.
1086      */
1087     matchfront = (char *)dup - (char *)hdr == offset;
1088     matchback = (char *)dup + oldlen - (char *)hdr == offset + len;
1089     ASSERT(*needscanp == 0);
1090     needscan = 0;
1091     /*
1092      * If we matched it exactly we just need to get rid of it from
1093      * the bestfree table.
1094      */
1095     if (matchfront && matchback) {
1096         if (dfp) {
1097             needscan = (bf[2].offset != 0);
1098             if (!needscan)
1099                 xfs_dir2_data_freeremove(hdr, bf, dfp,
1100                              needlogp);
1101         }
1102     }
1103     /*
1104      * We match the first part of the entry.
1105      * Make a new entry with the remaining freespace.
1106      */
1107     else if (matchfront) {
1108         newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
1109         newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
1110         newdup->length = cpu_to_be16(oldlen - len);
1111         *xfs_dir2_data_unused_tag_p(newdup) =
1112             cpu_to_be16((char *)newdup - (char *)hdr);
1113         xfs_dir2_data_log_unused(args, bp, newdup);
1114         /*
1115          * If it was in the table, remove it and add the new one.
1116          */
1117         if (dfp) {
1118             xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
1119             dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,
1120                                needlogp);
1121             fa = xfs_dir2_data_check_new_free(hdr, dfp, newdup);
1122             if (fa)
1123                 goto corrupt;
1124             /*
1125              * If we got inserted at the last slot,
1126              * that means we don't know if there was a better
1127              * choice for the last slot, or not.  Rescan.
1128              */
1129             needscan = dfp == &bf[2];
1130         }
1131     }
1132     /*
1133      * We match the last part of the entry.
1134      * Trim the allocated space off the tail of the entry.
1135      */
1136     else if (matchback) {
1137         newdup = dup;
1138         newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
1139         *xfs_dir2_data_unused_tag_p(newdup) =
1140             cpu_to_be16((char *)newdup - (char *)hdr);
1141         xfs_dir2_data_log_unused(args, bp, newdup);
1142         /*
1143          * If it was in the table, remove it and add the new one.
1144          */
1145         if (dfp) {
1146             xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
1147             dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,
1148                                needlogp);
1149             fa = xfs_dir2_data_check_new_free(hdr, dfp, newdup);
1150             if (fa)
1151                 goto corrupt;
1152             /*
1153              * If we got inserted at the last slot,
1154              * that means we don't know if there was a better
1155              * choice for the last slot, or not.  Rescan.
1156              */
1157             needscan = dfp == &bf[2];
1158         }
1159     }
1160     /*
1161      * Poking out the middle of an entry.
1162      * Make two new entries.
1163      */
1164     else {
1165         newdup = dup;
1166         newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
1167         *xfs_dir2_data_unused_tag_p(newdup) =
1168             cpu_to_be16((char *)newdup - (char *)hdr);
1169         xfs_dir2_data_log_unused(args, bp, newdup);
1170         newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
1171         newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
1172         newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
1173         *xfs_dir2_data_unused_tag_p(newdup2) =
1174             cpu_to_be16((char *)newdup2 - (char *)hdr);
1175         xfs_dir2_data_log_unused(args, bp, newdup2);
1176         /*
1177          * If the old entry was in the table, we need to scan
1178          * if the 3rd entry was valid, since these entries
1179          * are smaller than the old one.
1180          * If we don't need to scan that means there were 1 or 2
1181          * entries in the table, and removing the old and adding
1182          * the 2 new will work.
1183          */
1184         if (dfp) {
1185             needscan = (bf[2].length != 0);
1186             if (!needscan) {
1187                 xfs_dir2_data_freeremove(hdr, bf, dfp,
1188                              needlogp);
1189                 xfs_dir2_data_freeinsert(hdr, bf, newdup,
1190                              needlogp);
1191                 xfs_dir2_data_freeinsert(hdr, bf, newdup2,
1192                              needlogp);
1193             }
1194         }
1195     }
1196     *needscanp = needscan;
1197     return 0;
1198 corrupt:
1199     xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount,
1200             hdr, sizeof(*hdr), __FILE__, __LINE__, fa);
1201     return -EFSCORRUPTED;
1202 }
1203 
1204 /* Find the end of the entry data in a data/block format dir block. */
1205 unsigned int
1206 xfs_dir3_data_end_offset(
1207     struct xfs_da_geometry      *geo,
1208     struct xfs_dir2_data_hdr    *hdr)
1209 {
1210     void                *p;
1211 
1212     switch (hdr->magic) {
1213     case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
1214     case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
1215         p = xfs_dir2_block_leaf_p(xfs_dir2_block_tail_p(geo, hdr));
1216         return p - (void *)hdr;
1217     case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
1218     case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
1219         return geo->blksize;
1220     default:
1221         return 0;
1222     }
1223 }