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 | */ |
