diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_node.c')
-rw-r--r-- | fs/xfs/xfs_dir2_node.c | 402 |
1 files changed, 239 insertions, 163 deletions
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 8dade711f099..fa6c3a5ddbc6 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -226,7 +226,7 @@ xfs_dir2_leafn_add( | |||
226 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || | 226 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || |
227 | be32_to_cpu(leaf->ents[index].hashval) >= args->hashval); | 227 | be32_to_cpu(leaf->ents[index].hashval) >= args->hashval); |
228 | 228 | ||
229 | if (args->justcheck) | 229 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) |
230 | return 0; | 230 | return 0; |
231 | 231 | ||
232 | /* | 232 | /* |
@@ -387,28 +387,26 @@ xfs_dir2_leafn_lasthash( | |||
387 | } | 387 | } |
388 | 388 | ||
389 | /* | 389 | /* |
390 | * Look up a leaf entry in a node-format leaf block. | 390 | * Look up a leaf entry for space to add a name in a node-format leaf block. |
391 | * If this is an addname then the extrablk in state is a freespace block, | 391 | * The extrablk in state is a freespace block. |
392 | * otherwise it's a data block. | ||
393 | */ | 392 | */ |
394 | int | 393 | STATIC int |
395 | xfs_dir2_leafn_lookup_int( | 394 | xfs_dir2_leafn_lookup_for_addname( |
396 | xfs_dabuf_t *bp, /* leaf buffer */ | 395 | xfs_dabuf_t *bp, /* leaf buffer */ |
397 | xfs_da_args_t *args, /* operation arguments */ | 396 | xfs_da_args_t *args, /* operation arguments */ |
398 | int *indexp, /* out: leaf entry index */ | 397 | int *indexp, /* out: leaf entry index */ |
399 | xfs_da_state_t *state) /* state to fill in */ | 398 | xfs_da_state_t *state) /* state to fill in */ |
400 | { | 399 | { |
401 | xfs_dabuf_t *curbp; /* current data/free buffer */ | 400 | xfs_dabuf_t *curbp = NULL; /* current data/free buffer */ |
402 | xfs_dir2_db_t curdb; /* current data block number */ | 401 | xfs_dir2_db_t curdb = -1; /* current data block number */ |
403 | xfs_dir2_db_t curfdb; /* current free block number */ | 402 | xfs_dir2_db_t curfdb = -1; /* current free block number */ |
404 | xfs_dir2_data_entry_t *dep; /* data block entry */ | ||
405 | xfs_inode_t *dp; /* incore directory inode */ | 403 | xfs_inode_t *dp; /* incore directory inode */ |
406 | int error; /* error return value */ | 404 | int error; /* error return value */ |
407 | int fi; /* free entry index */ | 405 | int fi; /* free entry index */ |
408 | xfs_dir2_free_t *free=NULL; /* free block structure */ | 406 | xfs_dir2_free_t *free = NULL; /* free block structure */ |
409 | int index; /* leaf entry index */ | 407 | int index; /* leaf entry index */ |
410 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 408 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
411 | int length=0; /* length of new data entry */ | 409 | int length; /* length of new data entry */ |
412 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ | 410 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ |
413 | xfs_mount_t *mp; /* filesystem mount point */ | 411 | xfs_mount_t *mp; /* filesystem mount point */ |
414 | xfs_dir2_db_t newdb; /* new data block number */ | 412 | xfs_dir2_db_t newdb; /* new data block number */ |
@@ -431,33 +429,20 @@ xfs_dir2_leafn_lookup_int( | |||
431 | /* | 429 | /* |
432 | * Do we have a buffer coming in? | 430 | * Do we have a buffer coming in? |
433 | */ | 431 | */ |
434 | if (state->extravalid) | 432 | if (state->extravalid) { |
433 | /* If so, it's a free block buffer, get the block number. */ | ||
435 | curbp = state->extrablk.bp; | 434 | curbp = state->extrablk.bp; |
436 | else | 435 | curfdb = state->extrablk.blkno; |
437 | curbp = NULL; | 436 | free = curbp->data; |
438 | /* | 437 | ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); |
439 | * For addname, it's a free block buffer, get the block number. | ||
440 | */ | ||
441 | if (args->addname) { | ||
442 | curfdb = curbp ? state->extrablk.blkno : -1; | ||
443 | curdb = -1; | ||
444 | length = xfs_dir2_data_entsize(args->namelen); | ||
445 | if ((free = (curbp ? curbp->data : NULL))) | ||
446 | ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); | ||
447 | } | ||
448 | /* | ||
449 | * For others, it's a data block buffer, get the block number. | ||
450 | */ | ||
451 | else { | ||
452 | curfdb = -1; | ||
453 | curdb = curbp ? state->extrablk.blkno : -1; | ||
454 | } | 438 | } |
439 | length = xfs_dir2_data_entsize(args->namelen); | ||
455 | /* | 440 | /* |
456 | * Loop over leaf entries with the right hash value. | 441 | * Loop over leaf entries with the right hash value. |
457 | */ | 442 | */ |
458 | for (lep = &leaf->ents[index]; | 443 | for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && |
459 | index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; | 444 | be32_to_cpu(lep->hashval) == args->hashval; |
460 | lep++, index++) { | 445 | lep++, index++) { |
461 | /* | 446 | /* |
462 | * Skip stale leaf entries. | 447 | * Skip stale leaf entries. |
463 | */ | 448 | */ |
@@ -471,161 +456,244 @@ xfs_dir2_leafn_lookup_int( | |||
471 | * For addname, we're looking for a place to put the new entry. | 456 | * For addname, we're looking for a place to put the new entry. |
472 | * We want to use a data block with an entry of equal | 457 | * We want to use a data block with an entry of equal |
473 | * hash value to ours if there is one with room. | 458 | * hash value to ours if there is one with room. |
459 | * | ||
460 | * If this block isn't the data block we already have | ||
461 | * in hand, take a look at it. | ||
474 | */ | 462 | */ |
475 | if (args->addname) { | 463 | if (newdb != curdb) { |
464 | curdb = newdb; | ||
476 | /* | 465 | /* |
477 | * If this block isn't the data block we already have | 466 | * Convert the data block to the free block |
478 | * in hand, take a look at it. | 467 | * holding its freespace information. |
479 | */ | 468 | */ |
480 | if (newdb != curdb) { | 469 | newfdb = xfs_dir2_db_to_fdb(mp, newdb); |
481 | curdb = newdb; | ||
482 | /* | ||
483 | * Convert the data block to the free block | ||
484 | * holding its freespace information. | ||
485 | */ | ||
486 | newfdb = xfs_dir2_db_to_fdb(mp, newdb); | ||
487 | /* | ||
488 | * If it's not the one we have in hand, | ||
489 | * read it in. | ||
490 | */ | ||
491 | if (newfdb != curfdb) { | ||
492 | /* | ||
493 | * If we had one before, drop it. | ||
494 | */ | ||
495 | if (curbp) | ||
496 | xfs_da_brelse(tp, curbp); | ||
497 | /* | ||
498 | * Read the free block. | ||
499 | */ | ||
500 | if ((error = xfs_da_read_buf(tp, dp, | ||
501 | xfs_dir2_db_to_da(mp, | ||
502 | newfdb), | ||
503 | -1, &curbp, | ||
504 | XFS_DATA_FORK))) { | ||
505 | return error; | ||
506 | } | ||
507 | free = curbp->data; | ||
508 | ASSERT(be32_to_cpu(free->hdr.magic) == | ||
509 | XFS_DIR2_FREE_MAGIC); | ||
510 | ASSERT((be32_to_cpu(free->hdr.firstdb) % | ||
511 | XFS_DIR2_MAX_FREE_BESTS(mp)) == | ||
512 | 0); | ||
513 | ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb); | ||
514 | ASSERT(curdb < | ||
515 | be32_to_cpu(free->hdr.firstdb) + | ||
516 | be32_to_cpu(free->hdr.nvalid)); | ||
517 | } | ||
518 | /* | ||
519 | * Get the index for our entry. | ||
520 | */ | ||
521 | fi = xfs_dir2_db_to_fdindex(mp, curdb); | ||
522 | /* | ||
523 | * If it has room, return it. | ||
524 | */ | ||
525 | if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) { | ||
526 | XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", | ||
527 | XFS_ERRLEVEL_LOW, mp); | ||
528 | if (curfdb != newfdb) | ||
529 | xfs_da_brelse(tp, curbp); | ||
530 | return XFS_ERROR(EFSCORRUPTED); | ||
531 | } | ||
532 | curfdb = newfdb; | ||
533 | if (be16_to_cpu(free->bests[fi]) >= length) { | ||
534 | *indexp = index; | ||
535 | state->extravalid = 1; | ||
536 | state->extrablk.bp = curbp; | ||
537 | state->extrablk.blkno = curfdb; | ||
538 | state->extrablk.index = fi; | ||
539 | state->extrablk.magic = | ||
540 | XFS_DIR2_FREE_MAGIC; | ||
541 | ASSERT(args->oknoent); | ||
542 | return XFS_ERROR(ENOENT); | ||
543 | } | ||
544 | } | ||
545 | } | ||
546 | /* | ||
547 | * Not adding a new entry, so we really want to find | ||
548 | * the name given to us. | ||
549 | */ | ||
550 | else { | ||
551 | /* | 470 | /* |
552 | * If it's a different data block, go get it. | 471 | * If it's not the one we have in hand, read it in. |
553 | */ | 472 | */ |
554 | if (newdb != curdb) { | 473 | if (newfdb != curfdb) { |
555 | /* | 474 | /* |
556 | * If we had a block before, drop it. | 475 | * If we had one before, drop it. |
557 | */ | 476 | */ |
558 | if (curbp) | 477 | if (curbp) |
559 | xfs_da_brelse(tp, curbp); | 478 | xfs_da_brelse(tp, curbp); |
560 | /* | 479 | /* |
561 | * Read the data block. | 480 | * Read the free block. |
562 | */ | 481 | */ |
563 | if ((error = | 482 | error = xfs_da_read_buf(tp, dp, |
564 | xfs_da_read_buf(tp, dp, | 483 | xfs_dir2_db_to_da(mp, newfdb), |
565 | xfs_dir2_db_to_da(mp, newdb), -1, | 484 | -1, &curbp, XFS_DATA_FORK); |
566 | &curbp, XFS_DATA_FORK))) { | 485 | if (error) |
567 | return error; | 486 | return error; |
568 | } | 487 | free = curbp->data; |
569 | xfs_dir2_data_check(dp, curbp); | 488 | ASSERT(be32_to_cpu(free->hdr.magic) == |
570 | curdb = newdb; | 489 | XFS_DIR2_FREE_MAGIC); |
490 | ASSERT((be32_to_cpu(free->hdr.firstdb) % | ||
491 | XFS_DIR2_MAX_FREE_BESTS(mp)) == 0); | ||
492 | ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb); | ||
493 | ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) + | ||
494 | be32_to_cpu(free->hdr.nvalid)); | ||
571 | } | 495 | } |
572 | /* | 496 | /* |
573 | * Point to the data entry. | 497 | * Get the index for our entry. |
574 | */ | 498 | */ |
575 | dep = (xfs_dir2_data_entry_t *) | 499 | fi = xfs_dir2_db_to_fdindex(mp, curdb); |
576 | ((char *)curbp->data + | ||
577 | xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); | ||
578 | /* | 500 | /* |
579 | * Compare the entry, return it if it matches. | 501 | * If it has room, return it. |
580 | */ | 502 | */ |
581 | if (dep->namelen == args->namelen && | 503 | if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) { |
582 | dep->name[0] == args->name[0] && | 504 | XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", |
583 | memcmp(dep->name, args->name, args->namelen) == 0) { | 505 | XFS_ERRLEVEL_LOW, mp); |
584 | args->inumber = be64_to_cpu(dep->inumber); | 506 | if (curfdb != newfdb) |
585 | *indexp = index; | 507 | xfs_da_brelse(tp, curbp); |
586 | state->extravalid = 1; | 508 | return XFS_ERROR(EFSCORRUPTED); |
587 | state->extrablk.bp = curbp; | ||
588 | state->extrablk.blkno = curdb; | ||
589 | state->extrablk.index = | ||
590 | (int)((char *)dep - | ||
591 | (char *)curbp->data); | ||
592 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; | ||
593 | return XFS_ERROR(EEXIST); | ||
594 | } | 509 | } |
510 | curfdb = newfdb; | ||
511 | if (be16_to_cpu(free->bests[fi]) >= length) | ||
512 | goto out; | ||
595 | } | 513 | } |
596 | } | 514 | } |
515 | /* Didn't find any space */ | ||
516 | fi = -1; | ||
517 | out: | ||
518 | ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); | ||
519 | if (curbp) { | ||
520 | /* Giving back a free block. */ | ||
521 | state->extravalid = 1; | ||
522 | state->extrablk.bp = curbp; | ||
523 | state->extrablk.index = fi; | ||
524 | state->extrablk.blkno = curfdb; | ||
525 | state->extrablk.magic = XFS_DIR2_FREE_MAGIC; | ||
526 | } else { | ||
527 | state->extravalid = 0; | ||
528 | } | ||
597 | /* | 529 | /* |
598 | * Didn't find a match. | 530 | * Return the index, that will be the insertion point. |
599 | * If we are holding a buffer, give it back in case our caller | ||
600 | * finds it useful. | ||
601 | */ | 531 | */ |
602 | if ((state->extravalid = (curbp != NULL))) { | 532 | *indexp = index; |
603 | state->extrablk.bp = curbp; | 533 | return XFS_ERROR(ENOENT); |
604 | state->extrablk.index = -1; | 534 | } |
535 | |||
536 | /* | ||
537 | * Look up a leaf entry in a node-format leaf block. | ||
538 | * The extrablk in state a data block. | ||
539 | */ | ||
540 | STATIC int | ||
541 | xfs_dir2_leafn_lookup_for_entry( | ||
542 | xfs_dabuf_t *bp, /* leaf buffer */ | ||
543 | xfs_da_args_t *args, /* operation arguments */ | ||
544 | int *indexp, /* out: leaf entry index */ | ||
545 | xfs_da_state_t *state) /* state to fill in */ | ||
546 | { | ||
547 | xfs_dabuf_t *curbp = NULL; /* current data/free buffer */ | ||
548 | xfs_dir2_db_t curdb = -1; /* current data block number */ | ||
549 | xfs_dir2_data_entry_t *dep; /* data block entry */ | ||
550 | xfs_inode_t *dp; /* incore directory inode */ | ||
551 | int error; /* error return value */ | ||
552 | int index; /* leaf entry index */ | ||
553 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | ||
554 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ | ||
555 | xfs_mount_t *mp; /* filesystem mount point */ | ||
556 | xfs_dir2_db_t newdb; /* new data block number */ | ||
557 | xfs_trans_t *tp; /* transaction pointer */ | ||
558 | enum xfs_dacmp cmp; /* comparison result */ | ||
559 | |||
560 | dp = args->dp; | ||
561 | tp = args->trans; | ||
562 | mp = dp->i_mount; | ||
563 | leaf = bp->data; | ||
564 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); | ||
565 | #ifdef __KERNEL__ | ||
566 | ASSERT(be16_to_cpu(leaf->hdr.count) > 0); | ||
567 | #endif | ||
568 | xfs_dir2_leafn_check(dp, bp); | ||
569 | /* | ||
570 | * Look up the hash value in the leaf entries. | ||
571 | */ | ||
572 | index = xfs_dir2_leaf_search_hash(args, bp); | ||
573 | /* | ||
574 | * Do we have a buffer coming in? | ||
575 | */ | ||
576 | if (state->extravalid) { | ||
577 | curbp = state->extrablk.bp; | ||
578 | curdb = state->extrablk.blkno; | ||
579 | } | ||
580 | /* | ||
581 | * Loop over leaf entries with the right hash value. | ||
582 | */ | ||
583 | for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && | ||
584 | be32_to_cpu(lep->hashval) == args->hashval; | ||
585 | lep++, index++) { | ||
605 | /* | 586 | /* |
606 | * For addname, giving back a free block. | 587 | * Skip stale leaf entries. |
607 | */ | 588 | */ |
608 | if (args->addname) { | 589 | if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) |
609 | state->extrablk.blkno = curfdb; | 590 | continue; |
610 | state->extrablk.magic = XFS_DIR2_FREE_MAGIC; | 591 | /* |
592 | * Pull the data block number from the entry. | ||
593 | */ | ||
594 | newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); | ||
595 | /* | ||
596 | * Not adding a new entry, so we really want to find | ||
597 | * the name given to us. | ||
598 | * | ||
599 | * If it's a different data block, go get it. | ||
600 | */ | ||
601 | if (newdb != curdb) { | ||
602 | /* | ||
603 | * If we had a block before that we aren't saving | ||
604 | * for a CI name, drop it | ||
605 | */ | ||
606 | if (curbp && (args->cmpresult == XFS_CMP_DIFFERENT || | ||
607 | curdb != state->extrablk.blkno)) | ||
608 | xfs_da_brelse(tp, curbp); | ||
609 | /* | ||
610 | * If needing the block that is saved with a CI match, | ||
611 | * use it otherwise read in the new data block. | ||
612 | */ | ||
613 | if (args->cmpresult != XFS_CMP_DIFFERENT && | ||
614 | newdb == state->extrablk.blkno) { | ||
615 | ASSERT(state->extravalid); | ||
616 | curbp = state->extrablk.bp; | ||
617 | } else { | ||
618 | error = xfs_da_read_buf(tp, dp, | ||
619 | xfs_dir2_db_to_da(mp, newdb), | ||
620 | -1, &curbp, XFS_DATA_FORK); | ||
621 | if (error) | ||
622 | return error; | ||
623 | } | ||
624 | xfs_dir2_data_check(dp, curbp); | ||
625 | curdb = newdb; | ||
611 | } | 626 | } |
612 | /* | 627 | /* |
613 | * For other callers, giving back a data block. | 628 | * Point to the data entry. |
614 | */ | 629 | */ |
615 | else { | 630 | dep = (xfs_dir2_data_entry_t *)((char *)curbp->data + |
631 | xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); | ||
632 | /* | ||
633 | * Compare the entry and if it's an exact match, return | ||
634 | * EEXIST immediately. If it's the first case-insensitive | ||
635 | * match, store the block & inode number and continue looking. | ||
636 | */ | ||
637 | cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); | ||
638 | if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { | ||
639 | /* If there is a CI match block, drop it */ | ||
640 | if (args->cmpresult != XFS_CMP_DIFFERENT && | ||
641 | curdb != state->extrablk.blkno) | ||
642 | xfs_da_brelse(tp, state->extrablk.bp); | ||
643 | args->cmpresult = cmp; | ||
644 | args->inumber = be64_to_cpu(dep->inumber); | ||
645 | *indexp = index; | ||
646 | state->extravalid = 1; | ||
647 | state->extrablk.bp = curbp; | ||
616 | state->extrablk.blkno = curdb; | 648 | state->extrablk.blkno = curdb; |
649 | state->extrablk.index = (int)((char *)dep - | ||
650 | (char *)curbp->data); | ||
617 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; | 651 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; |
652 | if (cmp == XFS_CMP_EXACT) | ||
653 | return XFS_ERROR(EEXIST); | ||
618 | } | 654 | } |
619 | } | 655 | } |
620 | /* | 656 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || |
621 | * Return the final index, that will be the insertion point. | 657 | (args->op_flags & XFS_DA_OP_OKNOENT)); |
622 | */ | 658 | if (curbp) { |
659 | if (args->cmpresult == XFS_CMP_DIFFERENT) { | ||
660 | /* Giving back last used data block. */ | ||
661 | state->extravalid = 1; | ||
662 | state->extrablk.bp = curbp; | ||
663 | state->extrablk.index = -1; | ||
664 | state->extrablk.blkno = curdb; | ||
665 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; | ||
666 | } else { | ||
667 | /* If the curbp is not the CI match block, drop it */ | ||
668 | if (state->extrablk.bp != curbp) | ||
669 | xfs_da_brelse(tp, curbp); | ||
670 | } | ||
671 | } else { | ||
672 | state->extravalid = 0; | ||
673 | } | ||
623 | *indexp = index; | 674 | *indexp = index; |
624 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent); | ||
625 | return XFS_ERROR(ENOENT); | 675 | return XFS_ERROR(ENOENT); |
626 | } | 676 | } |
627 | 677 | ||
628 | /* | 678 | /* |
679 | * Look up a leaf entry in a node-format leaf block. | ||
680 | * If this is an addname then the extrablk in state is a freespace block, | ||
681 | * otherwise it's a data block. | ||
682 | */ | ||
683 | int | ||
684 | xfs_dir2_leafn_lookup_int( | ||
685 | xfs_dabuf_t *bp, /* leaf buffer */ | ||
686 | xfs_da_args_t *args, /* operation arguments */ | ||
687 | int *indexp, /* out: leaf entry index */ | ||
688 | xfs_da_state_t *state) /* state to fill in */ | ||
689 | { | ||
690 | if (args->op_flags & XFS_DA_OP_ADDNAME) | ||
691 | return xfs_dir2_leafn_lookup_for_addname(bp, args, indexp, | ||
692 | state); | ||
693 | return xfs_dir2_leafn_lookup_for_entry(bp, args, indexp, state); | ||
694 | } | ||
695 | |||
696 | /* | ||
629 | * Move count leaf entries from source to destination leaf. | 697 | * Move count leaf entries from source to destination leaf. |
630 | * Log entries and headers. Stale entries are preserved. | 698 | * Log entries and headers. Stale entries are preserved. |
631 | */ | 699 | */ |
@@ -823,9 +891,10 @@ xfs_dir2_leafn_rebalance( | |||
823 | */ | 891 | */ |
824 | if (!state->inleaf) | 892 | if (!state->inleaf) |
825 | blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); | 893 | blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); |
826 | 894 | ||
827 | /* | 895 | /* |
828 | * Finally sanity check just to make sure we are not returning a negative index | 896 | * Finally sanity check just to make sure we are not returning a |
897 | * negative index | ||
829 | */ | 898 | */ |
830 | if(blk2->index < 0) { | 899 | if(blk2->index < 0) { |
831 | state->inleaf = 1; | 900 | state->inleaf = 1; |
@@ -1332,7 +1401,7 @@ xfs_dir2_node_addname( | |||
1332 | /* | 1401 | /* |
1333 | * It worked, fix the hash values up the btree. | 1402 | * It worked, fix the hash values up the btree. |
1334 | */ | 1403 | */ |
1335 | if (!args->justcheck) | 1404 | if (!(args->op_flags & XFS_DA_OP_JUSTCHECK)) |
1336 | xfs_da_fixhashpath(state, &state->path); | 1405 | xfs_da_fixhashpath(state, &state->path); |
1337 | } else { | 1406 | } else { |
1338 | /* | 1407 | /* |
@@ -1515,7 +1584,8 @@ xfs_dir2_node_addname_int( | |||
1515 | /* | 1584 | /* |
1516 | * Not allowed to allocate, return failure. | 1585 | * Not allowed to allocate, return failure. |
1517 | */ | 1586 | */ |
1518 | if (args->justcheck || args->total == 0) { | 1587 | if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || |
1588 | args->total == 0) { | ||
1519 | /* | 1589 | /* |
1520 | * Drop the freespace buffer unless it came from our | 1590 | * Drop the freespace buffer unless it came from our |
1521 | * caller. | 1591 | * caller. |
@@ -1661,7 +1731,7 @@ xfs_dir2_node_addname_int( | |||
1661 | /* | 1731 | /* |
1662 | * If just checking, we succeeded. | 1732 | * If just checking, we succeeded. |
1663 | */ | 1733 | */ |
1664 | if (args->justcheck) { | 1734 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) { |
1665 | if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) | 1735 | if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) |
1666 | xfs_da_buf_done(fbp); | 1736 | xfs_da_buf_done(fbp); |
1667 | return 0; | 1737 | return 0; |
@@ -1767,6 +1837,14 @@ xfs_dir2_node_lookup( | |||
1767 | error = xfs_da_node_lookup_int(state, &rval); | 1837 | error = xfs_da_node_lookup_int(state, &rval); |
1768 | if (error) | 1838 | if (error) |
1769 | rval = error; | 1839 | rval = error; |
1840 | else if (rval == ENOENT && args->cmpresult == XFS_CMP_CASE) { | ||
1841 | /* If a CI match, dup the actual name and return EEXIST */ | ||
1842 | xfs_dir2_data_entry_t *dep; | ||
1843 | |||
1844 | dep = (xfs_dir2_data_entry_t *)((char *)state->extrablk.bp-> | ||
1845 | data + state->extrablk.index); | ||
1846 | rval = xfs_dir_cilookup_result(args, dep->name, dep->namelen); | ||
1847 | } | ||
1770 | /* | 1848 | /* |
1771 | * Release the btree blocks and leaf block. | 1849 | * Release the btree blocks and leaf block. |
1772 | */ | 1850 | */ |
@@ -1810,9 +1888,8 @@ xfs_dir2_node_removename( | |||
1810 | * Look up the entry we're deleting, set up the cursor. | 1888 | * Look up the entry we're deleting, set up the cursor. |
1811 | */ | 1889 | */ |
1812 | error = xfs_da_node_lookup_int(state, &rval); | 1890 | error = xfs_da_node_lookup_int(state, &rval); |
1813 | if (error) { | 1891 | if (error) |
1814 | rval = error; | 1892 | rval = error; |
1815 | } | ||
1816 | /* | 1893 | /* |
1817 | * Didn't find it, upper layer screwed up. | 1894 | * Didn't find it, upper layer screwed up. |
1818 | */ | 1895 | */ |
@@ -1829,9 +1906,8 @@ xfs_dir2_node_removename( | |||
1829 | */ | 1906 | */ |
1830 | error = xfs_dir2_leafn_remove(args, blk->bp, blk->index, | 1907 | error = xfs_dir2_leafn_remove(args, blk->bp, blk->index, |
1831 | &state->extrablk, &rval); | 1908 | &state->extrablk, &rval); |
1832 | if (error) { | 1909 | if (error) |
1833 | return error; | 1910 | return error; |
1834 | } | ||
1835 | /* | 1911 | /* |
1836 | * Fix the hash values up the btree. | 1912 | * Fix the hash values up the btree. |
1837 | */ | 1913 | */ |