~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/xfs/libxfs/xfs_dir2_data.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php