1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
34STATIC xfs_dir2_data_free_t *
35xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup);
36
37#ifdef DEBUG
38
39
40
41
42
43void
44xfs_dir2_data_check(
45 xfs_inode_t *dp,
46 xfs_dabuf_t *bp)
47{
48 xfs_dir2_dataptr_t addr;
49 xfs_dir2_data_free_t *bf;
50 xfs_dir2_block_tail_t *btp=NULL;
51 int count;
52 xfs_dir2_data_hdr_t *hdr;
53 xfs_dir2_data_entry_t *dep;
54 xfs_dir2_data_free_t *dfp;
55 xfs_dir2_data_unused_t *dup;
56 char *endp;
57 int freeseen;
58 xfs_dahash_t hash;
59 int i;
60 int lastfree;
61 xfs_dir2_leaf_entry_t *lep=NULL;
62 xfs_mount_t *mp;
63 char *p;
64 int stale;
65 struct xfs_name name;
66
67 mp = dp->i_mount;
68 hdr = bp->data;
69 bf = hdr->bestfree;
70 p = (char *)(hdr + 1);
71
72 if (hdr->magic == 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 } else {
77 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
78 endp = (char *)hdr + mp->m_dirblksize;
79 }
80
81 count = lastfree = freeseen = 0;
82
83
84
85 if (!bf[0].length) {
86 ASSERT(!bf[0].offset);
87 freeseen |= 1 << 0;
88 }
89 if (!bf[1].length) {
90 ASSERT(!bf[1].offset);
91 freeseen |= 1 << 1;
92 }
93 if (!bf[2].length) {
94 ASSERT(!bf[2].offset);
95 freeseen |= 1 << 2;
96 }
97 ASSERT(be16_to_cpu(bf[0].length) >= be16_to_cpu(bf[1].length));
98 ASSERT(be16_to_cpu(bf[1].length) >= be16_to_cpu(bf[2].length));
99
100
101
102 while (p < endp) {
103 dup = (xfs_dir2_data_unused_t *)p;
104
105
106
107
108
109 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
110 ASSERT(lastfree == 0);
111 ASSERT(be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
112 (char *)dup - (char *)hdr);
113 dfp = xfs_dir2_data_freefind(hdr, dup);
114 if (dfp) {
115 i = (int)(dfp - bf);
116 ASSERT((freeseen & (1 << i)) == 0);
117 freeseen |= 1 << i;
118 } else {
119 ASSERT(be16_to_cpu(dup->length) <=
120 be16_to_cpu(bf[2].length));
121 }
122 p += be16_to_cpu(dup->length);
123 lastfree = 1;
124 continue;
125 }
126
127
128
129
130
131
132 dep = (xfs_dir2_data_entry_t *)p;
133 ASSERT(dep->namelen != 0);
134 ASSERT(xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)) == 0);
135 ASSERT(be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)) ==
136 (char *)dep - (char *)hdr);
137 count++;
138 lastfree = 0;
139 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
140 addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
141 (xfs_dir2_data_aoff_t)
142 ((char *)dep - (char *)hdr));
143 name.name = dep->name;
144 name.len = dep->namelen;
145 hash = mp->m_dirnameops->hashname(&name);
146 for (i = 0; i < be32_to_cpu(btp->count); i++) {
147 if (be32_to_cpu(lep[i].address) == addr &&
148 be32_to_cpu(lep[i].hashval) == hash)
149 break;
150 }
151 ASSERT(i < be32_to_cpu(btp->count));
152 }
153 p += xfs_dir2_data_entsize(dep->namelen);
154 }
155
156
157
158 ASSERT(freeseen == 7);
159 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
160 for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
161 if (lep[i].address ==
162 cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
163 stale++;
164 if (i > 0)
165 ASSERT(be32_to_cpu(lep[i].hashval) >= be32_to_cpu(lep[i - 1].hashval));
166 }
167 ASSERT(count == be32_to_cpu(btp->count) - be32_to_cpu(btp->stale));
168 ASSERT(stale == be32_to_cpu(btp->stale));
169 }
170}
171#endif
172
173
174
175
176
177STATIC xfs_dir2_data_free_t *
178xfs_dir2_data_freefind(
179 xfs_dir2_data_hdr_t *hdr,
180 xfs_dir2_data_unused_t *dup)
181{
182 xfs_dir2_data_free_t *dfp;
183 xfs_dir2_data_aoff_t off;
184#if defined(DEBUG) && defined(__KERNEL__)
185 int matched;
186 int seenzero;
187#endif
188
189 off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
190#if defined(DEBUG) && defined(__KERNEL__)
191
192
193
194
195
196 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
197 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
198 for (dfp = &hdr->bestfree[0], seenzero = matched = 0;
199 dfp < &hdr->bestfree[XFS_DIR2_DATA_FD_COUNT];
200 dfp++) {
201 if (!dfp->offset) {
202 ASSERT(!dfp->length);
203 seenzero = 1;
204 continue;
205 }
206 ASSERT(seenzero == 0);
207 if (be16_to_cpu(dfp->offset) == off) {
208 matched = 1;
209 ASSERT(dfp->length == dup->length);
210 } else if (off < be16_to_cpu(dfp->offset))
211 ASSERT(off + be16_to_cpu(dup->length) <= be16_to_cpu(dfp->offset));
212 else
213 ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off);
214 ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length));
215 if (dfp > &hdr->bestfree[0])
216 ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length));
217 }
218#endif
219
220
221
222
223 if (be16_to_cpu(dup->length) <
224 be16_to_cpu(hdr->bestfree[XFS_DIR2_DATA_FD_COUNT - 1].length))
225 return NULL;
226
227
228
229 for (dfp = &hdr->bestfree[0];
230 dfp < &hdr->bestfree[XFS_DIR2_DATA_FD_COUNT];
231 dfp++) {
232 if (!dfp->offset)
233 return NULL;
234 if (be16_to_cpu(dfp->offset) == off)
235 return dfp;
236 }
237
238
239
240 return NULL;
241}
242
243
244
245
246xfs_dir2_data_free_t *
247xfs_dir2_data_freeinsert(
248 xfs_dir2_data_hdr_t *hdr,
249 xfs_dir2_data_unused_t *dup,
250 int *loghead)
251{
252 xfs_dir2_data_free_t *dfp;
253 xfs_dir2_data_free_t new;
254
255#ifdef __KERNEL__
256 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
257 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
258#endif
259 dfp = hdr->bestfree;
260 new.length = dup->length;
261 new.offset = cpu_to_be16((char *)dup - (char *)hdr);
262
263
264
265
266 if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) {
267 dfp[2] = dfp[1];
268 dfp[1] = dfp[0];
269 dfp[0] = new;
270 *loghead = 1;
271 return &dfp[0];
272 }
273 if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) {
274 dfp[2] = dfp[1];
275 dfp[1] = new;
276 *loghead = 1;
277 return &dfp[1];
278 }
279 if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) {
280 dfp[2] = new;
281 *loghead = 1;
282 return &dfp[2];
283 }
284 return NULL;
285}
286
287
288
289
290STATIC void
291xfs_dir2_data_freeremove(
292 xfs_dir2_data_hdr_t *hdr,
293 xfs_dir2_data_free_t *dfp,
294 int *loghead)
295{
296#ifdef __KERNEL__
297 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
298 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
299#endif
300
301
302
303 if (dfp == &hdr->bestfree[0]) {
304 hdr->bestfree[0] = hdr->bestfree[1];
305 hdr->bestfree[1] = hdr->bestfree[2];
306 }
307
308
309
310 else if (dfp == &hdr->bestfree[1])
311 hdr->bestfree[1] = hdr->bestfree[2];
312
313
314
315 else
316 ASSERT(dfp == &hdr->bestfree[2]);
317
318
319
320 hdr->bestfree[2].length = 0;
321 hdr->bestfree[2].offset = 0;
322 *loghead = 1;
323}
324
325
326
327
328void
329xfs_dir2_data_freescan(
330 xfs_mount_t *mp,
331 xfs_dir2_data_hdr_t *hdr,
332 int *loghead)
333{
334 xfs_dir2_block_tail_t *btp;
335 xfs_dir2_data_entry_t *dep;
336 xfs_dir2_data_unused_t *dup;
337 char *endp;
338 char *p;
339
340#ifdef __KERNEL__
341 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
342 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
343#endif
344
345
346
347 memset(hdr->bestfree, 0, sizeof(hdr->bestfree));
348 *loghead = 1;
349
350
351
352 p = (char *)(hdr + 1);
353 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
354 btp = xfs_dir2_block_tail_p(mp, hdr);
355 endp = (char *)xfs_dir2_block_leaf_p(btp);
356 } else
357 endp = (char *)hdr + mp->m_dirblksize;
358
359
360
361 while (p < endp) {
362 dup = (xfs_dir2_data_unused_t *)p;
363
364
365
366 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
367 ASSERT((char *)dup - (char *)hdr ==
368 be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
369 xfs_dir2_data_freeinsert(hdr, dup, loghead);
370 p += be16_to_cpu(dup->length);
371 }
372
373
374
375 else {
376 dep = (xfs_dir2_data_entry_t *)p;
377 ASSERT((char *)dep - (char *)hdr ==
378 be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)));
379 p += xfs_dir2_data_entsize(dep->namelen);
380 }
381 }
382}
383
384
385
386
387
388int
389xfs_dir2_data_init(
390 xfs_da_args_t *args,
391 xfs_dir2_db_t blkno,
392 xfs_dabuf_t **bpp)
393{
394 xfs_dabuf_t *bp;
395 xfs_dir2_data_hdr_t *hdr;
396 xfs_inode_t *dp;
397 xfs_dir2_data_unused_t *dup;
398 int error;
399 int i;
400 xfs_mount_t *mp;
401 xfs_trans_t *tp;
402 int t;
403
404 dp = args->dp;
405 mp = dp->i_mount;
406 tp = args->trans;
407
408
409
410 error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, blkno), -1, &bp,
411 XFS_DATA_FORK);
412 if (error) {
413 return error;
414 }
415 ASSERT(bp != NULL);
416
417
418
419
420 hdr = bp->data;
421 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
422 hdr->bestfree[0].offset = cpu_to_be16(sizeof(*hdr));
423 for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
424 hdr->bestfree[i].length = 0;
425 hdr->bestfree[i].offset = 0;
426 }
427
428
429
430
431 dup = (xfs_dir2_data_unused_t *)(hdr + 1);
432 dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
433
434 t = mp->m_dirblksize - (uint)sizeof(*hdr);
435 hdr->bestfree[0].length = cpu_to_be16(t);
436 dup->length = cpu_to_be16(t);
437 *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr);
438
439
440
441 xfs_dir2_data_log_header(tp, bp);
442 xfs_dir2_data_log_unused(tp, bp, dup);
443 *bpp = bp;
444 return 0;
445}
446
447
448
449
450void
451xfs_dir2_data_log_entry(
452 xfs_trans_t *tp,
453 xfs_dabuf_t *bp,
454 xfs_dir2_data_entry_t *dep)
455{
456 xfs_dir2_data_hdr_t *hdr = bp->data;
457
458 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
459 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
460
461 xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr),
462 (uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) -
463 (char *)hdr - 1));
464}
465
466
467
468
469void
470xfs_dir2_data_log_header(
471 xfs_trans_t *tp,
472 xfs_dabuf_t *bp)
473{
474 xfs_dir2_data_hdr_t *hdr = bp->data;
475
476 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
477 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
478
479 xfs_da_log_buf(tp, bp, 0, sizeof(*hdr) - 1);
480}
481
482
483
484
485void
486xfs_dir2_data_log_unused(
487 xfs_trans_t *tp,
488 xfs_dabuf_t *bp,
489 xfs_dir2_data_unused_t *dup)
490{
491 xfs_dir2_data_hdr_t *hdr = bp->data;
492
493 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
494 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
495
496
497
498
499 xfs_da_log_buf(tp, bp, (uint)((char *)dup - (char *)hdr),
500 (uint)((char *)&dup->length + sizeof(dup->length) -
501 1 - (char *)hdr));
502
503
504
505 xfs_da_log_buf(tp, bp,
506 (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr),
507 (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr +
508 sizeof(xfs_dir2_data_off_t) - 1));
509}
510
511
512
513
514
515void
516xfs_dir2_data_make_free(
517 xfs_trans_t *tp,
518 xfs_dabuf_t *bp,
519 xfs_dir2_data_aoff_t offset,
520 xfs_dir2_data_aoff_t len,
521 int *needlogp,
522 int *needscanp)
523{
524 xfs_dir2_data_hdr_t *hdr;
525 xfs_dir2_data_free_t *dfp;
526 char *endptr;
527 xfs_mount_t *mp;
528 int needscan;
529 xfs_dir2_data_unused_t *newdup;
530 xfs_dir2_data_unused_t *postdup;
531 xfs_dir2_data_unused_t *prevdup;
532
533 mp = tp->t_mountp;
534 hdr = bp->data;
535
536
537
538
539 if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC))
540 endptr = (char *)hdr + mp->m_dirblksize;
541 else {
542 xfs_dir2_block_tail_t *btp;
543
544 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
545 btp = xfs_dir2_block_tail_p(mp, hdr);
546 endptr = (char *)xfs_dir2_block_leaf_p(btp);
547 }
548
549
550
551
552 if (offset > sizeof(*hdr)) {
553 __be16 *tagp;
554
555 tagp = (__be16 *)((char *)hdr + offset) - 1;
556 prevdup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
557 if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
558 prevdup = NULL;
559 } else
560 prevdup = NULL;
561
562
563
564
565 if ((char *)hdr + offset + len < endptr) {
566 postdup =
567 (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
568 if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
569 postdup = NULL;
570 } else
571 postdup = NULL;
572 ASSERT(*needscanp == 0);
573 needscan = 0;
574
575
576
577
578 if (prevdup && postdup) {
579 xfs_dir2_data_free_t *dfp2;
580
581
582
583
584 dfp = xfs_dir2_data_freefind(hdr, prevdup);
585 dfp2 = xfs_dir2_data_freefind(hdr, postdup);
586
587
588
589
590
591
592 needscan = (hdr->bestfree[2].length != 0);
593
594
595
596 be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length));
597 *xfs_dir2_data_unused_tag_p(prevdup) =
598 cpu_to_be16((char *)prevdup - (char *)hdr);
599 xfs_dir2_data_log_unused(tp, bp, prevdup);
600 if (!needscan) {
601
602
603
604
605
606
607 ASSERT(dfp && dfp2);
608 if (dfp == &hdr->bestfree[1]) {
609 dfp = &hdr->bestfree[0];
610 ASSERT(dfp2 == dfp);
611 dfp2 = &hdr->bestfree[1];
612 }
613 xfs_dir2_data_freeremove(hdr, dfp2, needlogp);
614 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
615
616
617
618 dfp = xfs_dir2_data_freeinsert(hdr, prevdup, needlogp);
619 ASSERT(dfp == &hdr->bestfree[0]);
620 ASSERT(dfp->length == prevdup->length);
621 ASSERT(!dfp[1].length);
622 ASSERT(!dfp[2].length);
623 }
624 }
625
626
627
628 else if (prevdup) {
629 dfp = xfs_dir2_data_freefind(hdr, prevdup);
630 be16_add_cpu(&prevdup->length, len);
631 *xfs_dir2_data_unused_tag_p(prevdup) =
632 cpu_to_be16((char *)prevdup - (char *)hdr);
633 xfs_dir2_data_log_unused(tp, bp, prevdup);
634
635
636
637
638
639 if (dfp) {
640 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
641 xfs_dir2_data_freeinsert(hdr, prevdup, needlogp);
642 }
643
644
645
646 else {
647 needscan = be16_to_cpu(prevdup->length) >
648 be16_to_cpu(hdr->bestfree[2].length);
649 }
650 }
651
652
653
654 else if (postdup) {
655 dfp = xfs_dir2_data_freefind(hdr, postdup);
656 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
657 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
658 newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
659 *xfs_dir2_data_unused_tag_p(newdup) =
660 cpu_to_be16((char *)newdup - (char *)hdr);
661 xfs_dir2_data_log_unused(tp, bp, newdup);
662
663
664
665
666
667 if (dfp) {
668 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
669 xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
670 }
671
672
673
674 else {
675 needscan = be16_to_cpu(newdup->length) >
676 be16_to_cpu(hdr->bestfree[2].length);
677 }
678 }
679
680
681
682 else {
683 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
684 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
685 newdup->length = cpu_to_be16(len);
686 *xfs_dir2_data_unused_tag_p(newdup) =
687 cpu_to_be16((char *)newdup - (char *)hdr);
688 xfs_dir2_data_log_unused(tp, bp, newdup);
689 xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
690 }
691 *needscanp = needscan;
692}
693
694
695
696
697void
698xfs_dir2_data_use_free(
699 xfs_trans_t *tp,
700 xfs_dabuf_t *bp,
701 xfs_dir2_data_unused_t *dup,
702 xfs_dir2_data_aoff_t offset,
703 xfs_dir2_data_aoff_t len,
704 int *needlogp,
705 int *needscanp)
706{
707 xfs_dir2_data_hdr_t *hdr;
708 xfs_dir2_data_free_t *dfp;
709 int matchback;
710 int matchfront;
711 int needscan;
712 xfs_dir2_data_unused_t *newdup;
713 xfs_dir2_data_unused_t *newdup2;
714 int oldlen;
715
716 hdr = bp->data;
717 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
718 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
719 ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
720 ASSERT(offset >= (char *)dup - (char *)hdr);
721 ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)hdr);
722 ASSERT((char *)dup - (char *)hdr == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
723
724
725
726 dfp = xfs_dir2_data_freefind(hdr, dup);
727 oldlen = be16_to_cpu(dup->length);
728 ASSERT(dfp || oldlen <= be16_to_cpu(hdr->bestfree[2].length));
729
730
731
732 matchfront = (char *)dup - (char *)hdr == offset;
733 matchback = (char *)dup + oldlen - (char *)hdr == offset + len;
734 ASSERT(*needscanp == 0);
735 needscan = 0;
736
737
738
739
740 if (matchfront && matchback) {
741 if (dfp) {
742 needscan = (hdr->bestfree[2].offset != 0);
743 if (!needscan)
744 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
745 }
746 }
747
748
749
750
751 else if (matchfront) {
752 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
753 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
754 newdup->length = cpu_to_be16(oldlen - len);
755 *xfs_dir2_data_unused_tag_p(newdup) =
756 cpu_to_be16((char *)newdup - (char *)hdr);
757 xfs_dir2_data_log_unused(tp, bp, newdup);
758
759
760
761 if (dfp) {
762 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
763 dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
764 ASSERT(dfp != NULL);
765 ASSERT(dfp->length == newdup->length);
766 ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr);
767
768
769
770
771
772 needscan = dfp == &hdr->bestfree[2];
773 }
774 }
775
776
777
778
779 else if (matchback) {
780 newdup = dup;
781 newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
782 *xfs_dir2_data_unused_tag_p(newdup) =
783 cpu_to_be16((char *)newdup - (char *)hdr);
784 xfs_dir2_data_log_unused(tp, bp, newdup);
785
786
787
788 if (dfp) {
789 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
790 dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
791 ASSERT(dfp != NULL);
792 ASSERT(dfp->length == newdup->length);
793 ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr);
794
795
796
797
798
799 needscan = dfp == &hdr->bestfree[2];
800 }
801 }
802
803
804
805
806 else {
807 newdup = dup;
808 newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
809 *xfs_dir2_data_unused_tag_p(newdup) =
810 cpu_to_be16((char *)newdup - (char *)hdr);
811 xfs_dir2_data_log_unused(tp, bp, newdup);
812 newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
813 newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
814 newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
815 *xfs_dir2_data_unused_tag_p(newdup2) =
816 cpu_to_be16((char *)newdup2 - (char *)hdr);
817 xfs_dir2_data_log_unused(tp, bp, newdup2);
818
819
820
821
822
823
824
825
826 if (dfp) {
827 needscan = (hdr->bestfree[2].length != 0);
828 if (!needscan) {
829 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
830 xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
831 xfs_dir2_data_freeinsert(hdr, newdup2,
832 needlogp);
833 }
834 }
835 }
836 *needscanp = needscan;
837}
838