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