1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "xfs.h"
20#include "xfs_fs.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
24#include "xfs_mount.h"
25#include "xfs_da_format.h"
26#include "xfs_da_btree.h"
27#include "xfs_inode.h"
28#include "xfs_bmap.h"
29#include "xfs_dir2.h"
30#include "xfs_dir2_priv.h"
31#include "xfs_error.h"
32#include "xfs_trace.h"
33#include "xfs_trans.h"
34#include "xfs_buf_item.h"
35#include "xfs_cksum.h"
36#include "xfs_log.h"
37
38
39
40
41static int xfs_dir2_leafn_add(struct xfs_buf *bp, xfs_da_args_t *args,
42 int index);
43static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state,
44 xfs_da_state_blk_t *blk1,
45 xfs_da_state_blk_t *blk2);
46static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp,
47 int index, xfs_da_state_blk_t *dblk,
48 int *rval);
49static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
50 xfs_da_state_blk_t *fblk);
51
52
53
54
55#ifdef DEBUG
56static xfs_failaddr_t
57xfs_dir3_leafn_check(
58 struct xfs_inode *dp,
59 struct xfs_buf *bp)
60{
61 struct xfs_dir2_leaf *leaf = bp->b_addr;
62 struct xfs_dir3_icleaf_hdr leafhdr;
63
64 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
65
66 if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) {
67 struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
68 if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn)
69 return __this_address;
70 } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC)
71 return __this_address;
72
73 return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf);
74}
75
76static inline void
77xfs_dir3_leaf_check(
78 struct xfs_inode *dp,
79 struct xfs_buf *bp)
80{
81 xfs_failaddr_t fa;
82
83 fa = xfs_dir3_leafn_check(dp, bp);
84 if (!fa)
85 return;
86 xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,
87 bp->b_addr, __FILE__, __LINE__, fa);
88 ASSERT(0);
89}
90#else
91#define xfs_dir3_leaf_check(dp, bp)
92#endif
93
94static xfs_failaddr_t
95xfs_dir3_free_verify(
96 struct xfs_buf *bp)
97{
98 struct xfs_mount *mp = bp->b_target->bt_mount;
99 struct xfs_dir2_free_hdr *hdr = bp->b_addr;
100
101 if (xfs_sb_version_hascrc(&mp->m_sb)) {
102 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
103
104 if (hdr3->magic != cpu_to_be32(XFS_DIR3_FREE_MAGIC))
105 return __this_address;
106 if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
107 return __this_address;
108 if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
109 return __this_address;
110 if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
111 return __this_address;
112 } else {
113 if (hdr->magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC))
114 return __this_address;
115 }
116
117
118
119 return NULL;
120}
121
122static void
123xfs_dir3_free_read_verify(
124 struct xfs_buf *bp)
125{
126 struct xfs_mount *mp = bp->b_target->bt_mount;
127 xfs_failaddr_t fa;
128
129 if (xfs_sb_version_hascrc(&mp->m_sb) &&
130 !xfs_buf_verify_cksum(bp, XFS_DIR3_FREE_CRC_OFF))
131 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
132 else {
133 fa = xfs_dir3_free_verify(bp);
134 if (fa)
135 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
136 }
137}
138
139static void
140xfs_dir3_free_write_verify(
141 struct xfs_buf *bp)
142{
143 struct xfs_mount *mp = bp->b_target->bt_mount;
144 struct xfs_buf_log_item *bip = bp->b_log_item;
145 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
146 xfs_failaddr_t fa;
147
148 fa = xfs_dir3_free_verify(bp);
149 if (fa) {
150 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
151 return;
152 }
153
154 if (!xfs_sb_version_hascrc(&mp->m_sb))
155 return;
156
157 if (bip)
158 hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
159
160 xfs_buf_update_cksum(bp, XFS_DIR3_FREE_CRC_OFF);
161}
162
163const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
164 .name = "xfs_dir3_free",
165 .verify_read = xfs_dir3_free_read_verify,
166 .verify_write = xfs_dir3_free_write_verify,
167 .verify_struct = xfs_dir3_free_verify,
168};
169
170
171static xfs_failaddr_t
172xfs_dir3_free_header_check(
173 struct xfs_inode *dp,
174 xfs_dablk_t fbno,
175 struct xfs_buf *bp)
176{
177 struct xfs_mount *mp = dp->i_mount;
178 unsigned int firstdb;
179 int maxbests;
180
181 maxbests = dp->d_ops->free_max_bests(mp->m_dir_geo);
182 firstdb = (xfs_dir2_da_to_db(mp->m_dir_geo, fbno) -
183 xfs_dir2_byte_to_db(mp->m_dir_geo, XFS_DIR2_FREE_OFFSET)) *
184 maxbests;
185 if (xfs_sb_version_hascrc(&mp->m_sb)) {
186 struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
187
188 if (be32_to_cpu(hdr3->firstdb) != firstdb)
189 return __this_address;
190 if (be32_to_cpu(hdr3->nvalid) > maxbests)
191 return __this_address;
192 if (be32_to_cpu(hdr3->nvalid) < be32_to_cpu(hdr3->nused))
193 return __this_address;
194 } else {
195 struct xfs_dir2_free_hdr *hdr = bp->b_addr;
196
197 if (be32_to_cpu(hdr->firstdb) != firstdb)
198 return __this_address;
199 if (be32_to_cpu(hdr->nvalid) > maxbests)
200 return __this_address;
201 if (be32_to_cpu(hdr->nvalid) < be32_to_cpu(hdr->nused))
202 return __this_address;
203 }
204 return NULL;
205}
206
207static int
208__xfs_dir3_free_read(
209 struct xfs_trans *tp,
210 struct xfs_inode *dp,
211 xfs_dablk_t fbno,
212 xfs_daddr_t mappedbno,
213 struct xfs_buf **bpp)
214{
215 xfs_failaddr_t fa;
216 int err;
217
218 err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
219 XFS_DATA_FORK, &xfs_dir3_free_buf_ops);
220 if (err || !*bpp)
221 return err;
222
223
224 fa = xfs_dir3_free_header_check(dp, fbno, *bpp);
225 if (fa) {
226 xfs_verifier_error(*bpp, -EFSCORRUPTED, fa);
227 xfs_trans_brelse(tp, *bpp);
228 return -EFSCORRUPTED;
229 }
230
231
232 if (tp)
233 xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_FREE_BUF);
234
235 return 0;
236}
237
238int
239xfs_dir2_free_read(
240 struct xfs_trans *tp,
241 struct xfs_inode *dp,
242 xfs_dablk_t fbno,
243 struct xfs_buf **bpp)
244{
245 return __xfs_dir3_free_read(tp, dp, fbno, -1, bpp);
246}
247
248static int
249xfs_dir2_free_try_read(
250 struct xfs_trans *tp,
251 struct xfs_inode *dp,
252 xfs_dablk_t fbno,
253 struct xfs_buf **bpp)
254{
255 return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp);
256}
257
258static int
259xfs_dir3_free_get_buf(
260 xfs_da_args_t *args,
261 xfs_dir2_db_t fbno,
262 struct xfs_buf **bpp)
263{
264 struct xfs_trans *tp = args->trans;
265 struct xfs_inode *dp = args->dp;
266 struct xfs_mount *mp = dp->i_mount;
267 struct xfs_buf *bp;
268 int error;
269 struct xfs_dir3_icfree_hdr hdr;
270
271 error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, fbno),
272 -1, &bp, XFS_DATA_FORK);
273 if (error)
274 return error;
275
276 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_FREE_BUF);
277 bp->b_ops = &xfs_dir3_free_buf_ops;
278
279
280
281
282
283 memset(bp->b_addr, 0, sizeof(struct xfs_dir3_free_hdr));
284 memset(&hdr, 0, sizeof(hdr));
285
286 if (xfs_sb_version_hascrc(&mp->m_sb)) {
287 struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
288
289 hdr.magic = XFS_DIR3_FREE_MAGIC;
290
291 hdr3->hdr.blkno = cpu_to_be64(bp->b_bn);
292 hdr3->hdr.owner = cpu_to_be64(dp->i_ino);
293 uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_meta_uuid);
294 } else
295 hdr.magic = XFS_DIR2_FREE_MAGIC;
296 dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr);
297 *bpp = bp;
298 return 0;
299}
300
301
302
303
304STATIC void
305xfs_dir2_free_log_bests(
306 struct xfs_da_args *args,
307 struct xfs_buf *bp,
308 int first,
309 int last)
310{
311 xfs_dir2_free_t *free;
312 __be16 *bests;
313
314 free = bp->b_addr;
315 bests = args->dp->d_ops->free_bests_p(free);
316 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
317 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
318 xfs_trans_log_buf(args->trans, bp,
319 (uint)((char *)&bests[first] - (char *)free),
320 (uint)((char *)&bests[last] - (char *)free +
321 sizeof(bests[0]) - 1));
322}
323
324
325
326
327static void
328xfs_dir2_free_log_header(
329 struct xfs_da_args *args,
330 struct xfs_buf *bp)
331{
332#ifdef DEBUG
333 xfs_dir2_free_t *free;
334
335 free = bp->b_addr;
336 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
337 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
338#endif
339 xfs_trans_log_buf(args->trans, bp, 0,
340 args->dp->d_ops->free_hdr_size - 1);
341}
342
343
344
345
346
347
348int
349xfs_dir2_leaf_to_node(
350 xfs_da_args_t *args,
351 struct xfs_buf *lbp)
352{
353 xfs_inode_t *dp;
354 int error;
355 struct xfs_buf *fbp;
356 xfs_dir2_db_t fdb;
357 xfs_dir2_free_t *free;
358 __be16 *from;
359 int i;
360 xfs_dir2_leaf_t *leaf;
361 xfs_dir2_leaf_tail_t *ltp;
362 int n;
363 xfs_dir2_data_off_t off;
364 __be16 *to;
365 xfs_trans_t *tp;
366 struct xfs_dir3_icfree_hdr freehdr;
367
368 trace_xfs_dir2_leaf_to_node(args);
369
370 dp = args->dp;
371 tp = args->trans;
372
373
374
375 if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fdb))) {
376 return error;
377 }
378 ASSERT(fdb == xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET));
379
380
381
382 error = xfs_dir3_free_get_buf(args, fdb, &fbp);
383 if (error)
384 return error;
385
386 free = fbp->b_addr;
387 dp->d_ops->free_hdr_from_disk(&freehdr, free);
388 leaf = lbp->b_addr;
389 ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
390 ASSERT(be32_to_cpu(ltp->bestcount) <=
391 (uint)dp->i_d.di_size / args->geo->blksize);
392
393
394
395
396
397 from = xfs_dir2_leaf_bests_p(ltp);
398 to = dp->d_ops->free_bests_p(free);
399 for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) {
400 if ((off = be16_to_cpu(*from)) != NULLDATAOFF)
401 n++;
402 *to = cpu_to_be16(off);
403 }
404
405
406
407
408 freehdr.nused = n;
409 freehdr.nvalid = be32_to_cpu(ltp->bestcount);
410
411 dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr);
412 xfs_dir2_free_log_bests(args, fbp, 0, freehdr.nvalid - 1);
413 xfs_dir2_free_log_header(args, fbp);
414
415
416
417
418
419
420
421 if (leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC))
422 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC);
423 else
424 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC);
425 lbp->b_ops = &xfs_dir3_leafn_buf_ops;
426 xfs_trans_buf_set_type(tp, lbp, XFS_BLFT_DIR_LEAFN_BUF);
427 xfs_dir3_leaf_log_header(args, lbp);
428 xfs_dir3_leaf_check(dp, lbp);
429 return 0;
430}
431
432
433
434
435
436static int
437xfs_dir2_leafn_add(
438 struct xfs_buf *bp,
439 xfs_da_args_t *args,
440 int index)
441{
442 int compact;
443 xfs_inode_t *dp;
444 int highstale;
445 xfs_dir2_leaf_t *leaf;
446 xfs_dir2_leaf_entry_t *lep;
447 int lfloghigh;
448 int lfloglow;
449 int lowstale;
450 struct xfs_dir3_icleaf_hdr leafhdr;
451 struct xfs_dir2_leaf_entry *ents;
452
453 trace_xfs_dir2_leafn_add(args, index);
454
455 dp = args->dp;
456 leaf = bp->b_addr;
457 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
458 ents = dp->d_ops->leaf_ents_p(leaf);
459
460
461
462
463
464 if (index < 0)
465 return -EFSCORRUPTED;
466
467
468
469
470
471
472
473
474 if (leafhdr.count == dp->d_ops->leaf_max_ents(args->geo)) {
475 if (!leafhdr.stale)
476 return -ENOSPC;
477 compact = leafhdr.stale > 1;
478 } else
479 compact = 0;
480 ASSERT(index == 0 || be32_to_cpu(ents[index - 1].hashval) <= args->hashval);
481 ASSERT(index == leafhdr.count ||
482 be32_to_cpu(ents[index].hashval) >= args->hashval);
483
484 if (args->op_flags & XFS_DA_OP_JUSTCHECK)
485 return 0;
486
487
488
489
490
491 if (compact)
492 xfs_dir3_leaf_compact_x1(&leafhdr, ents, &index, &lowstale,
493 &highstale, &lfloglow, &lfloghigh);
494 else if (leafhdr.stale) {
495
496
497
498 lfloglow = leafhdr.count;
499 lfloghigh = -1;
500 }
501
502
503
504
505 lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale,
506 highstale, &lfloglow, &lfloghigh);
507
508 lep->hashval = cpu_to_be32(args->hashval);
509 lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(args->geo,
510 args->blkno, args->index));
511
512 dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
513 xfs_dir3_leaf_log_header(args, bp);
514 xfs_dir3_leaf_log_ents(args, bp, lfloglow, lfloghigh);
515 xfs_dir3_leaf_check(dp, bp);
516 return 0;
517}
518
519#ifdef DEBUG
520static void
521xfs_dir2_free_hdr_check(
522 struct xfs_inode *dp,
523 struct xfs_buf *bp,
524 xfs_dir2_db_t db)
525{
526 struct xfs_dir3_icfree_hdr hdr;
527
528 dp->d_ops->free_hdr_from_disk(&hdr, bp->b_addr);
529
530 ASSERT((hdr.firstdb %
531 dp->d_ops->free_max_bests(dp->i_mount->m_dir_geo)) == 0);
532 ASSERT(hdr.firstdb <= db);
533 ASSERT(db < hdr.firstdb + hdr.nvalid);
534}
535#else
536#define xfs_dir2_free_hdr_check(dp, bp, db)
537#endif
538
539
540
541
542
543xfs_dahash_t
544xfs_dir2_leaf_lasthash(
545 struct xfs_inode *dp,
546 struct xfs_buf *bp,
547 int *count)
548{
549 struct xfs_dir2_leaf *leaf = bp->b_addr;
550 struct xfs_dir2_leaf_entry *ents;
551 struct xfs_dir3_icleaf_hdr leafhdr;
552
553 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
554
555 ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
556 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC ||
557 leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
558 leafhdr.magic == XFS_DIR3_LEAF1_MAGIC);
559
560 if (count)
561 *count = leafhdr.count;
562 if (!leafhdr.count)
563 return 0;
564
565 ents = dp->d_ops->leaf_ents_p(leaf);
566 return be32_to_cpu(ents[leafhdr.count - 1].hashval);
567}
568
569
570
571
572
573STATIC int
574xfs_dir2_leafn_lookup_for_addname(
575 struct xfs_buf *bp,
576 xfs_da_args_t *args,
577 int *indexp,
578 xfs_da_state_t *state)
579{
580 struct xfs_buf *curbp = NULL;
581 xfs_dir2_db_t curdb = -1;
582 xfs_dir2_db_t curfdb = -1;
583 xfs_inode_t *dp;
584 int error;
585 int fi;
586 xfs_dir2_free_t *free = NULL;
587 int index;
588 xfs_dir2_leaf_t *leaf;
589 int length;
590 xfs_dir2_leaf_entry_t *lep;
591 xfs_mount_t *mp;
592 xfs_dir2_db_t newdb;
593 xfs_dir2_db_t newfdb;
594 xfs_trans_t *tp;
595 struct xfs_dir2_leaf_entry *ents;
596 struct xfs_dir3_icleaf_hdr leafhdr;
597
598 dp = args->dp;
599 tp = args->trans;
600 mp = dp->i_mount;
601 leaf = bp->b_addr;
602 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
603 ents = dp->d_ops->leaf_ents_p(leaf);
604
605 xfs_dir3_leaf_check(dp, bp);
606 ASSERT(leafhdr.count > 0);
607
608
609
610
611 index = xfs_dir2_leaf_search_hash(args, bp);
612
613
614
615 if (state->extravalid) {
616
617 curbp = state->extrablk.bp;
618 curfdb = state->extrablk.blkno;
619 free = curbp->b_addr;
620 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
621 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
622 }
623 length = dp->d_ops->data_entsize(args->namelen);
624
625
626
627 for (lep = &ents[index];
628 index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval;
629 lep++, index++) {
630
631
632
633 if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
634 continue;
635
636
637
638 newdb = xfs_dir2_dataptr_to_db(args->geo,
639 be32_to_cpu(lep->address));
640
641
642
643
644
645
646
647
648 if (newdb != curdb) {
649 __be16 *bests;
650
651 curdb = newdb;
652
653
654
655
656 newfdb = dp->d_ops->db_to_fdb(args->geo, newdb);
657
658
659
660 if (newfdb != curfdb) {
661
662
663
664 if (curbp)
665 xfs_trans_brelse(tp, curbp);
666
667 error = xfs_dir2_free_read(tp, dp,
668 xfs_dir2_db_to_da(args->geo,
669 newfdb),
670 &curbp);
671 if (error)
672 return error;
673 free = curbp->b_addr;
674
675 xfs_dir2_free_hdr_check(dp, curbp, curdb);
676 }
677
678
679
680 fi = dp->d_ops->db_to_fdindex(args->geo, curdb);
681
682
683
684 bests = dp->d_ops->free_bests_p(free);
685 if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) {
686 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
687 XFS_ERRLEVEL_LOW, mp);
688 if (curfdb != newfdb)
689 xfs_trans_brelse(tp, curbp);
690 return -EFSCORRUPTED;
691 }
692 curfdb = newfdb;
693 if (be16_to_cpu(bests[fi]) >= length)
694 goto out;
695 }
696 }
697
698 fi = -1;
699out:
700 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
701 if (curbp) {
702
703 state->extravalid = 1;
704 state->extrablk.bp = curbp;
705 state->extrablk.index = fi;
706 state->extrablk.blkno = curfdb;
707
708
709
710
711
712
713 state->extrablk.magic = XFS_DIR2_FREE_MAGIC;
714 } else {
715 state->extravalid = 0;
716 }
717
718
719
720 *indexp = index;
721 return -ENOENT;
722}
723
724
725
726
727
728STATIC int
729xfs_dir2_leafn_lookup_for_entry(
730 struct xfs_buf *bp,
731 xfs_da_args_t *args,
732 int *indexp,
733 xfs_da_state_t *state)
734{
735 struct xfs_buf *curbp = NULL;
736 xfs_dir2_db_t curdb = -1;
737 xfs_dir2_data_entry_t *dep;
738 xfs_inode_t *dp;
739 int error;
740 int index;
741 xfs_dir2_leaf_t *leaf;
742 xfs_dir2_leaf_entry_t *lep;
743 xfs_mount_t *mp;
744 xfs_dir2_db_t newdb;
745 xfs_trans_t *tp;
746 enum xfs_dacmp cmp;
747 struct xfs_dir2_leaf_entry *ents;
748 struct xfs_dir3_icleaf_hdr leafhdr;
749
750 dp = args->dp;
751 tp = args->trans;
752 mp = dp->i_mount;
753 leaf = bp->b_addr;
754 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
755 ents = dp->d_ops->leaf_ents_p(leaf);
756
757 xfs_dir3_leaf_check(dp, bp);
758 ASSERT(leafhdr.count > 0);
759
760
761
762
763 index = xfs_dir2_leaf_search_hash(args, bp);
764
765
766
767 if (state->extravalid) {
768 curbp = state->extrablk.bp;
769 curdb = state->extrablk.blkno;
770 }
771
772
773
774 for (lep = &ents[index];
775 index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval;
776 lep++, index++) {
777
778
779
780 if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
781 continue;
782
783
784
785 newdb = xfs_dir2_dataptr_to_db(args->geo,
786 be32_to_cpu(lep->address));
787
788
789
790
791
792
793 if (newdb != curdb) {
794
795
796
797
798 if (curbp && (args->cmpresult == XFS_CMP_DIFFERENT ||
799 curdb != state->extrablk.blkno))
800 xfs_trans_brelse(tp, curbp);
801
802
803
804
805 if (args->cmpresult != XFS_CMP_DIFFERENT &&
806 newdb == state->extrablk.blkno) {
807 ASSERT(state->extravalid);
808 curbp = state->extrablk.bp;
809 } else {
810 error = xfs_dir3_data_read(tp, dp,
811 xfs_dir2_db_to_da(args->geo,
812 newdb),
813 -1, &curbp);
814 if (error)
815 return error;
816 }
817 xfs_dir3_data_check(dp, curbp);
818 curdb = newdb;
819 }
820
821
822
823 dep = (xfs_dir2_data_entry_t *)((char *)curbp->b_addr +
824 xfs_dir2_dataptr_to_off(args->geo,
825 be32_to_cpu(lep->address)));
826
827
828
829
830
831 cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
832 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
833
834 if (args->cmpresult != XFS_CMP_DIFFERENT &&
835 curdb != state->extrablk.blkno)
836 xfs_trans_brelse(tp, state->extrablk.bp);
837 args->cmpresult = cmp;
838 args->inumber = be64_to_cpu(dep->inumber);
839 args->filetype = dp->d_ops->data_get_ftype(dep);
840 *indexp = index;
841 state->extravalid = 1;
842 state->extrablk.bp = curbp;
843 state->extrablk.blkno = curdb;
844 state->extrablk.index = (int)((char *)dep -
845 (char *)curbp->b_addr);
846 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
847 curbp->b_ops = &xfs_dir3_data_buf_ops;
848 xfs_trans_buf_set_type(tp, curbp, XFS_BLFT_DIR_DATA_BUF);
849 if (cmp == XFS_CMP_EXACT)
850 return -EEXIST;
851 }
852 }
853 ASSERT(index == leafhdr.count || (args->op_flags & XFS_DA_OP_OKNOENT));
854 if (curbp) {
855 if (args->cmpresult == XFS_CMP_DIFFERENT) {
856
857 state->extravalid = 1;
858 state->extrablk.bp = curbp;
859 state->extrablk.index = -1;
860 state->extrablk.blkno = curdb;
861 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
862 curbp->b_ops = &xfs_dir3_data_buf_ops;
863 xfs_trans_buf_set_type(tp, curbp, XFS_BLFT_DIR_DATA_BUF);
864 } else {
865
866 if (state->extrablk.bp != curbp)
867 xfs_trans_brelse(tp, curbp);
868 }
869 } else {
870 state->extravalid = 0;
871 }
872 *indexp = index;
873 return -ENOENT;
874}
875
876
877
878
879
880
881int
882xfs_dir2_leafn_lookup_int(
883 struct xfs_buf *bp,
884 xfs_da_args_t *args,
885 int *indexp,
886 xfs_da_state_t *state)
887{
888 if (args->op_flags & XFS_DA_OP_ADDNAME)
889 return xfs_dir2_leafn_lookup_for_addname(bp, args, indexp,
890 state);
891 return xfs_dir2_leafn_lookup_for_entry(bp, args, indexp, state);
892}
893
894
895
896
897
898static void
899xfs_dir3_leafn_moveents(
900 xfs_da_args_t *args,
901 struct xfs_buf *bp_s,
902 struct xfs_dir3_icleaf_hdr *shdr,
903 struct xfs_dir2_leaf_entry *sents,
904 int start_s,
905 struct xfs_buf *bp_d,
906 struct xfs_dir3_icleaf_hdr *dhdr,
907 struct xfs_dir2_leaf_entry *dents,
908 int start_d,
909 int count)
910{
911 int stale;
912
913 trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count);
914
915
916
917
918 if (count == 0)
919 return;
920
921
922
923
924
925
926 if (start_d < dhdr->count) {
927 memmove(&dents[start_d + count], &dents[start_d],
928 (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t));
929 xfs_dir3_leaf_log_ents(args, bp_d, start_d + count,
930 count + dhdr->count - 1);
931 }
932
933
934
935
936 if (shdr->stale) {
937 int i;
938
939 for (i = start_s, stale = 0; i < start_s + count; i++) {
940 if (sents[i].address ==
941 cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
942 stale++;
943 }
944 } else
945 stale = 0;
946
947
948
949 memcpy(&dents[start_d], &sents[start_s],
950 count * sizeof(xfs_dir2_leaf_entry_t));
951 xfs_dir3_leaf_log_ents(args, bp_d, start_d, start_d + count - 1);
952
953
954
955
956
957 if (start_s + count < shdr->count) {
958 memmove(&sents[start_s], &sents[start_s + count],
959 count * sizeof(xfs_dir2_leaf_entry_t));
960 xfs_dir3_leaf_log_ents(args, bp_s, start_s, start_s + count - 1);
961 }
962
963
964
965
966 shdr->count -= count;
967 shdr->stale -= stale;
968 dhdr->count += count;
969 dhdr->stale += stale;
970}
971
972
973
974
975
976int
977xfs_dir2_leafn_order(
978 struct xfs_inode *dp,
979 struct xfs_buf *leaf1_bp,
980 struct xfs_buf *leaf2_bp)
981{
982 struct xfs_dir2_leaf *leaf1 = leaf1_bp->b_addr;
983 struct xfs_dir2_leaf *leaf2 = leaf2_bp->b_addr;
984 struct xfs_dir2_leaf_entry *ents1;
985 struct xfs_dir2_leaf_entry *ents2;
986 struct xfs_dir3_icleaf_hdr hdr1;
987 struct xfs_dir3_icleaf_hdr hdr2;
988
989 dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1);
990 dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2);
991 ents1 = dp->d_ops->leaf_ents_p(leaf1);
992 ents2 = dp->d_ops->leaf_ents_p(leaf2);
993
994 if (hdr1.count > 0 && hdr2.count > 0 &&
995 (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) ||
996 be32_to_cpu(ents2[hdr2.count - 1].hashval) <
997 be32_to_cpu(ents1[hdr1.count - 1].hashval)))
998 return 1;
999 return 0;
1000}
1001
1002
1003
1004
1005
1006
1007
1008
1009static void
1010xfs_dir2_leafn_rebalance(
1011 xfs_da_state_t *state,
1012 xfs_da_state_blk_t *blk1,
1013 xfs_da_state_blk_t *blk2)
1014{
1015 xfs_da_args_t *args;
1016 int count;
1017 int isleft;
1018 xfs_dir2_leaf_t *leaf1;
1019 xfs_dir2_leaf_t *leaf2;
1020 int mid;
1021#if defined(DEBUG) || defined(XFS_WARN)
1022 int oldstale;
1023#endif
1024 int oldsum;
1025 int swap;
1026 struct xfs_dir2_leaf_entry *ents1;
1027 struct xfs_dir2_leaf_entry *ents2;
1028 struct xfs_dir3_icleaf_hdr hdr1;
1029 struct xfs_dir3_icleaf_hdr hdr2;
1030 struct xfs_inode *dp = state->args->dp;
1031
1032 args = state->args;
1033
1034
1035
1036 if ((swap = xfs_dir2_leafn_order(dp, blk1->bp, blk2->bp))) {
1037 xfs_da_state_blk_t *tmp;
1038
1039 tmp = blk1;
1040 blk1 = blk2;
1041 blk2 = tmp;
1042 }
1043 leaf1 = blk1->bp->b_addr;
1044 leaf2 = blk2->bp->b_addr;
1045 dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1);
1046 dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2);
1047 ents1 = dp->d_ops->leaf_ents_p(leaf1);
1048 ents2 = dp->d_ops->leaf_ents_p(leaf2);
1049
1050 oldsum = hdr1.count + hdr2.count;
1051#if defined(DEBUG) || defined(XFS_WARN)
1052 oldstale = hdr1.stale + hdr2.stale;
1053#endif
1054 mid = oldsum >> 1;
1055
1056
1057
1058
1059
1060 if (oldsum & 1) {
1061 xfs_dahash_t midhash;
1062
1063 if (mid >= hdr1.count)
1064 midhash = be32_to_cpu(ents2[mid - hdr1.count].hashval);
1065 else
1066 midhash = be32_to_cpu(ents1[mid].hashval);
1067 isleft = args->hashval <= midhash;
1068 }
1069
1070
1071
1072
1073
1074 else
1075 isleft = 1;
1076
1077
1078
1079
1080 count = hdr1.count - mid + (isleft == 0);
1081 if (count > 0)
1082 xfs_dir3_leafn_moveents(args, blk1->bp, &hdr1, ents1,
1083 hdr1.count - count, blk2->bp,
1084 &hdr2, ents2, 0, count);
1085 else if (count < 0)
1086 xfs_dir3_leafn_moveents(args, blk2->bp, &hdr2, ents2, 0,
1087 blk1->bp, &hdr1, ents1,
1088 hdr1.count, count);
1089
1090 ASSERT(hdr1.count + hdr2.count == oldsum);
1091 ASSERT(hdr1.stale + hdr2.stale == oldstale);
1092
1093
1094 dp->d_ops->leaf_hdr_to_disk(leaf1, &hdr1);
1095 dp->d_ops->leaf_hdr_to_disk(leaf2, &hdr2);
1096 xfs_dir3_leaf_log_header(args, blk1->bp);
1097 xfs_dir3_leaf_log_header(args, blk2->bp);
1098
1099 xfs_dir3_leaf_check(dp, blk1->bp);
1100 xfs_dir3_leaf_check(dp, blk2->bp);
1101
1102
1103
1104
1105 if (hdr1.count < hdr2.count)
1106 state->inleaf = swap;
1107 else if (hdr1.count > hdr2.count)
1108 state->inleaf = !swap;
1109 else
1110 state->inleaf = swap ^ (blk1->index <= hdr1.count);
1111
1112
1113
1114 if (!state->inleaf)
1115 blk2->index = blk1->index - hdr1.count;
1116
1117
1118
1119
1120
1121 if (blk2->index < 0) {
1122 state->inleaf = 1;
1123 blk2->index = 0;
1124 xfs_alert(dp->i_mount,
1125 "%s: picked the wrong leaf? reverting original leaf: blk1->index %d",
1126 __func__, blk1->index);
1127 }
1128}
1129
1130static int
1131xfs_dir3_data_block_free(
1132 xfs_da_args_t *args,
1133 struct xfs_dir2_data_hdr *hdr,
1134 struct xfs_dir2_free *free,
1135 xfs_dir2_db_t fdb,
1136 int findex,
1137 struct xfs_buf *fbp,
1138 int longest)
1139{
1140 int logfree = 0;
1141 __be16 *bests;
1142 struct xfs_dir3_icfree_hdr freehdr;
1143 struct xfs_inode *dp = args->dp;
1144
1145 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1146 bests = dp->d_ops->free_bests_p(free);
1147 if (hdr) {
1148
1149
1150
1151
1152 bests[findex] = cpu_to_be16(longest);
1153 xfs_dir2_free_log_bests(args, fbp, findex, findex);
1154 return 0;
1155 }
1156
1157
1158 freehdr.nused--;
1159
1160
1161
1162
1163
1164
1165 if (findex == freehdr.nvalid - 1) {
1166 int i;
1167
1168 for (i = findex - 1; i >= 0; i--) {
1169 if (bests[i] != cpu_to_be16(NULLDATAOFF))
1170 break;
1171 }
1172 freehdr.nvalid = i + 1;
1173 logfree = 0;
1174 } else {
1175
1176 bests[findex] = cpu_to_be16(NULLDATAOFF);
1177 logfree = 1;
1178 }
1179
1180 dp->d_ops->free_hdr_to_disk(free, &freehdr);
1181 xfs_dir2_free_log_header(args, fbp);
1182
1183
1184
1185
1186
1187 if (!freehdr.nused) {
1188 int error;
1189
1190 error = xfs_dir2_shrink_inode(args, fdb, fbp);
1191 if (error == 0) {
1192 fbp = NULL;
1193 logfree = 0;
1194 } else if (error != -ENOSPC || args->total != 0)
1195 return error;
1196
1197
1198
1199
1200
1201 }
1202
1203
1204 if (logfree)
1205 xfs_dir2_free_log_bests(args, fbp, findex, findex);
1206 return 0;
1207}
1208
1209
1210
1211
1212
1213
1214static int
1215xfs_dir2_leafn_remove(
1216 xfs_da_args_t *args,
1217 struct xfs_buf *bp,
1218 int index,
1219 xfs_da_state_blk_t *dblk,
1220 int *rval)
1221{
1222 xfs_dir2_data_hdr_t *hdr;
1223 xfs_dir2_db_t db;
1224 struct xfs_buf *dbp;
1225 xfs_dir2_data_entry_t *dep;
1226 xfs_inode_t *dp;
1227 xfs_dir2_leaf_t *leaf;
1228 xfs_dir2_leaf_entry_t *lep;
1229 int longest;
1230 int off;
1231 int needlog;
1232 int needscan;
1233 xfs_trans_t *tp;
1234 struct xfs_dir2_data_free *bf;
1235 struct xfs_dir3_icleaf_hdr leafhdr;
1236 struct xfs_dir2_leaf_entry *ents;
1237
1238 trace_xfs_dir2_leafn_remove(args, index);
1239
1240 dp = args->dp;
1241 tp = args->trans;
1242 leaf = bp->b_addr;
1243 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
1244 ents = dp->d_ops->leaf_ents_p(leaf);
1245
1246
1247
1248
1249 lep = &ents[index];
1250
1251
1252
1253
1254 db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address));
1255 ASSERT(dblk->blkno == db);
1256 off = xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address));
1257 ASSERT(dblk->index == off);
1258
1259
1260
1261
1262
1263 leafhdr.stale++;
1264 dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
1265 xfs_dir3_leaf_log_header(args, bp);
1266
1267 lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
1268 xfs_dir3_leaf_log_ents(args, bp, index, index);
1269
1270
1271
1272
1273
1274 dbp = dblk->bp;
1275 hdr = dbp->b_addr;
1276 dep = (xfs_dir2_data_entry_t *)((char *)hdr + off);
1277 bf = dp->d_ops->data_bestfree_p(hdr);
1278 longest = be16_to_cpu(bf[0].length);
1279 needlog = needscan = 0;
1280 xfs_dir2_data_make_free(args, dbp, off,
1281 dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
1282
1283
1284
1285
1286 if (needscan)
1287 xfs_dir2_data_freescan(dp, hdr, &needlog);
1288 if (needlog)
1289 xfs_dir2_data_log_header(args, dbp);
1290 xfs_dir3_data_check(dp, dbp);
1291
1292
1293
1294
1295 if (longest < be16_to_cpu(bf[0].length)) {
1296 int error;
1297 struct xfs_buf *fbp;
1298 xfs_dir2_db_t fdb;
1299 int findex;
1300 xfs_dir2_free_t *free;
1301
1302
1303
1304
1305
1306 fdb = dp->d_ops->db_to_fdb(args->geo, db);
1307 error = xfs_dir2_free_read(tp, dp,
1308 xfs_dir2_db_to_da(args->geo, fdb),
1309 &fbp);
1310 if (error)
1311 return error;
1312 free = fbp->b_addr;
1313#ifdef DEBUG
1314 {
1315 struct xfs_dir3_icfree_hdr freehdr;
1316 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1317 ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(args->geo) *
1318 (fdb - xfs_dir2_byte_to_db(args->geo,
1319 XFS_DIR2_FREE_OFFSET)));
1320 }
1321#endif
1322
1323
1324
1325 findex = dp->d_ops->db_to_fdindex(args->geo, db);
1326 longest = be16_to_cpu(bf[0].length);
1327
1328
1329
1330
1331 if (longest == args->geo->blksize -
1332 dp->d_ops->data_entry_offset) {
1333
1334
1335
1336 error = xfs_dir2_shrink_inode(args, db, dbp);
1337 if (error == 0) {
1338 dblk->bp = NULL;
1339 hdr = NULL;
1340 }
1341
1342
1343
1344
1345
1346 else if (!(error == -ENOSPC && args->total == 0))
1347 return error;
1348 }
1349
1350
1351
1352
1353 error = xfs_dir3_data_block_free(args, hdr, free,
1354 fdb, findex, fbp, longest);
1355 if (error)
1356 return error;
1357 }
1358
1359 xfs_dir3_leaf_check(dp, bp);
1360
1361
1362
1363
1364 *rval = (dp->d_ops->leaf_hdr_size +
1365 (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) <
1366 args->geo->magicpct;
1367 return 0;
1368}
1369
1370
1371
1372
1373int
1374xfs_dir2_leafn_split(
1375 xfs_da_state_t *state,
1376 xfs_da_state_blk_t *oldblk,
1377 xfs_da_state_blk_t *newblk)
1378{
1379 xfs_da_args_t *args;
1380 xfs_dablk_t blkno;
1381 int error;
1382 struct xfs_inode *dp;
1383
1384
1385
1386
1387 args = state->args;
1388 dp = args->dp;
1389 ASSERT(oldblk->magic == XFS_DIR2_LEAFN_MAGIC);
1390 error = xfs_da_grow_inode(args, &blkno);
1391 if (error) {
1392 return error;
1393 }
1394
1395
1396
1397 error = xfs_dir3_leaf_get_buf(args, xfs_dir2_da_to_db(args->geo, blkno),
1398 &newblk->bp, XFS_DIR2_LEAFN_MAGIC);
1399 if (error)
1400 return error;
1401
1402 newblk->blkno = blkno;
1403 newblk->magic = XFS_DIR2_LEAFN_MAGIC;
1404
1405
1406
1407
1408 xfs_dir2_leafn_rebalance(state, oldblk, newblk);
1409 error = xfs_da3_blk_link(state, oldblk, newblk);
1410 if (error) {
1411 return error;
1412 }
1413
1414
1415
1416 if (state->inleaf)
1417 error = xfs_dir2_leafn_add(oldblk->bp, args, oldblk->index);
1418 else
1419 error = xfs_dir2_leafn_add(newblk->bp, args, newblk->index);
1420
1421
1422
1423 oldblk->hashval = xfs_dir2_leaf_lasthash(dp, oldblk->bp, NULL);
1424 newblk->hashval = xfs_dir2_leaf_lasthash(dp, newblk->bp, NULL);
1425 xfs_dir3_leaf_check(dp, oldblk->bp);
1426 xfs_dir3_leaf_check(dp, newblk->bp);
1427 return error;
1428}
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439int
1440xfs_dir2_leafn_toosmall(
1441 xfs_da_state_t *state,
1442 int *action)
1443{
1444 xfs_da_state_blk_t *blk;
1445 xfs_dablk_t blkno;
1446 struct xfs_buf *bp;
1447 int bytes;
1448 int count;
1449 int error;
1450 int forward;
1451 int i;
1452 xfs_dir2_leaf_t *leaf;
1453 int rval;
1454 struct xfs_dir3_icleaf_hdr leafhdr;
1455 struct xfs_dir2_leaf_entry *ents;
1456 struct xfs_inode *dp = state->args->dp;
1457
1458
1459
1460
1461
1462
1463 blk = &state->path.blk[state->path.active - 1];
1464 leaf = blk->bp->b_addr;
1465 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
1466 ents = dp->d_ops->leaf_ents_p(leaf);
1467 xfs_dir3_leaf_check(dp, blk->bp);
1468
1469 count = leafhdr.count - leafhdr.stale;
1470 bytes = dp->d_ops->leaf_hdr_size + count * sizeof(ents[0]);
1471 if (bytes > (state->args->geo->blksize >> 1)) {
1472
1473
1474
1475 *action = 0;
1476 return 0;
1477 }
1478
1479
1480
1481
1482
1483
1484 if (count == 0) {
1485
1486
1487
1488
1489 forward = (leafhdr.forw != 0);
1490 memcpy(&state->altpath, &state->path, sizeof(state->path));
1491 error = xfs_da3_path_shift(state, &state->altpath, forward, 0,
1492 &rval);
1493 if (error)
1494 return error;
1495 *action = rval ? 2 : 0;
1496 return 0;
1497 }
1498
1499
1500
1501
1502
1503
1504
1505 forward = leafhdr.forw < leafhdr.back;
1506 for (i = 0, bp = NULL; i < 2; forward = !forward, i++) {
1507 struct xfs_dir3_icleaf_hdr hdr2;
1508
1509 blkno = forward ? leafhdr.forw : leafhdr.back;
1510 if (blkno == 0)
1511 continue;
1512
1513
1514
1515 error = xfs_dir3_leafn_read(state->args->trans, dp,
1516 blkno, -1, &bp);
1517 if (error)
1518 return error;
1519
1520
1521
1522
1523 count = leafhdr.count - leafhdr.stale;
1524 bytes = state->args->geo->blksize -
1525 (state->args->geo->blksize >> 2);
1526
1527 leaf = bp->b_addr;
1528 dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf);
1529 ents = dp->d_ops->leaf_ents_p(leaf);
1530 count += hdr2.count - hdr2.stale;
1531 bytes -= count * sizeof(ents[0]);
1532
1533
1534
1535
1536 if (bytes >= 0)
1537 break;
1538 xfs_trans_brelse(state->args->trans, bp);
1539 }
1540
1541
1542
1543 if (i >= 2) {
1544 *action = 0;
1545 return 0;
1546 }
1547
1548
1549
1550
1551
1552 memcpy(&state->altpath, &state->path, sizeof(state->path));
1553 if (blkno < blk->blkno)
1554 error = xfs_da3_path_shift(state, &state->altpath, forward, 0,
1555 &rval);
1556 else
1557 error = xfs_da3_path_shift(state, &state->path, forward, 0,
1558 &rval);
1559 if (error) {
1560 return error;
1561 }
1562 *action = rval ? 0 : 1;
1563 return 0;
1564}
1565
1566
1567
1568
1569
1570void
1571xfs_dir2_leafn_unbalance(
1572 xfs_da_state_t *state,
1573 xfs_da_state_blk_t *drop_blk,
1574 xfs_da_state_blk_t *save_blk)
1575{
1576 xfs_da_args_t *args;
1577 xfs_dir2_leaf_t *drop_leaf;
1578 xfs_dir2_leaf_t *save_leaf;
1579 struct xfs_dir3_icleaf_hdr savehdr;
1580 struct xfs_dir3_icleaf_hdr drophdr;
1581 struct xfs_dir2_leaf_entry *sents;
1582 struct xfs_dir2_leaf_entry *dents;
1583 struct xfs_inode *dp = state->args->dp;
1584
1585 args = state->args;
1586 ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
1587 ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC);
1588 drop_leaf = drop_blk->bp->b_addr;
1589 save_leaf = save_blk->bp->b_addr;
1590
1591 dp->d_ops->leaf_hdr_from_disk(&savehdr, save_leaf);
1592 dp->d_ops->leaf_hdr_from_disk(&drophdr, drop_leaf);
1593 sents = dp->d_ops->leaf_ents_p(save_leaf);
1594 dents = dp->d_ops->leaf_ents_p(drop_leaf);
1595
1596
1597
1598
1599
1600 if (drophdr.stale)
1601 xfs_dir3_leaf_compact(args, &drophdr, drop_blk->bp);
1602 if (savehdr.stale)
1603 xfs_dir3_leaf_compact(args, &savehdr, save_blk->bp);
1604
1605
1606
1607
1608 drop_blk->hashval = be32_to_cpu(dents[drophdr.count - 1].hashval);
1609 if (xfs_dir2_leafn_order(dp, save_blk->bp, drop_blk->bp))
1610 xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0,
1611 save_blk->bp, &savehdr, sents, 0,
1612 drophdr.count);
1613 else
1614 xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0,
1615 save_blk->bp, &savehdr, sents,
1616 savehdr.count, drophdr.count);
1617 save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval);
1618
1619
1620 dp->d_ops->leaf_hdr_to_disk(save_leaf, &savehdr);
1621 dp->d_ops->leaf_hdr_to_disk(drop_leaf, &drophdr);
1622 xfs_dir3_leaf_log_header(args, save_blk->bp);
1623 xfs_dir3_leaf_log_header(args, drop_blk->bp);
1624
1625 xfs_dir3_leaf_check(dp, save_blk->bp);
1626 xfs_dir3_leaf_check(dp, drop_blk->bp);
1627}
1628
1629
1630
1631
1632int
1633xfs_dir2_node_addname(
1634 xfs_da_args_t *args)
1635{
1636 xfs_da_state_blk_t *blk;
1637 int error;
1638 int rval;
1639 xfs_da_state_t *state;
1640
1641 trace_xfs_dir2_node_addname(args);
1642
1643
1644
1645
1646 state = xfs_da_state_alloc();
1647 state->args = args;
1648 state->mp = args->dp->i_mount;
1649
1650
1651
1652
1653 error = xfs_da3_node_lookup_int(state, &rval);
1654 if (error)
1655 rval = error;
1656 if (rval != -ENOENT) {
1657 goto done;
1658 }
1659
1660
1661
1662
1663 rval = xfs_dir2_node_addname_int(args,
1664 state->extravalid ? &state->extrablk : NULL);
1665 if (rval) {
1666 goto done;
1667 }
1668 blk = &state->path.blk[state->path.active - 1];
1669 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
1670
1671
1672
1673 rval = xfs_dir2_leafn_add(blk->bp, args, blk->index);
1674 if (rval == 0) {
1675
1676
1677
1678 if (!(args->op_flags & XFS_DA_OP_JUSTCHECK))
1679 xfs_da3_fixhashpath(state, &state->path);
1680 } else {
1681
1682
1683
1684 if (args->total == 0) {
1685 ASSERT(rval == -ENOSPC);
1686 goto done;
1687 }
1688
1689
1690
1691 rval = xfs_da3_split(state);
1692 }
1693done:
1694 xfs_da_state_free(state);
1695 return rval;
1696}
1697
1698
1699
1700
1701
1702
1703static int
1704xfs_dir2_node_addname_int(
1705 xfs_da_args_t *args,
1706 xfs_da_state_blk_t *fblk)
1707{
1708 xfs_dir2_data_hdr_t *hdr;
1709 xfs_dir2_db_t dbno;
1710 struct xfs_buf *dbp;
1711 xfs_dir2_data_entry_t *dep;
1712 xfs_inode_t *dp;
1713 xfs_dir2_data_unused_t *dup;
1714 int error;
1715 xfs_dir2_db_t fbno;
1716 struct xfs_buf *fbp;
1717 int findex;
1718 xfs_dir2_free_t *free=NULL;
1719 xfs_dir2_db_t ifbno;
1720 xfs_dir2_db_t lastfbno=0;
1721 int length;
1722 int logfree;
1723 xfs_mount_t *mp;
1724 int needlog;
1725 int needscan;
1726 __be16 *tagp;
1727 xfs_trans_t *tp;
1728 __be16 *bests;
1729 struct xfs_dir3_icfree_hdr freehdr;
1730 struct xfs_dir2_data_free *bf;
1731
1732 dp = args->dp;
1733 mp = dp->i_mount;
1734 tp = args->trans;
1735 length = dp->d_ops->data_entsize(args->namelen);
1736
1737
1738
1739
1740
1741 if (fblk) {
1742 fbp = fblk->bp;
1743
1744
1745
1746 ifbno = fblk->blkno;
1747 free = fbp->b_addr;
1748 findex = fblk->index;
1749 bests = dp->d_ops->free_bests_p(free);
1750 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1751
1752
1753
1754
1755
1756
1757 if (findex >= 0) {
1758 ASSERT(findex < freehdr.nvalid);
1759 ASSERT(be16_to_cpu(bests[findex]) != NULLDATAOFF);
1760 ASSERT(be16_to_cpu(bests[findex]) >= length);
1761 dbno = freehdr.firstdb + findex;
1762 } else {
1763
1764
1765
1766
1767 dbno = -1;
1768 findex = 0;
1769 }
1770 } else {
1771
1772
1773
1774 ifbno = dbno = -1;
1775 fbp = NULL;
1776 findex = 0;
1777 }
1778
1779
1780
1781
1782
1783
1784 if (dbno == -1) {
1785 xfs_fileoff_t fo;
1786
1787 if ((error = xfs_bmap_last_offset(dp, &fo, XFS_DATA_FORK)))
1788 return error;
1789 lastfbno = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo);
1790 fbno = ifbno;
1791 }
1792
1793
1794
1795
1796
1797 while (dbno == -1) {
1798
1799
1800
1801 if (fbp == NULL) {
1802
1803
1804
1805
1806 if (++fbno == 0)
1807 fbno = xfs_dir2_byte_to_db(args->geo,
1808 XFS_DIR2_FREE_OFFSET);
1809
1810
1811
1812 if (fbno == ifbno)
1813 fbno++;
1814
1815
1816
1817 if (fbno >= lastfbno)
1818 break;
1819
1820
1821
1822
1823
1824
1825 error = xfs_dir2_free_try_read(tp, dp,
1826 xfs_dir2_db_to_da(args->geo, fbno),
1827 &fbp);
1828 if (error)
1829 return error;
1830 if (!fbp)
1831 continue;
1832 free = fbp->b_addr;
1833 findex = 0;
1834 }
1835
1836
1837
1838
1839
1840
1841
1842
1843 bests = dp->d_ops->free_bests_p(free);
1844 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1845 if (be16_to_cpu(bests[findex]) != NULLDATAOFF &&
1846 be16_to_cpu(bests[findex]) >= length)
1847 dbno = freehdr.firstdb + findex;
1848 else {
1849
1850
1851
1852 if (++findex == freehdr.nvalid) {
1853
1854
1855
1856 xfs_trans_brelse(tp, fbp);
1857 fbp = NULL;
1858 if (fblk && fblk->bp)
1859 fblk->bp = NULL;
1860 }
1861 }
1862 }
1863
1864
1865
1866
1867 if (unlikely(dbno == -1)) {
1868
1869
1870
1871 if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0)
1872 return -ENOSPC;
1873
1874
1875
1876
1877 if (unlikely((error = xfs_dir2_grow_inode(args,
1878 XFS_DIR2_DATA_SPACE,
1879 &dbno)) ||
1880 (error = xfs_dir3_data_init(args, dbno, &dbp))))
1881 return error;
1882
1883
1884
1885
1886 if (fbp)
1887 xfs_trans_brelse(tp, fbp);
1888 if (fblk && fblk->bp)
1889 fblk->bp = NULL;
1890
1891
1892
1893
1894
1895 fbno = dp->d_ops->db_to_fdb(args->geo, dbno);
1896 error = xfs_dir2_free_try_read(tp, dp,
1897 xfs_dir2_db_to_da(args->geo, fbno),
1898 &fbp);
1899 if (error)
1900 return error;
1901
1902
1903
1904
1905
1906 if (!fbp) {
1907 error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE,
1908 &fbno);
1909 if (error)
1910 return error;
1911
1912 if (dp->d_ops->db_to_fdb(args->geo, dbno) != fbno) {
1913 xfs_alert(mp,
1914"%s: dir ino %llu needed freesp block %lld for data block %lld, got %lld ifbno %llu lastfbno %d",
1915 __func__, (unsigned long long)dp->i_ino,
1916 (long long)dp->d_ops->db_to_fdb(
1917 args->geo, dbno),
1918 (long long)dbno, (long long)fbno,
1919 (unsigned long long)ifbno, lastfbno);
1920 if (fblk) {
1921 xfs_alert(mp,
1922 " fblk "PTR_FMT" blkno %llu index %d magic 0x%x",
1923 fblk,
1924 (unsigned long long)fblk->blkno,
1925 fblk->index,
1926 fblk->magic);
1927 } else {
1928 xfs_alert(mp, " ... fblk is NULL");
1929 }
1930 XFS_ERROR_REPORT("xfs_dir2_node_addname_int",
1931 XFS_ERRLEVEL_LOW, mp);
1932 return -EFSCORRUPTED;
1933 }
1934
1935
1936
1937
1938 error = xfs_dir3_free_get_buf(args, fbno, &fbp);
1939 if (error)
1940 return error;
1941 free = fbp->b_addr;
1942 bests = dp->d_ops->free_bests_p(free);
1943 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1944
1945
1946
1947
1948 freehdr.firstdb =
1949 (fbno - xfs_dir2_byte_to_db(args->geo,
1950 XFS_DIR2_FREE_OFFSET)) *
1951 dp->d_ops->free_max_bests(args->geo);
1952 } else {
1953 free = fbp->b_addr;
1954 bests = dp->d_ops->free_bests_p(free);
1955 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1956 }
1957
1958
1959
1960
1961 findex = dp->d_ops->db_to_fdindex(args->geo, dbno);
1962
1963
1964
1965
1966 if (findex >= freehdr.nvalid) {
1967 ASSERT(findex < dp->d_ops->free_max_bests(args->geo));
1968 freehdr.nvalid = findex + 1;
1969
1970
1971
1972 bests[findex] = cpu_to_be16(NULLDATAOFF);
1973 }
1974
1975
1976
1977
1978 if (bests[findex] == cpu_to_be16(NULLDATAOFF)) {
1979 freehdr.nused++;
1980 dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr);
1981 xfs_dir2_free_log_header(args, fbp);
1982 }
1983
1984
1985
1986
1987
1988 hdr = dbp->b_addr;
1989 bf = dp->d_ops->data_bestfree_p(hdr);
1990 bests[findex] = bf[0].length;
1991 logfree = 1;
1992 }
1993
1994
1995
1996 else {
1997
1998
1999
2000 if (args->op_flags & XFS_DA_OP_JUSTCHECK)
2001 return 0;
2002
2003
2004
2005
2006 error = xfs_dir3_data_read(tp, dp,
2007 xfs_dir2_db_to_da(args->geo, dbno),
2008 -1, &dbp);
2009 if (error)
2010 return error;
2011 hdr = dbp->b_addr;
2012 bf = dp->d_ops->data_bestfree_p(hdr);
2013 logfree = 0;
2014 }
2015 ASSERT(be16_to_cpu(bf[0].length) >= length);
2016
2017
2018
2019 dup = (xfs_dir2_data_unused_t *)
2020 ((char *)hdr + be16_to_cpu(bf[0].offset));
2021 needscan = needlog = 0;
2022
2023
2024
2025 xfs_dir2_data_use_free(args, dbp, dup,
2026 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length,
2027 &needlog, &needscan);
2028
2029
2030
2031 dep = (xfs_dir2_data_entry_t *)dup;
2032 dep->inumber = cpu_to_be64(args->inumber);
2033 dep->namelen = args->namelen;
2034 memcpy(dep->name, args->name, dep->namelen);
2035 dp->d_ops->data_put_ftype(dep, args->filetype);
2036 tagp = dp->d_ops->data_entry_tag_p(dep);
2037 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
2038 xfs_dir2_data_log_entry(args, dbp, dep);
2039
2040
2041
2042 if (needscan)
2043 xfs_dir2_data_freescan(dp, hdr, &needlog);
2044
2045
2046
2047 if (needlog)
2048 xfs_dir2_data_log_header(args, dbp);
2049
2050
2051
2052 bests = dp->d_ops->free_bests_p(free);
2053 if (be16_to_cpu(bests[findex]) != be16_to_cpu(bf[0].length)) {
2054 bests[findex] = bf[0].length;
2055 logfree = 1;
2056 }
2057
2058
2059
2060 if (logfree)
2061 xfs_dir2_free_log_bests(args, fbp, findex, findex);
2062
2063
2064
2065 args->blkno = (xfs_dablk_t)dbno;
2066 args->index = be16_to_cpu(*tagp);
2067 return 0;
2068}
2069
2070
2071
2072
2073
2074
2075int
2076xfs_dir2_node_lookup(
2077 xfs_da_args_t *args)
2078{
2079 int error;
2080 int i;
2081 int rval;
2082 xfs_da_state_t *state;
2083
2084 trace_xfs_dir2_node_lookup(args);
2085
2086
2087
2088
2089 state = xfs_da_state_alloc();
2090 state->args = args;
2091 state->mp = args->dp->i_mount;
2092
2093
2094
2095 error = xfs_da3_node_lookup_int(state, &rval);
2096 if (error)
2097 rval = error;
2098 else if (rval == -ENOENT && args->cmpresult == XFS_CMP_CASE) {
2099
2100 xfs_dir2_data_entry_t *dep;
2101
2102 dep = (xfs_dir2_data_entry_t *)
2103 ((char *)state->extrablk.bp->b_addr +
2104 state->extrablk.index);
2105 rval = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
2106 }
2107
2108
2109
2110 for (i = 0; i < state->path.active; i++) {
2111 xfs_trans_brelse(args->trans, state->path.blk[i].bp);
2112 state->path.blk[i].bp = NULL;
2113 }
2114
2115
2116
2117 if (state->extravalid && state->extrablk.bp) {
2118 xfs_trans_brelse(args->trans, state->extrablk.bp);
2119 state->extrablk.bp = NULL;
2120 }
2121 xfs_da_state_free(state);
2122 return rval;
2123}
2124
2125
2126
2127
2128int
2129xfs_dir2_node_removename(
2130 struct xfs_da_args *args)
2131{
2132 struct xfs_da_state_blk *blk;
2133 int error;
2134 int rval;
2135 struct xfs_da_state *state;
2136
2137 trace_xfs_dir2_node_removename(args);
2138
2139
2140
2141
2142 state = xfs_da_state_alloc();
2143 state->args = args;
2144 state->mp = args->dp->i_mount;
2145
2146
2147 error = xfs_da3_node_lookup_int(state, &rval);
2148 if (error)
2149 goto out_free;
2150
2151
2152 if (rval != -EEXIST) {
2153 error = rval;
2154 goto out_free;
2155 }
2156
2157 blk = &state->path.blk[state->path.active - 1];
2158 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
2159 ASSERT(state->extravalid);
2160
2161
2162
2163
2164 error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
2165 &state->extrablk, &rval);
2166 if (error)
2167 goto out_free;
2168
2169
2170
2171 xfs_da3_fixhashpath(state, &state->path);
2172
2173
2174
2175 if (rval && state->path.active > 1)
2176 error = xfs_da3_join(state);
2177
2178
2179
2180 if (!error)
2181 error = xfs_dir2_node_to_leaf(state);
2182out_free:
2183 xfs_da_state_free(state);
2184 return error;
2185}
2186
2187
2188
2189
2190int
2191xfs_dir2_node_replace(
2192 xfs_da_args_t *args)
2193{
2194 xfs_da_state_blk_t *blk;
2195 xfs_dir2_data_hdr_t *hdr;
2196 xfs_dir2_data_entry_t *dep;
2197 int error;
2198 int i;
2199 xfs_ino_t inum;
2200 int ftype;
2201 xfs_dir2_leaf_t *leaf;
2202 xfs_dir2_leaf_entry_t *lep;
2203 int rval;
2204 xfs_da_state_t *state;
2205
2206 trace_xfs_dir2_node_replace(args);
2207
2208
2209
2210
2211 state = xfs_da_state_alloc();
2212 state->args = args;
2213 state->mp = args->dp->i_mount;
2214
2215
2216
2217
2218
2219 inum = args->inumber;
2220 ftype = args->filetype;
2221
2222
2223
2224
2225 error = xfs_da3_node_lookup_int(state, &rval);
2226 if (error) {
2227 rval = error;
2228 }
2229
2230
2231
2232
2233 if (rval == -EEXIST) {
2234 struct xfs_dir2_leaf_entry *ents;
2235
2236
2237
2238 blk = &state->path.blk[state->path.active - 1];
2239 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
2240 leaf = blk->bp->b_addr;
2241 ents = args->dp->d_ops->leaf_ents_p(leaf);
2242 lep = &ents[blk->index];
2243 ASSERT(state->extravalid);
2244
2245
2246
2247 hdr = state->extrablk.bp->b_addr;
2248 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
2249 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
2250 dep = (xfs_dir2_data_entry_t *)
2251 ((char *)hdr +
2252 xfs_dir2_dataptr_to_off(args->geo,
2253 be32_to_cpu(lep->address)));
2254 ASSERT(inum != be64_to_cpu(dep->inumber));
2255
2256
2257
2258 dep->inumber = cpu_to_be64(inum);
2259 args->dp->d_ops->data_put_ftype(dep, ftype);
2260 xfs_dir2_data_log_entry(args, state->extrablk.bp, dep);
2261 rval = 0;
2262 }
2263
2264
2265
2266 else if (state->extravalid) {
2267 xfs_trans_brelse(args->trans, state->extrablk.bp);
2268 state->extrablk.bp = NULL;
2269 }
2270
2271
2272
2273 for (i = 0; i < state->path.active; i++) {
2274 xfs_trans_brelse(args->trans, state->path.blk[i].bp);
2275 state->path.blk[i].bp = NULL;
2276 }
2277 xfs_da_state_free(state);
2278 return rval;
2279}
2280
2281
2282
2283
2284
2285int
2286xfs_dir2_node_trim_free(
2287 xfs_da_args_t *args,
2288 xfs_fileoff_t fo,
2289 int *rvalp)
2290{
2291 struct xfs_buf *bp;
2292 xfs_inode_t *dp;
2293 int error;
2294 xfs_dir2_free_t *free;
2295 xfs_trans_t *tp;
2296 struct xfs_dir3_icfree_hdr freehdr;
2297
2298 dp = args->dp;
2299 tp = args->trans;
2300
2301 *rvalp = 0;
2302
2303
2304
2305
2306 error = xfs_dir2_free_try_read(tp, dp, fo, &bp);
2307 if (error)
2308 return error;
2309
2310
2311
2312
2313 if (!bp)
2314 return 0;
2315 free = bp->b_addr;
2316 dp->d_ops->free_hdr_from_disk(&freehdr, free);
2317
2318
2319
2320
2321 if (freehdr.nused > 0) {
2322 xfs_trans_brelse(tp, bp);
2323 return 0;
2324 }
2325
2326
2327
2328 error = xfs_dir2_shrink_inode(args,
2329 xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo), bp);
2330 if (error) {
2331
2332
2333
2334
2335
2336 ASSERT(error != -ENOSPC);
2337 xfs_trans_brelse(tp, bp);
2338 return error;
2339 }
2340
2341
2342
2343 *rvalp = 1;
2344 return 0;
2345}
2346