xfs: factor out dir2 data block reading
[firefly-linux-kernel-4.4.55.git] / fs / xfs / xfs_dir2_data.c
1 /*
2  * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_types.h"
21 #include "xfs_log.h"
22 #include "xfs_trans.h"
23 #include "xfs_sb.h"
24 #include "xfs_ag.h"
25 #include "xfs_mount.h"
26 #include "xfs_da_btree.h"
27 #include "xfs_bmap_btree.h"
28 #include "xfs_dinode.h"
29 #include "xfs_inode.h"
30 #include "xfs_dir2_format.h"
31 #include "xfs_dir2_priv.h"
32 #include "xfs_error.h"
33
34 STATIC xfs_dir2_data_free_t *
35 xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup);
36
37 /*
38  * Check the consistency of the data block.
39  * The input can also be a block-format directory.
40  * Return 0 is the buffer is good, otherwise an error.
41  */
42 int
43 __xfs_dir2_data_check(
44         struct xfs_inode        *dp,            /* incore inode pointer */
45         struct xfs_buf          *bp)            /* data block's buffer */
46 {
47         xfs_dir2_dataptr_t      addr;           /* addr for leaf lookup */
48         xfs_dir2_data_free_t    *bf;            /* bestfree table */
49         xfs_dir2_block_tail_t   *btp=NULL;      /* block tail */
50         int                     count;          /* count of entries found */
51         xfs_dir2_data_hdr_t     *hdr;           /* data block header */
52         xfs_dir2_data_entry_t   *dep;           /* data entry */
53         xfs_dir2_data_free_t    *dfp;           /* bestfree entry */
54         xfs_dir2_data_unused_t  *dup;           /* unused entry */
55         char                    *endp;          /* end of useful data */
56         int                     freeseen;       /* mask of bestfrees seen */
57         xfs_dahash_t            hash;           /* hash of current name */
58         int                     i;              /* leaf index */
59         int                     lastfree;       /* last entry was unused */
60         xfs_dir2_leaf_entry_t   *lep=NULL;      /* block leaf entries */
61         xfs_mount_t             *mp;            /* filesystem mount point */
62         char                    *p;             /* current data position */
63         int                     stale;          /* count of stale leaves */
64         struct xfs_name         name;
65
66         mp = bp->b_target->bt_mount;
67         hdr = bp->b_addr;
68         bf = hdr->bestfree;
69         p = (char *)(hdr + 1);
70
71         switch (hdr->magic) {
72         case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
73                 btp = xfs_dir2_block_tail_p(mp, hdr);
74                 lep = xfs_dir2_block_leaf_p(btp);
75                 endp = (char *)lep;
76                 break;
77         case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
78                 endp = (char *)hdr + mp->m_dirblksize;
79                 break;
80         default:
81                 XFS_ERROR_REPORT("Bad Magic", XFS_ERRLEVEL_LOW, mp);
82                 return EFSCORRUPTED;
83         }
84
85         count = lastfree = freeseen = 0;
86         /*
87          * Account for zero bestfree entries.
88          */
89         if (!bf[0].length) {
90                 XFS_WANT_CORRUPTED_RETURN(!bf[0].offset);
91                 freeseen |= 1 << 0;
92         }
93         if (!bf[1].length) {
94                 XFS_WANT_CORRUPTED_RETURN(!bf[1].offset);
95                 freeseen |= 1 << 1;
96         }
97         if (!bf[2].length) {
98                 XFS_WANT_CORRUPTED_RETURN(!bf[2].offset);
99                 freeseen |= 1 << 2;
100         }
101
102         XFS_WANT_CORRUPTED_RETURN(be16_to_cpu(bf[0].length) >=
103                                                 be16_to_cpu(bf[1].length));
104         XFS_WANT_CORRUPTED_RETURN(be16_to_cpu(bf[1].length) >=
105                                                 be16_to_cpu(bf[2].length));
106         /*
107          * Loop over the data/unused entries.
108          */
109         while (p < endp) {
110                 dup = (xfs_dir2_data_unused_t *)p;
111                 /*
112                  * If it's unused, look for the space in the bestfree table.
113                  * If we find it, account for that, else make sure it
114                  * doesn't need to be there.
115                  */
116                 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
117                         XFS_WANT_CORRUPTED_RETURN(lastfree == 0);
118                         XFS_WANT_CORRUPTED_RETURN(
119                                 be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
120                                                (char *)dup - (char *)hdr);
121                         dfp = xfs_dir2_data_freefind(hdr, dup);
122                         if (dfp) {
123                                 i = (int)(dfp - bf);
124                                 XFS_WANT_CORRUPTED_RETURN(
125                                         (freeseen & (1 << i)) == 0);
126                                 freeseen |= 1 << i;
127                         } else {
128                                 XFS_WANT_CORRUPTED_RETURN(
129                                         be16_to_cpu(dup->length) <=
130                                                 be16_to_cpu(bf[2].length));
131                         }
132                         p += be16_to_cpu(dup->length);
133                         lastfree = 1;
134                         continue;
135                 }
136                 /*
137                  * It's a real entry.  Validate the fields.
138                  * If this is a block directory then make sure it's
139                  * in the leaf section of the block.
140                  * The linear search is crude but this is DEBUG code.
141                  */
142                 dep = (xfs_dir2_data_entry_t *)p;
143                 XFS_WANT_CORRUPTED_RETURN(dep->namelen != 0);
144                 XFS_WANT_CORRUPTED_RETURN(
145                         !xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)));
146                 XFS_WANT_CORRUPTED_RETURN(
147                         be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)) ==
148                                                (char *)dep - (char *)hdr);
149                 count++;
150                 lastfree = 0;
151                 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
152                         addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
153                                 (xfs_dir2_data_aoff_t)
154                                 ((char *)dep - (char *)hdr));
155                         name.name = dep->name;
156                         name.len = dep->namelen;
157                         hash = mp->m_dirnameops->hashname(&name);
158                         for (i = 0; i < be32_to_cpu(btp->count); i++) {
159                                 if (be32_to_cpu(lep[i].address) == addr &&
160                                     be32_to_cpu(lep[i].hashval) == hash)
161                                         break;
162                         }
163                         XFS_WANT_CORRUPTED_RETURN(i < be32_to_cpu(btp->count));
164                 }
165                 p += xfs_dir2_data_entsize(dep->namelen);
166         }
167         /*
168          * Need to have seen all the entries and all the bestfree slots.
169          */
170         XFS_WANT_CORRUPTED_RETURN(freeseen == 7);
171         if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
172                 for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
173                         if (lep[i].address ==
174                             cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
175                                 stale++;
176                         if (i > 0)
177                                 XFS_WANT_CORRUPTED_RETURN(
178                                         be32_to_cpu(lep[i].hashval) >=
179                                                 be32_to_cpu(lep[i - 1].hashval));
180                 }
181                 XFS_WANT_CORRUPTED_RETURN(count ==
182                         be32_to_cpu(btp->count) - be32_to_cpu(btp->stale));
183                 XFS_WANT_CORRUPTED_RETURN(stale == be32_to_cpu(btp->stale));
184         }
185         return 0;
186 }
187
188 static void
189 xfs_dir2_data_verify(
190         struct xfs_buf          *bp)
191 {
192         struct xfs_mount        *mp = bp->b_target->bt_mount;
193         struct xfs_dir2_data_hdr *hdr = bp->b_addr;
194         int                     block_ok = 0;
195
196         block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC);
197         block_ok = block_ok && __xfs_dir2_data_check(NULL, bp) == 0;
198
199         if (!block_ok) {
200                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
201                 xfs_buf_ioerror(bp, EFSCORRUPTED);
202         }
203
204         bp->b_iodone = NULL;
205         xfs_buf_ioend(bp, 0);
206 }
207
208 int
209 xfs_dir2_data_read(
210         struct xfs_trans        *tp,
211         struct xfs_inode        *dp,
212         xfs_dablk_t             bno,
213         xfs_daddr_t             mapped_bno,
214         struct xfs_buf          **bpp)
215 {
216         return xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp,
217                                         XFS_DATA_FORK, xfs_dir2_data_verify);
218 }
219
220 /*
221  * Given a data block and an unused entry from that block,
222  * return the bestfree entry if any that corresponds to it.
223  */
224 STATIC xfs_dir2_data_free_t *
225 xfs_dir2_data_freefind(
226         xfs_dir2_data_hdr_t     *hdr,           /* data block */
227         xfs_dir2_data_unused_t  *dup)           /* data unused entry */
228 {
229         xfs_dir2_data_free_t    *dfp;           /* bestfree entry */
230         xfs_dir2_data_aoff_t    off;            /* offset value needed */
231 #if defined(DEBUG) && defined(__KERNEL__)
232         int                     matched;        /* matched the value */
233         int                     seenzero;       /* saw a 0 bestfree entry */
234 #endif
235
236         off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
237 #if defined(DEBUG) && defined(__KERNEL__)
238         /*
239          * Validate some consistency in the bestfree table.
240          * Check order, non-overlapping entries, and if we find the
241          * one we're looking for it has to be exact.
242          */
243         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
244                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
245         for (dfp = &hdr->bestfree[0], seenzero = matched = 0;
246              dfp < &hdr->bestfree[XFS_DIR2_DATA_FD_COUNT];
247              dfp++) {
248                 if (!dfp->offset) {
249                         ASSERT(!dfp->length);
250                         seenzero = 1;
251                         continue;
252                 }
253                 ASSERT(seenzero == 0);
254                 if (be16_to_cpu(dfp->offset) == off) {
255                         matched = 1;
256                         ASSERT(dfp->length == dup->length);
257                 } else if (off < be16_to_cpu(dfp->offset))
258                         ASSERT(off + be16_to_cpu(dup->length) <= be16_to_cpu(dfp->offset));
259                 else
260                         ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off);
261                 ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length));
262                 if (dfp > &hdr->bestfree[0])
263                         ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length));
264         }
265 #endif
266         /*
267          * If this is smaller than the smallest bestfree entry,
268          * it can't be there since they're sorted.
269          */
270         if (be16_to_cpu(dup->length) <
271             be16_to_cpu(hdr->bestfree[XFS_DIR2_DATA_FD_COUNT - 1].length))
272                 return NULL;
273         /*
274          * Look at the three bestfree entries for our guy.
275          */
276         for (dfp = &hdr->bestfree[0];
277              dfp < &hdr->bestfree[XFS_DIR2_DATA_FD_COUNT];
278              dfp++) {
279                 if (!dfp->offset)
280                         return NULL;
281                 if (be16_to_cpu(dfp->offset) == off)
282                         return dfp;
283         }
284         /*
285          * Didn't find it.  This only happens if there are duplicate lengths.
286          */
287         return NULL;
288 }
289
290 /*
291  * Insert an unused-space entry into the bestfree table.
292  */
293 xfs_dir2_data_free_t *                          /* entry inserted */
294 xfs_dir2_data_freeinsert(
295         xfs_dir2_data_hdr_t     *hdr,           /* data block pointer */
296         xfs_dir2_data_unused_t  *dup,           /* unused space */
297         int                     *loghead)       /* log the data header (out) */
298 {
299         xfs_dir2_data_free_t    *dfp;           /* bestfree table pointer */
300         xfs_dir2_data_free_t    new;            /* new bestfree entry */
301
302 #ifdef __KERNEL__
303         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
304                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
305 #endif
306         dfp = hdr->bestfree;
307         new.length = dup->length;
308         new.offset = cpu_to_be16((char *)dup - (char *)hdr);
309
310         /*
311          * Insert at position 0, 1, or 2; or not at all.
312          */
313         if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) {
314                 dfp[2] = dfp[1];
315                 dfp[1] = dfp[0];
316                 dfp[0] = new;
317                 *loghead = 1;
318                 return &dfp[0];
319         }
320         if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) {
321                 dfp[2] = dfp[1];
322                 dfp[1] = new;
323                 *loghead = 1;
324                 return &dfp[1];
325         }
326         if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) {
327                 dfp[2] = new;
328                 *loghead = 1;
329                 return &dfp[2];
330         }
331         return NULL;
332 }
333
334 /*
335  * Remove a bestfree entry from the table.
336  */
337 STATIC void
338 xfs_dir2_data_freeremove(
339         xfs_dir2_data_hdr_t     *hdr,           /* data block header */
340         xfs_dir2_data_free_t    *dfp,           /* bestfree entry pointer */
341         int                     *loghead)       /* out: log data header */
342 {
343 #ifdef __KERNEL__
344         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
345                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
346 #endif
347         /*
348          * It's the first entry, slide the next 2 up.
349          */
350         if (dfp == &hdr->bestfree[0]) {
351                 hdr->bestfree[0] = hdr->bestfree[1];
352                 hdr->bestfree[1] = hdr->bestfree[2];
353         }
354         /*
355          * It's the second entry, slide the 3rd entry up.
356          */
357         else if (dfp == &hdr->bestfree[1])
358                 hdr->bestfree[1] = hdr->bestfree[2];
359         /*
360          * Must be the last entry.
361          */
362         else
363                 ASSERT(dfp == &hdr->bestfree[2]);
364         /*
365          * Clear the 3rd entry, must be zero now.
366          */
367         hdr->bestfree[2].length = 0;
368         hdr->bestfree[2].offset = 0;
369         *loghead = 1;
370 }
371
372 /*
373  * Given a data block, reconstruct its bestfree map.
374  */
375 void
376 xfs_dir2_data_freescan(
377         xfs_mount_t             *mp,            /* filesystem mount point */
378         xfs_dir2_data_hdr_t     *hdr,           /* data block header */
379         int                     *loghead)       /* out: log data header */
380 {
381         xfs_dir2_block_tail_t   *btp;           /* block tail */
382         xfs_dir2_data_entry_t   *dep;           /* active data entry */
383         xfs_dir2_data_unused_t  *dup;           /* unused data entry */
384         char                    *endp;          /* end of block's data */
385         char                    *p;             /* current entry pointer */
386
387 #ifdef __KERNEL__
388         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
389                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
390 #endif
391         /*
392          * Start by clearing the table.
393          */
394         memset(hdr->bestfree, 0, sizeof(hdr->bestfree));
395         *loghead = 1;
396         /*
397          * Set up pointers.
398          */
399         p = (char *)(hdr + 1);
400         if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
401                 btp = xfs_dir2_block_tail_p(mp, hdr);
402                 endp = (char *)xfs_dir2_block_leaf_p(btp);
403         } else
404                 endp = (char *)hdr + mp->m_dirblksize;
405         /*
406          * Loop over the block's entries.
407          */
408         while (p < endp) {
409                 dup = (xfs_dir2_data_unused_t *)p;
410                 /*
411                  * If it's a free entry, insert it.
412                  */
413                 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
414                         ASSERT((char *)dup - (char *)hdr ==
415                                be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
416                         xfs_dir2_data_freeinsert(hdr, dup, loghead);
417                         p += be16_to_cpu(dup->length);
418                 }
419                 /*
420                  * For active entries, check their tags and skip them.
421                  */
422                 else {
423                         dep = (xfs_dir2_data_entry_t *)p;
424                         ASSERT((char *)dep - (char *)hdr ==
425                                be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)));
426                         p += xfs_dir2_data_entsize(dep->namelen);
427                 }
428         }
429 }
430
431 /*
432  * Initialize a data block at the given block number in the directory.
433  * Give back the buffer for the created block.
434  */
435 int                                             /* error */
436 xfs_dir2_data_init(
437         xfs_da_args_t           *args,          /* directory operation args */
438         xfs_dir2_db_t           blkno,          /* logical dir block number */
439         struct xfs_buf          **bpp)          /* output block buffer */
440 {
441         struct xfs_buf          *bp;            /* block buffer */
442         xfs_dir2_data_hdr_t     *hdr;           /* data block header */
443         xfs_inode_t             *dp;            /* incore directory inode */
444         xfs_dir2_data_unused_t  *dup;           /* unused entry pointer */
445         int                     error;          /* error return value */
446         int                     i;              /* bestfree index */
447         xfs_mount_t             *mp;            /* filesystem mount point */
448         xfs_trans_t             *tp;            /* transaction pointer */
449         int                     t;              /* temp */
450
451         dp = args->dp;
452         mp = dp->i_mount;
453         tp = args->trans;
454         /*
455          * Get the buffer set up for the block.
456          */
457         error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, blkno), -1, &bp,
458                 XFS_DATA_FORK);
459         if (error) {
460                 return error;
461         }
462         ASSERT(bp != NULL);
463
464         /*
465          * Initialize the header.
466          */
467         hdr = bp->b_addr;
468         hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
469         hdr->bestfree[0].offset = cpu_to_be16(sizeof(*hdr));
470         for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
471                 hdr->bestfree[i].length = 0;
472                 hdr->bestfree[i].offset = 0;
473         }
474
475         /*
476          * Set up an unused entry for the block's body.
477          */
478         dup = (xfs_dir2_data_unused_t *)(hdr + 1);
479         dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
480
481         t = mp->m_dirblksize - (uint)sizeof(*hdr);
482         hdr->bestfree[0].length = cpu_to_be16(t);
483         dup->length = cpu_to_be16(t);
484         *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr);
485         /*
486          * Log it and return it.
487          */
488         xfs_dir2_data_log_header(tp, bp);
489         xfs_dir2_data_log_unused(tp, bp, dup);
490         *bpp = bp;
491         return 0;
492 }
493
494 /*
495  * Log an active data entry from the block.
496  */
497 void
498 xfs_dir2_data_log_entry(
499         struct xfs_trans        *tp,
500         struct xfs_buf          *bp,
501         xfs_dir2_data_entry_t   *dep)           /* data entry pointer */
502 {
503         xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
504
505         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
506                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
507
508         xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr),
509                 (uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) -
510                        (char *)hdr - 1));
511 }
512
513 /*
514  * Log a data block header.
515  */
516 void
517 xfs_dir2_data_log_header(
518         struct xfs_trans        *tp,
519         struct xfs_buf          *bp)
520 {
521         xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
522
523         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
524                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
525
526         xfs_trans_log_buf(tp, bp, 0, sizeof(*hdr) - 1);
527 }
528
529 /*
530  * Log a data unused entry.
531  */
532 void
533 xfs_dir2_data_log_unused(
534         struct xfs_trans        *tp,
535         struct xfs_buf          *bp,
536         xfs_dir2_data_unused_t  *dup)           /* data unused pointer */
537 {
538         xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
539
540         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
541                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
542
543         /*
544          * Log the first part of the unused entry.
545          */
546         xfs_trans_log_buf(tp, bp, (uint)((char *)dup - (char *)hdr),
547                 (uint)((char *)&dup->length + sizeof(dup->length) -
548                        1 - (char *)hdr));
549         /*
550          * Log the end (tag) of the unused entry.
551          */
552         xfs_trans_log_buf(tp, bp,
553                 (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr),
554                 (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr +
555                        sizeof(xfs_dir2_data_off_t) - 1));
556 }
557
558 /*
559  * Make a byte range in the data block unused.
560  * Its current contents are unimportant.
561  */
562 void
563 xfs_dir2_data_make_free(
564         struct xfs_trans        *tp,
565         struct xfs_buf          *bp,
566         xfs_dir2_data_aoff_t    offset,         /* starting byte offset */
567         xfs_dir2_data_aoff_t    len,            /* length in bytes */
568         int                     *needlogp,      /* out: log header */
569         int                     *needscanp)     /* out: regen bestfree */
570 {
571         xfs_dir2_data_hdr_t     *hdr;           /* data block pointer */
572         xfs_dir2_data_free_t    *dfp;           /* bestfree pointer */
573         char                    *endptr;        /* end of data area */
574         xfs_mount_t             *mp;            /* filesystem mount point */
575         int                     needscan;       /* need to regen bestfree */
576         xfs_dir2_data_unused_t  *newdup;        /* new unused entry */
577         xfs_dir2_data_unused_t  *postdup;       /* unused entry after us */
578         xfs_dir2_data_unused_t  *prevdup;       /* unused entry before us */
579
580         mp = tp->t_mountp;
581         hdr = bp->b_addr;
582
583         /*
584          * Figure out where the end of the data area is.
585          */
586         if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC))
587                 endptr = (char *)hdr + mp->m_dirblksize;
588         else {
589                 xfs_dir2_block_tail_t   *btp;   /* block tail */
590
591                 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
592                 btp = xfs_dir2_block_tail_p(mp, hdr);
593                 endptr = (char *)xfs_dir2_block_leaf_p(btp);
594         }
595         /*
596          * If this isn't the start of the block, then back up to
597          * the previous entry and see if it's free.
598          */
599         if (offset > sizeof(*hdr)) {
600                 __be16                  *tagp;  /* tag just before us */
601
602                 tagp = (__be16 *)((char *)hdr + offset) - 1;
603                 prevdup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
604                 if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
605                         prevdup = NULL;
606         } else
607                 prevdup = NULL;
608         /*
609          * If this isn't the end of the block, see if the entry after
610          * us is free.
611          */
612         if ((char *)hdr + offset + len < endptr) {
613                 postdup =
614                         (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
615                 if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
616                         postdup = NULL;
617         } else
618                 postdup = NULL;
619         ASSERT(*needscanp == 0);
620         needscan = 0;
621         /*
622          * Previous and following entries are both free,
623          * merge everything into a single free entry.
624          */
625         if (prevdup && postdup) {
626                 xfs_dir2_data_free_t    *dfp2;  /* another bestfree pointer */
627
628                 /*
629                  * See if prevdup and/or postdup are in bestfree table.
630                  */
631                 dfp = xfs_dir2_data_freefind(hdr, prevdup);
632                 dfp2 = xfs_dir2_data_freefind(hdr, postdup);
633                 /*
634                  * We need a rescan unless there are exactly 2 free entries
635                  * namely our two.  Then we know what's happening, otherwise
636                  * since the third bestfree is there, there might be more
637                  * entries.
638                  */
639                 needscan = (hdr->bestfree[2].length != 0);
640                 /*
641                  * Fix up the new big freespace.
642                  */
643                 be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length));
644                 *xfs_dir2_data_unused_tag_p(prevdup) =
645                         cpu_to_be16((char *)prevdup - (char *)hdr);
646                 xfs_dir2_data_log_unused(tp, bp, prevdup);
647                 if (!needscan) {
648                         /*
649                          * Has to be the case that entries 0 and 1 are
650                          * dfp and dfp2 (don't know which is which), and
651                          * entry 2 is empty.
652                          * Remove entry 1 first then entry 0.
653                          */
654                         ASSERT(dfp && dfp2);
655                         if (dfp == &hdr->bestfree[1]) {
656                                 dfp = &hdr->bestfree[0];
657                                 ASSERT(dfp2 == dfp);
658                                 dfp2 = &hdr->bestfree[1];
659                         }
660                         xfs_dir2_data_freeremove(hdr, dfp2, needlogp);
661                         xfs_dir2_data_freeremove(hdr, dfp, needlogp);
662                         /*
663                          * Now insert the new entry.
664                          */
665                         dfp = xfs_dir2_data_freeinsert(hdr, prevdup, needlogp);
666                         ASSERT(dfp == &hdr->bestfree[0]);
667                         ASSERT(dfp->length == prevdup->length);
668                         ASSERT(!dfp[1].length);
669                         ASSERT(!dfp[2].length);
670                 }
671         }
672         /*
673          * The entry before us is free, merge with it.
674          */
675         else if (prevdup) {
676                 dfp = xfs_dir2_data_freefind(hdr, prevdup);
677                 be16_add_cpu(&prevdup->length, len);
678                 *xfs_dir2_data_unused_tag_p(prevdup) =
679                         cpu_to_be16((char *)prevdup - (char *)hdr);
680                 xfs_dir2_data_log_unused(tp, bp, prevdup);
681                 /*
682                  * If the previous entry was in the table, the new entry
683                  * is longer, so it will be in the table too.  Remove
684                  * the old one and add the new one.
685                  */
686                 if (dfp) {
687                         xfs_dir2_data_freeremove(hdr, dfp, needlogp);
688                         xfs_dir2_data_freeinsert(hdr, prevdup, needlogp);
689                 }
690                 /*
691                  * Otherwise we need a scan if the new entry is big enough.
692                  */
693                 else {
694                         needscan = be16_to_cpu(prevdup->length) >
695                                    be16_to_cpu(hdr->bestfree[2].length);
696                 }
697         }
698         /*
699          * The following entry is free, merge with it.
700          */
701         else if (postdup) {
702                 dfp = xfs_dir2_data_freefind(hdr, postdup);
703                 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
704                 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
705                 newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
706                 *xfs_dir2_data_unused_tag_p(newdup) =
707                         cpu_to_be16((char *)newdup - (char *)hdr);
708                 xfs_dir2_data_log_unused(tp, bp, newdup);
709                 /*
710                  * If the following entry was in the table, the new entry
711                  * is longer, so it will be in the table too.  Remove
712                  * the old one and add the new one.
713                  */
714                 if (dfp) {
715                         xfs_dir2_data_freeremove(hdr, dfp, needlogp);
716                         xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
717                 }
718                 /*
719                  * Otherwise we need a scan if the new entry is big enough.
720                  */
721                 else {
722                         needscan = be16_to_cpu(newdup->length) >
723                                    be16_to_cpu(hdr->bestfree[2].length);
724                 }
725         }
726         /*
727          * Neither neighbor is free.  Make a new entry.
728          */
729         else {
730                 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
731                 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
732                 newdup->length = cpu_to_be16(len);
733                 *xfs_dir2_data_unused_tag_p(newdup) =
734                         cpu_to_be16((char *)newdup - (char *)hdr);
735                 xfs_dir2_data_log_unused(tp, bp, newdup);
736                 xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
737         }
738         *needscanp = needscan;
739 }
740
741 /*
742  * Take a byte range out of an existing unused space and make it un-free.
743  */
744 void
745 xfs_dir2_data_use_free(
746         struct xfs_trans        *tp,
747         struct xfs_buf          *bp,
748         xfs_dir2_data_unused_t  *dup,           /* unused entry */
749         xfs_dir2_data_aoff_t    offset,         /* starting offset to use */
750         xfs_dir2_data_aoff_t    len,            /* length to use */
751         int                     *needlogp,      /* out: need to log header */
752         int                     *needscanp)     /* out: need regen bestfree */
753 {
754         xfs_dir2_data_hdr_t     *hdr;           /* data block header */
755         xfs_dir2_data_free_t    *dfp;           /* bestfree pointer */
756         int                     matchback;      /* matches end of freespace */
757         int                     matchfront;     /* matches start of freespace */
758         int                     needscan;       /* need to regen bestfree */
759         xfs_dir2_data_unused_t  *newdup;        /* new unused entry */
760         xfs_dir2_data_unused_t  *newdup2;       /* another new unused entry */
761         int                     oldlen;         /* old unused entry's length */
762
763         hdr = bp->b_addr;
764         ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
765                hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
766         ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
767         ASSERT(offset >= (char *)dup - (char *)hdr);
768         ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)hdr);
769         ASSERT((char *)dup - (char *)hdr == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
770         /*
771          * Look up the entry in the bestfree table.
772          */
773         dfp = xfs_dir2_data_freefind(hdr, dup);
774         oldlen = be16_to_cpu(dup->length);
775         ASSERT(dfp || oldlen <= be16_to_cpu(hdr->bestfree[2].length));
776         /*
777          * Check for alignment with front and back of the entry.
778          */
779         matchfront = (char *)dup - (char *)hdr == offset;
780         matchback = (char *)dup + oldlen - (char *)hdr == offset + len;
781         ASSERT(*needscanp == 0);
782         needscan = 0;
783         /*
784          * If we matched it exactly we just need to get rid of it from
785          * the bestfree table.
786          */
787         if (matchfront && matchback) {
788                 if (dfp) {
789                         needscan = (hdr->bestfree[2].offset != 0);
790                         if (!needscan)
791                                 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
792                 }
793         }
794         /*
795          * We match the first part of the entry.
796          * Make a new entry with the remaining freespace.
797          */
798         else if (matchfront) {
799                 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
800                 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
801                 newdup->length = cpu_to_be16(oldlen - len);
802                 *xfs_dir2_data_unused_tag_p(newdup) =
803                         cpu_to_be16((char *)newdup - (char *)hdr);
804                 xfs_dir2_data_log_unused(tp, bp, newdup);
805                 /*
806                  * If it was in the table, remove it and add the new one.
807                  */
808                 if (dfp) {
809                         xfs_dir2_data_freeremove(hdr, dfp, needlogp);
810                         dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
811                         ASSERT(dfp != NULL);
812                         ASSERT(dfp->length == newdup->length);
813                         ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr);
814                         /*
815                          * If we got inserted at the last slot,
816                          * that means we don't know if there was a better
817                          * choice for the last slot, or not.  Rescan.
818                          */
819                         needscan = dfp == &hdr->bestfree[2];
820                 }
821         }
822         /*
823          * We match the last part of the entry.
824          * Trim the allocated space off the tail of the entry.
825          */
826         else if (matchback) {
827                 newdup = dup;
828                 newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
829                 *xfs_dir2_data_unused_tag_p(newdup) =
830                         cpu_to_be16((char *)newdup - (char *)hdr);
831                 xfs_dir2_data_log_unused(tp, bp, newdup);
832                 /*
833                  * If it was in the table, remove it and add the new one.
834                  */
835                 if (dfp) {
836                         xfs_dir2_data_freeremove(hdr, dfp, needlogp);
837                         dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
838                         ASSERT(dfp != NULL);
839                         ASSERT(dfp->length == newdup->length);
840                         ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr);
841                         /*
842                          * If we got inserted at the last slot,
843                          * that means we don't know if there was a better
844                          * choice for the last slot, or not.  Rescan.
845                          */
846                         needscan = dfp == &hdr->bestfree[2];
847                 }
848         }
849         /*
850          * Poking out the middle of an entry.
851          * Make two new entries.
852          */
853         else {
854                 newdup = dup;
855                 newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
856                 *xfs_dir2_data_unused_tag_p(newdup) =
857                         cpu_to_be16((char *)newdup - (char *)hdr);
858                 xfs_dir2_data_log_unused(tp, bp, newdup);
859                 newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
860                 newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
861                 newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
862                 *xfs_dir2_data_unused_tag_p(newdup2) =
863                         cpu_to_be16((char *)newdup2 - (char *)hdr);
864                 xfs_dir2_data_log_unused(tp, bp, newdup2);
865                 /*
866                  * If the old entry was in the table, we need to scan
867                  * if the 3rd entry was valid, since these entries
868                  * are smaller than the old one.
869                  * If we don't need to scan that means there were 1 or 2
870                  * entries in the table, and removing the old and adding
871                  * the 2 new will work.
872                  */
873                 if (dfp) {
874                         needscan = (hdr->bestfree[2].length != 0);
875                         if (!needscan) {
876                                 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
877                                 xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
878                                 xfs_dir2_data_freeinsert(hdr, newdup2,
879                                                          needlogp);
880                         }
881                 }
882         }
883         *needscanp = needscan;
884 }