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_inum.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h"
25#include "xfs_ag.h"
26#include "xfs_dir2.h"
27#include "xfs_dmapi.h"
28#include "xfs_mount.h"
29#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_dir2_sf.h"
32#include "xfs_attr_sf.h"
33#include "xfs_dinode.h"
34#include "xfs_inode.h"
35#include "xfs_bmap.h"
36#include "xfs_dir2_data.h"
37#include "xfs_dir2_leaf.h"
38#include "xfs_dir2_block.h"
39#include "xfs_dir2_node.h"
40#include "xfs_dir2_trace.h"
41#include "xfs_error.h"
42
43
44
45
46static void xfs_dir2_free_log_header(xfs_trans_t *tp, xfs_dabuf_t *bp);
47static int xfs_dir2_leafn_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index);
48#ifdef DEBUG
49static void xfs_dir2_leafn_check(xfs_inode_t *dp, xfs_dabuf_t *bp);
50#else
51#define xfs_dir2_leafn_check(dp, bp)
52#endif
53static void xfs_dir2_leafn_moveents(xfs_da_args_t *args, xfs_dabuf_t *bp_s,
54 int start_s, xfs_dabuf_t *bp_d, int start_d,
55 int count);
56static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state,
57 xfs_da_state_blk_t *blk1,
58 xfs_da_state_blk_t *blk2);
59static int xfs_dir2_leafn_remove(xfs_da_args_t *args, xfs_dabuf_t *bp,
60 int index, xfs_da_state_blk_t *dblk,
61 int *rval);
62static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
63 xfs_da_state_blk_t *fblk);
64
65
66
67
68void
69xfs_dir2_free_log_bests(
70 xfs_trans_t *tp,
71 xfs_dabuf_t *bp,
72 int first,
73 int last)
74{
75 xfs_dir2_free_t *free;
76
77 free = bp->data;
78 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
79 xfs_da_log_buf(tp, bp,
80 (uint)((char *)&free->bests[first] - (char *)free),
81 (uint)((char *)&free->bests[last] - (char *)free +
82 sizeof(free->bests[0]) - 1));
83}
84
85
86
87
88static void
89xfs_dir2_free_log_header(
90 xfs_trans_t *tp,
91 xfs_dabuf_t *bp)
92{
93 xfs_dir2_free_t *free;
94
95 free = bp->data;
96 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
97 xfs_da_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free),
98 (uint)(sizeof(xfs_dir2_free_hdr_t) - 1));
99}
100
101
102
103
104
105
106int
107xfs_dir2_leaf_to_node(
108 xfs_da_args_t *args,
109 xfs_dabuf_t *lbp)
110{
111 xfs_inode_t *dp;
112 int error;
113 xfs_dabuf_t *fbp;
114 xfs_dir2_db_t fdb;
115 xfs_dir2_free_t *free;
116 __be16 *from;
117 int i;
118 xfs_dir2_leaf_t *leaf;
119 xfs_dir2_leaf_tail_t *ltp;
120 xfs_mount_t *mp;
121 int n;
122 xfs_dir2_data_off_t off;
123 __be16 *to;
124 xfs_trans_t *tp;
125
126 xfs_dir2_trace_args_b("leaf_to_node", args, lbp);
127 dp = args->dp;
128 mp = dp->i_mount;
129 tp = args->trans;
130
131
132
133 if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fdb))) {
134 return error;
135 }
136 ASSERT(fdb == XFS_DIR2_FREE_FIRSTDB(mp));
137
138
139
140 if ((error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp,
141 XFS_DATA_FORK))) {
142 return error;
143 }
144 ASSERT(fbp != NULL);
145 free = fbp->data;
146 leaf = lbp->data;
147 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
148
149
150
151 free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC);
152 free->hdr.firstdb = 0;
153 ASSERT(be32_to_cpu(ltp->bestcount) <= (uint)dp->i_d.di_size / mp->m_dirblksize);
154 free->hdr.nvalid = ltp->bestcount;
155
156
157
158
159 for (i = n = 0, from = xfs_dir2_leaf_bests_p(ltp), to = free->bests;
160 i < be32_to_cpu(ltp->bestcount); i++, from++, to++) {
161 if ((off = be16_to_cpu(*from)) != NULLDATAOFF)
162 n++;
163 *to = cpu_to_be16(off);
164 }
165 free->hdr.nused = cpu_to_be32(n);
166 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC);
167
168
169
170 xfs_dir2_leaf_log_header(tp, lbp);
171 xfs_dir2_free_log_header(tp, fbp);
172 xfs_dir2_free_log_bests(tp, fbp, 0, be32_to_cpu(free->hdr.nvalid) - 1);
173 xfs_da_buf_done(fbp);
174 xfs_dir2_leafn_check(dp, lbp);
175 return 0;
176}
177
178
179
180
181
182static int
183xfs_dir2_leafn_add(
184 xfs_dabuf_t *bp,
185 xfs_da_args_t *args,
186 int index)
187{
188 int compact;
189 xfs_inode_t *dp;
190 int highstale;
191 xfs_dir2_leaf_t *leaf;
192 xfs_dir2_leaf_entry_t *lep;
193 int lfloghigh;
194 int lfloglow;
195 int lowstale;
196 xfs_mount_t *mp;
197 xfs_trans_t *tp;
198
199 xfs_dir2_trace_args_sb("leafn_add", args, index, bp);
200 dp = args->dp;
201 mp = dp->i_mount;
202 tp = args->trans;
203 leaf = bp->data;
204
205
206
207
208
209 if (index < 0)
210 return XFS_ERROR(EFSCORRUPTED);
211
212
213
214
215
216
217
218
219 if (be16_to_cpu(leaf->hdr.count) == xfs_dir2_max_leaf_ents(mp)) {
220 if (!leaf->hdr.stale)
221 return XFS_ERROR(ENOSPC);
222 compact = be16_to_cpu(leaf->hdr.stale) > 1;
223 } else
224 compact = 0;
225 ASSERT(index == 0 || be32_to_cpu(leaf->ents[index - 1].hashval) <= args->hashval);
226 ASSERT(index == be16_to_cpu(leaf->hdr.count) ||
227 be32_to_cpu(leaf->ents[index].hashval) >= args->hashval);
228
229 if (args->justcheck)
230 return 0;
231
232
233
234
235
236 if (compact) {
237 xfs_dir2_leaf_compact_x1(bp, &index, &lowstale, &highstale,
238 &lfloglow, &lfloghigh);
239 }
240
241
242
243 else if (leaf->hdr.stale) {
244 lfloglow = be16_to_cpu(leaf->hdr.count);
245 lfloghigh = -1;
246 }
247
248
249
250 if (!leaf->hdr.stale) {
251 lep = &leaf->ents[index];
252 if (index < be16_to_cpu(leaf->hdr.count))
253 memmove(lep + 1, lep,
254 (be16_to_cpu(leaf->hdr.count) - index) * sizeof(*lep));
255 lfloglow = index;
256 lfloghigh = be16_to_cpu(leaf->hdr.count);
257 be16_add(&leaf->hdr.count, 1);
258 }
259
260
261
262 else {
263
264
265
266
267 if (compact == 0) {
268
269
270
271 for (lowstale = index - 1;
272 lowstale >= 0 &&
273 be32_to_cpu(leaf->ents[lowstale].address) !=
274 XFS_DIR2_NULL_DATAPTR;
275 lowstale--)
276 continue;
277
278
279
280
281
282 for (highstale = index;
283 highstale < be16_to_cpu(leaf->hdr.count) &&
284 be32_to_cpu(leaf->ents[highstale].address) !=
285 XFS_DIR2_NULL_DATAPTR &&
286 (lowstale < 0 ||
287 index - lowstale - 1 >= highstale - index);
288 highstale++)
289 continue;
290 }
291
292
293
294
295 if (lowstale >= 0 &&
296 (highstale == be16_to_cpu(leaf->hdr.count) ||
297 index - lowstale - 1 < highstale - index)) {
298 ASSERT(be32_to_cpu(leaf->ents[lowstale].address) ==
299 XFS_DIR2_NULL_DATAPTR);
300 ASSERT(index - lowstale - 1 >= 0);
301 if (index - lowstale - 1 > 0)
302 memmove(&leaf->ents[lowstale],
303 &leaf->ents[lowstale + 1],
304 (index - lowstale - 1) * sizeof(*lep));
305 lep = &leaf->ents[index - 1];
306 lfloglow = MIN(lowstale, lfloglow);
307 lfloghigh = MAX(index - 1, lfloghigh);
308 }
309
310
311
312
313 else {
314 ASSERT(be32_to_cpu(leaf->ents[highstale].address) ==
315 XFS_DIR2_NULL_DATAPTR);
316 ASSERT(highstale - index >= 0);
317 if (highstale - index > 0)
318 memmove(&leaf->ents[index + 1],
319 &leaf->ents[index],
320 (highstale - index) * sizeof(*lep));
321 lep = &leaf->ents[index];
322 lfloglow = MIN(index, lfloglow);
323 lfloghigh = MAX(highstale, lfloghigh);
324 }
325 be16_add(&leaf->hdr.stale, -1);
326 }
327
328
329
330 lep->hashval = cpu_to_be32(args->hashval);
331 lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp,
332 args->blkno, args->index));
333 xfs_dir2_leaf_log_header(tp, bp);
334 xfs_dir2_leaf_log_ents(tp, bp, lfloglow, lfloghigh);
335 xfs_dir2_leafn_check(dp, bp);
336 return 0;
337}
338
339#ifdef DEBUG
340
341
342
343void
344xfs_dir2_leafn_check(
345 xfs_inode_t *dp,
346 xfs_dabuf_t *bp)
347{
348 int i;
349 xfs_dir2_leaf_t *leaf;
350 xfs_mount_t *mp;
351 int stale;
352
353 leaf = bp->data;
354 mp = dp->i_mount;
355 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
356 ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));
357 for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) {
358 if (i + 1 < be16_to_cpu(leaf->hdr.count)) {
359 ASSERT(be32_to_cpu(leaf->ents[i].hashval) <=
360 be32_to_cpu(leaf->ents[i + 1].hashval));
361 }
362 if (be32_to_cpu(leaf->ents[i].address) == XFS_DIR2_NULL_DATAPTR)
363 stale++;
364 }
365 ASSERT(be16_to_cpu(leaf->hdr.stale) == stale);
366}
367#endif
368
369
370
371
372
373xfs_dahash_t
374xfs_dir2_leafn_lasthash(
375 xfs_dabuf_t *bp,
376 int *count)
377{
378 xfs_dir2_leaf_t *leaf;
379
380 leaf = bp->data;
381 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
382 if (count)
383 *count = be16_to_cpu(leaf->hdr.count);
384 if (!leaf->hdr.count)
385 return 0;
386 return be32_to_cpu(leaf->ents[be16_to_cpu(leaf->hdr.count) - 1].hashval);
387}
388
389
390
391
392
393
394int
395xfs_dir2_leafn_lookup_int(
396 xfs_dabuf_t *bp,
397 xfs_da_args_t *args,
398 int *indexp,
399 xfs_da_state_t *state)
400{
401 xfs_dabuf_t *curbp;
402 xfs_dir2_db_t curdb;
403 xfs_dir2_db_t curfdb;
404 xfs_dir2_data_entry_t *dep;
405 xfs_inode_t *dp;
406 int error;
407 int fi;
408 xfs_dir2_free_t *free=NULL;
409 int index;
410 xfs_dir2_leaf_t *leaf;
411 int length=0;
412 xfs_dir2_leaf_entry_t *lep;
413 xfs_mount_t *mp;
414 xfs_dir2_db_t newdb;
415 xfs_dir2_db_t newfdb;
416 xfs_trans_t *tp;
417
418 dp = args->dp;
419 tp = args->trans;
420 mp = dp->i_mount;
421 leaf = bp->data;
422 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
423#ifdef __KERNEL__
424 ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
425#endif
426 xfs_dir2_leafn_check(dp, bp);
427
428
429
430 index = xfs_dir2_leaf_search_hash(args, bp);
431
432
433
434 if (state->extravalid)
435 curbp = state->extrablk.bp;
436 else
437 curbp = NULL;
438
439
440
441 if (args->addname) {
442 curfdb = curbp ? state->extrablk.blkno : -1;
443 curdb = -1;
444 length = xfs_dir2_data_entsize(args->namelen);
445 if ((free = (curbp ? curbp->data : NULL)))
446 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
447 }
448
449
450
451 else {
452 curfdb = -1;
453 curdb = curbp ? state->extrablk.blkno : -1;
454 }
455
456
457
458 for (lep = &leaf->ents[index];
459 index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval;
460 lep++, index++) {
461
462
463
464 if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
465 continue;
466
467
468
469 newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
470
471
472
473
474
475 if (args->addname) {
476
477
478
479
480 if (newdb != curdb) {
481 curdb = newdb;
482
483
484
485
486 newfdb = xfs_dir2_db_to_fdb(mp, newdb);
487
488
489
490
491 if (newfdb != curfdb) {
492
493
494
495 if (curbp)
496 xfs_da_brelse(tp, curbp);
497
498
499
500 if ((error = xfs_da_read_buf(tp, dp,
501 xfs_dir2_db_to_da(mp,
502 newfdb),
503 -1, &curbp,
504 XFS_DATA_FORK))) {
505 return error;
506 }
507 free = curbp->data;
508 ASSERT(be32_to_cpu(free->hdr.magic) ==
509 XFS_DIR2_FREE_MAGIC);
510 ASSERT((be32_to_cpu(free->hdr.firstdb) %
511 XFS_DIR2_MAX_FREE_BESTS(mp)) ==
512 0);
513 ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb);
514 ASSERT(curdb <
515 be32_to_cpu(free->hdr.firstdb) +
516 be32_to_cpu(free->hdr.nvalid));
517 }
518
519
520
521 fi = xfs_dir2_db_to_fdindex(mp, curdb);
522
523
524
525 if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) {
526 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
527 XFS_ERRLEVEL_LOW, mp);
528 if (curfdb != newfdb)
529 xfs_da_brelse(tp, curbp);
530 return XFS_ERROR(EFSCORRUPTED);
531 }
532 curfdb = newfdb;
533 if (be16_to_cpu(free->bests[fi]) >= length) {
534 *indexp = index;
535 state->extravalid = 1;
536 state->extrablk.bp = curbp;
537 state->extrablk.blkno = curfdb;
538 state->extrablk.index = fi;
539 state->extrablk.magic =
540 XFS_DIR2_FREE_MAGIC;
541 ASSERT(args->oknoent);
542 return XFS_ERROR(ENOENT);
543 }
544 }
545 }
546
547
548
549
550 else {
551
552
553
554 if (newdb != curdb) {
555
556
557
558 if (curbp)
559 xfs_da_brelse(tp, curbp);
560
561
562
563 if ((error =
564 xfs_da_read_buf(tp, dp,
565 xfs_dir2_db_to_da(mp, newdb), -1,
566 &curbp, XFS_DATA_FORK))) {
567 return error;
568 }
569 xfs_dir2_data_check(dp, curbp);
570 curdb = newdb;
571 }
572
573
574
575 dep = (xfs_dir2_data_entry_t *)
576 ((char *)curbp->data +
577 xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
578
579
580
581 if (dep->namelen == args->namelen &&
582 dep->name[0] == args->name[0] &&
583 memcmp(dep->name, args->name, args->namelen) == 0) {
584 args->inumber = be64_to_cpu(dep->inumber);
585 *indexp = index;
586 state->extravalid = 1;
587 state->extrablk.bp = curbp;
588 state->extrablk.blkno = curdb;
589 state->extrablk.index =
590 (int)((char *)dep -
591 (char *)curbp->data);
592 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
593 return XFS_ERROR(EEXIST);
594 }
595 }
596 }
597
598
599
600
601
602 if ((state->extravalid = (curbp != NULL))) {
603 state->extrablk.bp = curbp;
604 state->extrablk.index = -1;
605
606
607
608 if (args->addname) {
609 state->extrablk.blkno = curfdb;
610 state->extrablk.magic = XFS_DIR2_FREE_MAGIC;
611 }
612
613
614
615 else {
616 state->extrablk.blkno = curdb;
617 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
618 }
619 }
620
621
622
623 *indexp = index;
624 ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent);
625 return XFS_ERROR(ENOENT);
626}
627
628
629
630
631
632static void
633xfs_dir2_leafn_moveents(
634 xfs_da_args_t *args,
635 xfs_dabuf_t *bp_s,
636 int start_s,
637 xfs_dabuf_t *bp_d,
638 int start_d,
639 int count)
640{
641 xfs_dir2_leaf_t *leaf_d;
642 xfs_dir2_leaf_t *leaf_s;
643 int stale;
644 xfs_trans_t *tp;
645
646 xfs_dir2_trace_args_bibii("leafn_moveents", args, bp_s, start_s, bp_d,
647 start_d, count);
648
649
650
651 if (count == 0) {
652 return;
653 }
654 tp = args->trans;
655 leaf_s = bp_s->data;
656 leaf_d = bp_d->data;
657
658
659
660
661
662 if (start_d < be16_to_cpu(leaf_d->hdr.count)) {
663 memmove(&leaf_d->ents[start_d + count], &leaf_d->ents[start_d],
664 (be16_to_cpu(leaf_d->hdr.count) - start_d) *
665 sizeof(xfs_dir2_leaf_entry_t));
666 xfs_dir2_leaf_log_ents(tp, bp_d, start_d + count,
667 count + be16_to_cpu(leaf_d->hdr.count) - 1);
668 }
669
670
671
672
673 if (leaf_s->hdr.stale) {
674 int i;
675
676 for (i = start_s, stale = 0; i < start_s + count; i++) {
677 if (be32_to_cpu(leaf_s->ents[i].address) == XFS_DIR2_NULL_DATAPTR)
678 stale++;
679 }
680 } else
681 stale = 0;
682
683
684
685 memcpy(&leaf_d->ents[start_d], &leaf_s->ents[start_s],
686 count * sizeof(xfs_dir2_leaf_entry_t));
687 xfs_dir2_leaf_log_ents(tp, bp_d, start_d, start_d + count - 1);
688
689
690
691
692 if (start_s + count < be16_to_cpu(leaf_s->hdr.count)) {
693 memmove(&leaf_s->ents[start_s], &leaf_s->ents[start_s + count],
694 count * sizeof(xfs_dir2_leaf_entry_t));
695 xfs_dir2_leaf_log_ents(tp, bp_s, start_s, start_s + count - 1);
696 }
697
698
699
700 be16_add(&leaf_s->hdr.count, -(count));
701 be16_add(&leaf_s->hdr.stale, -(stale));
702 be16_add(&leaf_d->hdr.count, count);
703 be16_add(&leaf_d->hdr.stale, stale);
704 xfs_dir2_leaf_log_header(tp, bp_s);
705 xfs_dir2_leaf_log_header(tp, bp_d);
706 xfs_dir2_leafn_check(args->dp, bp_s);
707 xfs_dir2_leafn_check(args->dp, bp_d);
708}
709
710
711
712
713
714int
715xfs_dir2_leafn_order(
716 xfs_dabuf_t *leaf1_bp,
717 xfs_dabuf_t *leaf2_bp)
718{
719 xfs_dir2_leaf_t *leaf1;
720 xfs_dir2_leaf_t *leaf2;
721
722 leaf1 = leaf1_bp->data;
723 leaf2 = leaf2_bp->data;
724 ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
725 ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
726 if (be16_to_cpu(leaf1->hdr.count) > 0 &&
727 be16_to_cpu(leaf2->hdr.count) > 0 &&
728 (be32_to_cpu(leaf2->ents[0].hashval) < be32_to_cpu(leaf1->ents[0].hashval) ||
729 be32_to_cpu(leaf2->ents[be16_to_cpu(leaf2->hdr.count) - 1].hashval) <
730 be32_to_cpu(leaf1->ents[be16_to_cpu(leaf1->hdr.count) - 1].hashval)))
731 return 1;
732 return 0;
733}
734
735
736
737
738
739
740
741
742static void
743xfs_dir2_leafn_rebalance(
744 xfs_da_state_t *state,
745 xfs_da_state_blk_t *blk1,
746 xfs_da_state_blk_t *blk2)
747{
748 xfs_da_args_t *args;
749 int count;
750 int isleft;
751 xfs_dir2_leaf_t *leaf1;
752 xfs_dir2_leaf_t *leaf2;
753 int mid;
754#ifdef DEBUG
755 int oldstale;
756#endif
757 int oldsum;
758 int swap;
759
760 args = state->args;
761
762
763
764 if ((swap = xfs_dir2_leafn_order(blk1->bp, blk2->bp))) {
765 xfs_da_state_blk_t *tmp;
766
767 tmp = blk1;
768 blk1 = blk2;
769 blk2 = tmp;
770 }
771 leaf1 = blk1->bp->data;
772 leaf2 = blk2->bp->data;
773 oldsum = be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count);
774#ifdef DEBUG
775 oldstale = be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale);
776#endif
777 mid = oldsum >> 1;
778
779
780
781
782 if (oldsum & 1) {
783 xfs_dahash_t midhash;
784
785 if (mid >= be16_to_cpu(leaf1->hdr.count))
786 midhash = be32_to_cpu(leaf2->ents[mid - be16_to_cpu(leaf1->hdr.count)].hashval);
787 else
788 midhash = be32_to_cpu(leaf1->ents[mid].hashval);
789 isleft = args->hashval <= midhash;
790 }
791
792
793
794
795
796 else
797 isleft = 1;
798
799
800
801
802 count = be16_to_cpu(leaf1->hdr.count) - mid + (isleft == 0);
803 if (count > 0)
804 xfs_dir2_leafn_moveents(args, blk1->bp,
805 be16_to_cpu(leaf1->hdr.count) - count, blk2->bp, 0, count);
806 else if (count < 0)
807 xfs_dir2_leafn_moveents(args, blk2->bp, 0, blk1->bp,
808 be16_to_cpu(leaf1->hdr.count), count);
809 ASSERT(be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count) == oldsum);
810 ASSERT(be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale) == oldstale);
811
812
813
814 if (be16_to_cpu(leaf1->hdr.count) < be16_to_cpu(leaf2->hdr.count))
815 state->inleaf = swap;
816 else if (be16_to_cpu(leaf1->hdr.count) > be16_to_cpu(leaf2->hdr.count))
817 state->inleaf = !swap;
818 else
819 state->inleaf =
820 swap ^ (blk1->index <= be16_to_cpu(leaf1->hdr.count));
821
822
823
824 if (!state->inleaf)
825 blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count);
826
827
828
829
830 if(blk2->index < 0) {
831 state->inleaf = 1;
832 blk2->index = 0;
833 cmn_err(CE_ALERT,
834 "xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting original leaf: "
835 "blk1->index %d\n",
836 blk1->index);
837 }
838}
839
840
841
842
843
844
845static int
846xfs_dir2_leafn_remove(
847 xfs_da_args_t *args,
848 xfs_dabuf_t *bp,
849 int index,
850 xfs_da_state_blk_t *dblk,
851 int *rval)
852{
853 xfs_dir2_data_t *data;
854 xfs_dir2_db_t db;
855 xfs_dabuf_t *dbp;
856 xfs_dir2_data_entry_t *dep;
857 xfs_inode_t *dp;
858 xfs_dir2_leaf_t *leaf;
859 xfs_dir2_leaf_entry_t *lep;
860 int longest;
861 int off;
862 xfs_mount_t *mp;
863 int needlog;
864 int needscan;
865 xfs_trans_t *tp;
866
867 xfs_dir2_trace_args_sb("leafn_remove", args, index, bp);
868 dp = args->dp;
869 tp = args->trans;
870 mp = dp->i_mount;
871 leaf = bp->data;
872 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
873
874
875
876 lep = &leaf->ents[index];
877
878
879
880 db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
881 ASSERT(dblk->blkno == db);
882 off = xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address));
883 ASSERT(dblk->index == off);
884
885
886
887
888 be16_add(&leaf->hdr.stale, 1);
889 xfs_dir2_leaf_log_header(tp, bp);
890 lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
891 xfs_dir2_leaf_log_ents(tp, bp, index, index);
892
893
894
895
896 dbp = dblk->bp;
897 data = dbp->data;
898 dep = (xfs_dir2_data_entry_t *)((char *)data + off);
899 longest = be16_to_cpu(data->hdr.bestfree[0].length);
900 needlog = needscan = 0;
901 xfs_dir2_data_make_free(tp, dbp, off,
902 xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
903
904
905
906
907 if (needscan)
908 xfs_dir2_data_freescan(mp, data, &needlog);
909 if (needlog)
910 xfs_dir2_data_log_header(tp, dbp);
911 xfs_dir2_data_check(dp, dbp);
912
913
914
915
916 if (longest < be16_to_cpu(data->hdr.bestfree[0].length)) {
917 int error;
918 xfs_dabuf_t *fbp;
919 xfs_dir2_db_t fdb;
920 int findex;
921 xfs_dir2_free_t *free;
922 int logfree;
923
924
925
926
927
928 fdb = xfs_dir2_db_to_fdb(mp, db);
929 if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb),
930 -1, &fbp, XFS_DATA_FORK))) {
931 return error;
932 }
933 free = fbp->data;
934 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
935 ASSERT(be32_to_cpu(free->hdr.firstdb) ==
936 XFS_DIR2_MAX_FREE_BESTS(mp) *
937 (fdb - XFS_DIR2_FREE_FIRSTDB(mp)));
938
939
940
941 findex = xfs_dir2_db_to_fdindex(mp, db);
942 longest = be16_to_cpu(data->hdr.bestfree[0].length);
943
944
945
946
947 if (longest == mp->m_dirblksize - (uint)sizeof(data->hdr)) {
948
949
950
951 error = xfs_dir2_shrink_inode(args, db, dbp);
952 if (error == 0) {
953 dblk->bp = NULL;
954 data = NULL;
955 }
956
957
958
959
960
961 else if (error == ENOSPC && args->total == 0)
962 xfs_da_buf_done(dbp);
963 else
964 return error;
965 }
966
967
968
969
970 if (data == NULL) {
971
972
973
974 be32_add(&free->hdr.nused, -1);
975 xfs_dir2_free_log_header(tp, fbp);
976
977
978
979
980
981
982 if (findex == be32_to_cpu(free->hdr.nvalid) - 1) {
983 int i;
984
985 for (i = findex - 1;
986 i >= 0 && be16_to_cpu(free->bests[i]) == NULLDATAOFF;
987 i--)
988 continue;
989 free->hdr.nvalid = cpu_to_be32(i + 1);
990 logfree = 0;
991 }
992
993
994
995 else {
996 free->bests[findex] = cpu_to_be16(NULLDATAOFF);
997 logfree = 1;
998 }
999
1000
1001
1002
1003 if (!free->hdr.nused) {
1004 error = xfs_dir2_shrink_inode(args, fdb, fbp);
1005 if (error == 0) {
1006 fbp = NULL;
1007 logfree = 0;
1008 } else if (error != ENOSPC || args->total != 0)
1009 return error;
1010
1011
1012
1013
1014
1015 }
1016 }
1017
1018
1019
1020
1021 else {
1022 free->bests[findex] = cpu_to_be16(longest);
1023 logfree = 1;
1024 }
1025
1026
1027
1028 if (logfree)
1029 xfs_dir2_free_log_bests(tp, fbp, findex, findex);
1030
1031
1032
1033 if (fbp)
1034 xfs_da_buf_done(fbp);
1035 }
1036 xfs_dir2_leafn_check(dp, bp);
1037
1038
1039
1040
1041 *rval =
1042 ((uint)sizeof(leaf->hdr) +
1043 (uint)sizeof(leaf->ents[0]) *
1044 (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale))) <
1045 mp->m_dir_magicpct;
1046 return 0;
1047}
1048
1049
1050
1051
1052int
1053xfs_dir2_leafn_split(
1054 xfs_da_state_t *state,
1055 xfs_da_state_blk_t *oldblk,
1056 xfs_da_state_blk_t *newblk)
1057{
1058 xfs_da_args_t *args;
1059 xfs_dablk_t blkno;
1060 int error;
1061 xfs_mount_t *mp;
1062
1063
1064
1065
1066 args = state->args;
1067 mp = args->dp->i_mount;
1068 ASSERT(args != NULL);
1069 ASSERT(oldblk->magic == XFS_DIR2_LEAFN_MAGIC);
1070 error = xfs_da_grow_inode(args, &blkno);
1071 if (error) {
1072 return error;
1073 }
1074
1075
1076
1077 error = xfs_dir2_leaf_init(args, xfs_dir2_da_to_db(mp, blkno),
1078 &newblk->bp, XFS_DIR2_LEAFN_MAGIC);
1079 if (error) {
1080 return error;
1081 }
1082 newblk->blkno = blkno;
1083 newblk->magic = XFS_DIR2_LEAFN_MAGIC;
1084
1085
1086
1087
1088 xfs_dir2_leafn_rebalance(state, oldblk, newblk);
1089 error = xfs_da_blk_link(state, oldblk, newblk);
1090 if (error) {
1091 return error;
1092 }
1093
1094
1095
1096 if (state->inleaf)
1097 error = xfs_dir2_leafn_add(oldblk->bp, args, oldblk->index);
1098 else
1099 error = xfs_dir2_leafn_add(newblk->bp, args, newblk->index);
1100
1101
1102
1103 oldblk->hashval = xfs_dir2_leafn_lasthash(oldblk->bp, NULL);
1104 newblk->hashval = xfs_dir2_leafn_lasthash(newblk->bp, NULL);
1105 xfs_dir2_leafn_check(args->dp, oldblk->bp);
1106 xfs_dir2_leafn_check(args->dp, newblk->bp);
1107 return error;
1108}
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119int
1120xfs_dir2_leafn_toosmall(
1121 xfs_da_state_t *state,
1122 int *action)
1123{
1124 xfs_da_state_blk_t *blk;
1125 xfs_dablk_t blkno;
1126 xfs_dabuf_t *bp;
1127 int bytes;
1128 int count;
1129 int error;
1130 int forward;
1131 int i;
1132 xfs_da_blkinfo_t *info;
1133 xfs_dir2_leaf_t *leaf;
1134 int rval;
1135
1136
1137
1138
1139
1140
1141 blk = &state->path.blk[state->path.active - 1];
1142 info = blk->bp->data;
1143 ASSERT(be16_to_cpu(info->magic) == XFS_DIR2_LEAFN_MAGIC);
1144 leaf = (xfs_dir2_leaf_t *)info;
1145 count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
1146 bytes = (uint)sizeof(leaf->hdr) + count * (uint)sizeof(leaf->ents[0]);
1147 if (bytes > (state->blocksize >> 1)) {
1148
1149
1150
1151 *action = 0;
1152 return 0;
1153 }
1154
1155
1156
1157
1158
1159
1160 if (count == 0) {
1161
1162
1163
1164
1165 forward = (info->forw != 0);
1166 memcpy(&state->altpath, &state->path, sizeof(state->path));
1167 error = xfs_da_path_shift(state, &state->altpath, forward, 0,
1168 &rval);
1169 if (error)
1170 return error;
1171 *action = rval ? 2 : 0;
1172 return 0;
1173 }
1174
1175
1176
1177
1178
1179
1180
1181 forward = be32_to_cpu(info->forw) < be32_to_cpu(info->back);
1182 for (i = 0, bp = NULL; i < 2; forward = !forward, i++) {
1183 blkno = forward ? be32_to_cpu(info->forw) : be32_to_cpu(info->back);
1184 if (blkno == 0)
1185 continue;
1186
1187
1188
1189 if ((error =
1190 xfs_da_read_buf(state->args->trans, state->args->dp, blkno,
1191 -1, &bp, XFS_DATA_FORK))) {
1192 return error;
1193 }
1194 ASSERT(bp != NULL);
1195
1196
1197
1198 leaf = (xfs_dir2_leaf_t *)info;
1199 count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
1200 bytes = state->blocksize - (state->blocksize >> 2);
1201 leaf = bp->data;
1202 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
1203 count += be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
1204 bytes -= count * (uint)sizeof(leaf->ents[0]);
1205
1206
1207
1208 if (bytes >= 0)
1209 break;
1210 xfs_da_brelse(state->args->trans, bp);
1211 }
1212
1213
1214
1215 if (i >= 2) {
1216 *action = 0;
1217 return 0;
1218 }
1219
1220
1221
1222
1223 xfs_da_buf_done(bp);
1224
1225
1226
1227
1228 memcpy(&state->altpath, &state->path, sizeof(state->path));
1229 if (blkno < blk->blkno)
1230 error = xfs_da_path_shift(state, &state->altpath, forward, 0,
1231 &rval);
1232 else
1233 error = xfs_da_path_shift(state, &state->path, forward, 0,
1234 &rval);
1235 if (error) {
1236 return error;
1237 }
1238 *action = rval ? 0 : 1;
1239 return 0;
1240}
1241
1242
1243
1244
1245
1246void
1247xfs_dir2_leafn_unbalance(
1248 xfs_da_state_t *state,
1249 xfs_da_state_blk_t *drop_blk,
1250 xfs_da_state_blk_t *save_blk)
1251{
1252 xfs_da_args_t *args;
1253 xfs_dir2_leaf_t *drop_leaf;
1254 xfs_dir2_leaf_t *save_leaf;
1255
1256 args = state->args;
1257 ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
1258 ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC);
1259 drop_leaf = drop_blk->bp->data;
1260 save_leaf = save_blk->bp->data;
1261 ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
1262 ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
1263
1264
1265
1266
1267 if (drop_leaf->hdr.stale)
1268 xfs_dir2_leaf_compact(args, drop_blk->bp);
1269 if (save_leaf->hdr.stale)
1270 xfs_dir2_leaf_compact(args, save_blk->bp);
1271
1272
1273
1274 drop_blk->hashval = be32_to_cpu(drop_leaf->ents[be16_to_cpu(drop_leaf->hdr.count) - 1].hashval);
1275 if (xfs_dir2_leafn_order(save_blk->bp, drop_blk->bp))
1276 xfs_dir2_leafn_moveents(args, drop_blk->bp, 0, save_blk->bp, 0,
1277 be16_to_cpu(drop_leaf->hdr.count));
1278 else
1279 xfs_dir2_leafn_moveents(args, drop_blk->bp, 0, save_blk->bp,
1280 be16_to_cpu(save_leaf->hdr.count), be16_to_cpu(drop_leaf->hdr.count));
1281 save_blk->hashval = be32_to_cpu(save_leaf->ents[be16_to_cpu(save_leaf->hdr.count) - 1].hashval);
1282 xfs_dir2_leafn_check(args->dp, save_blk->bp);
1283}
1284
1285
1286
1287
1288int
1289xfs_dir2_node_addname(
1290 xfs_da_args_t *args)
1291{
1292 xfs_da_state_blk_t *blk;
1293 int error;
1294 int rval;
1295 xfs_da_state_t *state;
1296
1297 xfs_dir2_trace_args("node_addname", args);
1298
1299
1300
1301 state = xfs_da_state_alloc();
1302 state->args = args;
1303 state->mp = args->dp->i_mount;
1304 state->blocksize = state->mp->m_dirblksize;
1305 state->node_ents = state->mp->m_dir_node_ents;
1306
1307
1308
1309
1310 error = xfs_da_node_lookup_int(state, &rval);
1311 if (error)
1312 rval = error;
1313 if (rval != ENOENT) {
1314 goto done;
1315 }
1316
1317
1318
1319
1320 rval = xfs_dir2_node_addname_int(args,
1321 state->extravalid ? &state->extrablk : NULL);
1322 if (rval) {
1323 goto done;
1324 }
1325 blk = &state->path.blk[state->path.active - 1];
1326 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
1327
1328
1329
1330 rval = xfs_dir2_leafn_add(blk->bp, args, blk->index);
1331 if (rval == 0) {
1332
1333
1334
1335 if (!args->justcheck)
1336 xfs_da_fixhashpath(state, &state->path);
1337 } else {
1338
1339
1340
1341 if (args->total == 0) {
1342 ASSERT(rval == ENOSPC);
1343 goto done;
1344 }
1345
1346
1347
1348 rval = xfs_da_split(state);
1349 }
1350done:
1351 xfs_da_state_free(state);
1352 return rval;
1353}
1354
1355
1356
1357
1358
1359
1360static int
1361xfs_dir2_node_addname_int(
1362 xfs_da_args_t *args,
1363 xfs_da_state_blk_t *fblk)
1364{
1365 xfs_dir2_data_t *data;
1366 xfs_dir2_db_t dbno;
1367 xfs_dabuf_t *dbp;
1368 xfs_dir2_data_entry_t *dep;
1369 xfs_inode_t *dp;
1370 xfs_dir2_data_unused_t *dup;
1371 int error;
1372 xfs_dir2_db_t fbno;
1373 xfs_dabuf_t *fbp;
1374 int findex;
1375 xfs_dir2_free_t *free=NULL;
1376 xfs_dir2_db_t ifbno;
1377 xfs_dir2_db_t lastfbno=0;
1378 int length;
1379 int logfree;
1380 xfs_mount_t *mp;
1381 int needlog;
1382 int needscan;
1383 __be16 *tagp;
1384 xfs_trans_t *tp;
1385
1386 dp = args->dp;
1387 mp = dp->i_mount;
1388 tp = args->trans;
1389 length = xfs_dir2_data_entsize(args->namelen);
1390
1391
1392
1393
1394
1395 if (fblk) {
1396 fbp = fblk->bp;
1397
1398
1399
1400 ifbno = fblk->blkno;
1401 free = fbp->data;
1402 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
1403 findex = fblk->index;
1404
1405
1406
1407
1408
1409 if (findex >= 0) {
1410 ASSERT(findex < be32_to_cpu(free->hdr.nvalid));
1411 ASSERT(be16_to_cpu(free->bests[findex]) != NULLDATAOFF);
1412 ASSERT(be16_to_cpu(free->bests[findex]) >= length);
1413 dbno = be32_to_cpu(free->hdr.firstdb) + findex;
1414 }
1415
1416
1417
1418
1419 else {
1420 dbno = -1;
1421 findex = 0;
1422 }
1423 }
1424
1425
1426
1427 else {
1428 ifbno = dbno = -1;
1429 fbp = NULL;
1430 findex = 0;
1431 }
1432
1433
1434
1435
1436
1437 if (dbno == -1) {
1438 xfs_fileoff_t fo;
1439
1440 if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK)))
1441 return error;
1442 lastfbno = xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo);
1443 fbno = ifbno;
1444 }
1445
1446
1447
1448
1449
1450 while (dbno == -1) {
1451
1452
1453
1454 if (fbp == NULL) {
1455
1456
1457
1458
1459 if (++fbno == 0)
1460 fbno = XFS_DIR2_FREE_FIRSTDB(mp);
1461
1462
1463
1464 if (fbno == ifbno)
1465 fbno++;
1466
1467
1468
1469 if (fbno >= lastfbno)
1470 break;
1471
1472
1473
1474
1475
1476
1477 if ((error = xfs_da_read_buf(tp, dp,
1478 xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
1479 XFS_DATA_FORK))) {
1480 return error;
1481 }
1482 if (unlikely(fbp == NULL)) {
1483 continue;
1484 }
1485 free = fbp->data;
1486 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
1487 findex = 0;
1488 }
1489
1490
1491
1492 if (be16_to_cpu(free->bests[findex]) != NULLDATAOFF &&
1493 be16_to_cpu(free->bests[findex]) >= length)
1494 dbno = be32_to_cpu(free->hdr.firstdb) + findex;
1495 else {
1496
1497
1498
1499 if (++findex == be32_to_cpu(free->hdr.nvalid)) {
1500
1501
1502
1503 xfs_da_brelse(tp, fbp);
1504 fbp = NULL;
1505 if (fblk && fblk->bp)
1506 fblk->bp = NULL;
1507 }
1508 }
1509 }
1510
1511
1512
1513
1514 if (unlikely(dbno == -1)) {
1515
1516
1517
1518 if (args->justcheck || args->total == 0) {
1519
1520
1521
1522
1523 if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
1524 xfs_da_buf_done(fbp);
1525 return XFS_ERROR(ENOSPC);
1526 }
1527
1528
1529
1530 if (unlikely((error = xfs_dir2_grow_inode(args,
1531 XFS_DIR2_DATA_SPACE,
1532 &dbno)) ||
1533 (error = xfs_dir2_data_init(args, dbno, &dbp)))) {
1534
1535
1536
1537
1538 if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
1539 xfs_da_buf_done(fbp);
1540 return error;
1541 }
1542
1543
1544
1545 if (fbp)
1546 xfs_da_brelse(tp, fbp);
1547 if (fblk && fblk->bp)
1548 fblk->bp = NULL;
1549
1550
1551
1552
1553
1554 fbno = xfs_dir2_db_to_fdb(mp, dbno);
1555 if (unlikely(error = xfs_da_read_buf(tp, dp,
1556 xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
1557 XFS_DATA_FORK))) {
1558 xfs_da_buf_done(dbp);
1559 return error;
1560 }
1561
1562
1563
1564
1565 if( fbp == NULL ) {
1566 if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE,
1567 &fbno))) {
1568 return error;
1569 }
1570
1571 if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) {
1572 cmn_err(CE_ALERT,
1573 "xfs_dir2_node_addname_int: dir ino "
1574 "%llu needed freesp block %lld for\n"
1575 " data block %lld, got %lld\n"
1576 " ifbno %llu lastfbno %d\n",
1577 (unsigned long long)dp->i_ino,
1578 (long long)xfs_dir2_db_to_fdb(mp, dbno),
1579 (long long)dbno, (long long)fbno,
1580 (unsigned long long)ifbno, lastfbno);
1581 if (fblk) {
1582 cmn_err(CE_ALERT,
1583 " fblk 0x%p blkno %llu "
1584 "index %d magic 0x%x\n",
1585 fblk,
1586 (unsigned long long)fblk->blkno,
1587 fblk->index,
1588 fblk->magic);
1589 } else {
1590 cmn_err(CE_ALERT,
1591 " ... fblk is NULL\n");
1592 }
1593 XFS_ERROR_REPORT("xfs_dir2_node_addname_int",
1594 XFS_ERRLEVEL_LOW, mp);
1595 return XFS_ERROR(EFSCORRUPTED);
1596 }
1597
1598
1599
1600
1601 if ((error = xfs_da_get_buf(tp, dp,
1602 xfs_dir2_db_to_da(mp, fbno),
1603 -1, &fbp, XFS_DATA_FORK))) {
1604 return error;
1605 }
1606 ASSERT(fbp != NULL);
1607
1608
1609
1610
1611
1612 free = fbp->data;
1613 free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC);
1614 free->hdr.firstdb = cpu_to_be32(
1615 (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
1616 XFS_DIR2_MAX_FREE_BESTS(mp));
1617 free->hdr.nvalid = 0;
1618 free->hdr.nused = 0;
1619 } else {
1620 free = fbp->data;
1621 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
1622 }
1623
1624
1625
1626
1627 findex = xfs_dir2_db_to_fdindex(mp, dbno);
1628
1629
1630
1631
1632 if (findex >= be32_to_cpu(free->hdr.nvalid)) {
1633 ASSERT(findex < XFS_DIR2_MAX_FREE_BESTS(mp));
1634 free->hdr.nvalid = cpu_to_be32(findex + 1);
1635
1636
1637
1638 free->bests[findex] = cpu_to_be16(NULLDATAOFF);
1639 }
1640
1641
1642
1643
1644 if (be16_to_cpu(free->bests[findex]) == NULLDATAOFF) {
1645 be32_add(&free->hdr.nused, 1);
1646 xfs_dir2_free_log_header(tp, fbp);
1647 }
1648
1649
1650
1651
1652
1653 data = dbp->data;
1654 free->bests[findex] = data->hdr.bestfree[0].length;
1655 logfree = 1;
1656 }
1657
1658
1659
1660 else {
1661
1662
1663
1664 if (args->justcheck) {
1665 if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
1666 xfs_da_buf_done(fbp);
1667 return 0;
1668 }
1669
1670
1671
1672 if (unlikely(
1673 error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno),
1674 -1, &dbp, XFS_DATA_FORK))) {
1675 if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
1676 xfs_da_buf_done(fbp);
1677 return error;
1678 }
1679 data = dbp->data;
1680 logfree = 0;
1681 }
1682 ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) >= length);
1683
1684
1685
1686 dup = (xfs_dir2_data_unused_t *)
1687 ((char *)data + be16_to_cpu(data->hdr.bestfree[0].offset));
1688 needscan = needlog = 0;
1689
1690
1691
1692 xfs_dir2_data_use_free(tp, dbp, dup,
1693 (xfs_dir2_data_aoff_t)((char *)dup - (char *)data), length,
1694 &needlog, &needscan);
1695
1696
1697
1698 dep = (xfs_dir2_data_entry_t *)dup;
1699 dep->inumber = cpu_to_be64(args->inumber);
1700 dep->namelen = args->namelen;
1701 memcpy(dep->name, args->name, dep->namelen);
1702 tagp = xfs_dir2_data_entry_tag_p(dep);
1703 *tagp = cpu_to_be16((char *)dep - (char *)data);
1704 xfs_dir2_data_log_entry(tp, dbp, dep);
1705
1706
1707
1708 if (needscan)
1709 xfs_dir2_data_freescan(mp, data, &needlog);
1710
1711
1712
1713 if (needlog)
1714 xfs_dir2_data_log_header(tp, dbp);
1715
1716
1717
1718 if (be16_to_cpu(free->bests[findex]) != be16_to_cpu(data->hdr.bestfree[0].length)) {
1719 free->bests[findex] = data->hdr.bestfree[0].length;
1720 logfree = 1;
1721 }
1722
1723
1724
1725 if (logfree)
1726 xfs_dir2_free_log_bests(tp, fbp, findex, findex);
1727
1728
1729
1730 if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
1731 xfs_da_buf_done(fbp);
1732
1733
1734
1735 args->blkno = (xfs_dablk_t)dbno;
1736 args->index = be16_to_cpu(*tagp);
1737 xfs_da_buf_done(dbp);
1738 return 0;
1739}
1740
1741
1742
1743
1744
1745
1746int
1747xfs_dir2_node_lookup(
1748 xfs_da_args_t *args)
1749{
1750 int error;
1751 int i;
1752 int rval;
1753 xfs_da_state_t *state;
1754
1755 xfs_dir2_trace_args("node_lookup", args);
1756
1757
1758
1759 state = xfs_da_state_alloc();
1760 state->args = args;
1761 state->mp = args->dp->i_mount;
1762 state->blocksize = state->mp->m_dirblksize;
1763 state->node_ents = state->mp->m_dir_node_ents;
1764
1765
1766
1767 error = xfs_da_node_lookup_int(state, &rval);
1768 if (error)
1769 rval = error;
1770
1771
1772
1773 for (i = 0; i < state->path.active; i++) {
1774 xfs_da_brelse(args->trans, state->path.blk[i].bp);
1775 state->path.blk[i].bp = NULL;
1776 }
1777
1778
1779
1780 if (state->extravalid && state->extrablk.bp) {
1781 xfs_da_brelse(args->trans, state->extrablk.bp);
1782 state->extrablk.bp = NULL;
1783 }
1784 xfs_da_state_free(state);
1785 return rval;
1786}
1787
1788
1789
1790
1791int
1792xfs_dir2_node_removename(
1793 xfs_da_args_t *args)
1794{
1795 xfs_da_state_blk_t *blk;
1796 int error;
1797 int rval;
1798 xfs_da_state_t *state;
1799
1800 xfs_dir2_trace_args("node_removename", args);
1801
1802
1803
1804 state = xfs_da_state_alloc();
1805 state->args = args;
1806 state->mp = args->dp->i_mount;
1807 state->blocksize = state->mp->m_dirblksize;
1808 state->node_ents = state->mp->m_dir_node_ents;
1809
1810
1811
1812 error = xfs_da_node_lookup_int(state, &rval);
1813 if (error) {
1814 rval = error;
1815 }
1816
1817
1818
1819 if (rval != EEXIST) {
1820 xfs_da_state_free(state);
1821 return rval;
1822 }
1823 blk = &state->path.blk[state->path.active - 1];
1824 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
1825 ASSERT(state->extravalid);
1826
1827
1828
1829
1830 error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
1831 &state->extrablk, &rval);
1832 if (error) {
1833 return error;
1834 }
1835
1836
1837
1838 xfs_da_fixhashpath(state, &state->path);
1839
1840
1841
1842 if (rval && state->path.active > 1)
1843 error = xfs_da_join(state);
1844
1845
1846
1847 if (!error)
1848 error = xfs_dir2_node_to_leaf(state);
1849 xfs_da_state_free(state);
1850 return error;
1851}
1852
1853
1854
1855
1856int
1857xfs_dir2_node_replace(
1858 xfs_da_args_t *args)
1859{
1860 xfs_da_state_blk_t *blk;
1861 xfs_dir2_data_t *data;
1862 xfs_dir2_data_entry_t *dep;
1863 int error;
1864 int i;
1865 xfs_ino_t inum;
1866 xfs_dir2_leaf_t *leaf;
1867 xfs_dir2_leaf_entry_t *lep;
1868 int rval;
1869 xfs_da_state_t *state;
1870
1871 xfs_dir2_trace_args("node_replace", args);
1872
1873
1874
1875 state = xfs_da_state_alloc();
1876 state->args = args;
1877 state->mp = args->dp->i_mount;
1878 state->blocksize = state->mp->m_dirblksize;
1879 state->node_ents = state->mp->m_dir_node_ents;
1880 inum = args->inumber;
1881
1882
1883
1884 error = xfs_da_node_lookup_int(state, &rval);
1885 if (error) {
1886 rval = error;
1887 }
1888
1889
1890
1891
1892 if (rval == EEXIST) {
1893
1894
1895
1896 blk = &state->path.blk[state->path.active - 1];
1897 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
1898 leaf = blk->bp->data;
1899 lep = &leaf->ents[blk->index];
1900 ASSERT(state->extravalid);
1901
1902
1903
1904 data = state->extrablk.bp->data;
1905 ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC);
1906 dep = (xfs_dir2_data_entry_t *)
1907 ((char *)data +
1908 xfs_dir2_dataptr_to_off(state->mp, be32_to_cpu(lep->address)));
1909 ASSERT(inum != be64_to_cpu(dep->inumber));
1910
1911
1912
1913 dep->inumber = cpu_to_be64(inum);
1914 xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep);
1915 rval = 0;
1916 }
1917
1918
1919
1920 else if (state->extravalid) {
1921 xfs_da_brelse(args->trans, state->extrablk.bp);
1922 state->extrablk.bp = NULL;
1923 }
1924
1925
1926
1927 for (i = 0; i < state->path.active; i++) {
1928 xfs_da_brelse(args->trans, state->path.blk[i].bp);
1929 state->path.blk[i].bp = NULL;
1930 }
1931 xfs_da_state_free(state);
1932 return rval;
1933}
1934
1935
1936
1937
1938
1939int
1940xfs_dir2_node_trim_free(
1941 xfs_da_args_t *args,
1942 xfs_fileoff_t fo,
1943 int *rvalp)
1944{
1945 xfs_dabuf_t *bp;
1946 xfs_inode_t *dp;
1947 int error;
1948 xfs_dir2_free_t *free;
1949 xfs_mount_t *mp;
1950 xfs_trans_t *tp;
1951
1952 dp = args->dp;
1953 mp = dp->i_mount;
1954 tp = args->trans;
1955
1956
1957
1958 if (unlikely(error = xfs_da_read_buf(tp, dp, (xfs_dablk_t)fo, -2, &bp,
1959 XFS_DATA_FORK))) {
1960 return error;
1961 }
1962
1963
1964
1965
1966
1967 if (bp == NULL) {
1968 return 0;
1969 }
1970 free = bp->data;
1971 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
1972
1973
1974
1975 if (be32_to_cpu(free->hdr.nused) > 0) {
1976 xfs_da_brelse(tp, bp);
1977 *rvalp = 0;
1978 return 0;
1979 }
1980
1981
1982
1983 if ((error =
1984 xfs_dir2_shrink_inode(args, xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo),
1985 bp))) {
1986
1987
1988
1989
1990
1991 ASSERT(error != ENOSPC);
1992 xfs_da_brelse(tp, bp);
1993 return error;
1994 }
1995
1996
1997
1998 *rvalp = 1;
1999 return 0;
2000}
2001