| 625 | } |
| 626 | |
| 627 | static int |
| 628 | zap_expand_leaf(zap_name_t *zn, zap_leaf_t *l, |
| 629 | void *tag, dmu_tx_t *tx, zap_leaf_t **lp) |
| 630 | { |
| 631 | zap_t *zap = zn->zn_zap; |
| 632 | uint64_t hash = zn->zn_hash; |
| 633 | int err; |
| 634 | int old_prefix_len = zap_leaf_phys(l)->l_hdr.lh_prefix_len; |
| 635 | |
| 636 | ASSERT3U(old_prefix_len, <=, zap_f_phys(zap)->zap_ptrtbl.zt_shift); |
| 637 | ASSERT(RW_LOCK_HELD(&zap->zap_rwlock)); |
| 638 | |
| 639 | ASSERT3U(ZAP_HASH_IDX(hash, old_prefix_len), ==, |
| 640 | zap_leaf_phys(l)->l_hdr.lh_prefix); |
| 641 | |
| 642 | if (zap_tryupgradedir(zap, tx) == 0 || |
| 643 | old_prefix_len == zap_f_phys(zap)->zap_ptrtbl.zt_shift) { |
| 644 | /* We failed to upgrade, or need to grow the pointer table */ |
| 645 | objset_t *os = zap->zap_objset; |
| 646 | uint64_t object = zap->zap_object; |
| 647 | |
| 648 | zap_put_leaf(l); |
| 649 | zap_unlockdir(zap, tag); |
| 650 | err = zap_lockdir(os, object, tx, RW_WRITER, |
| 651 | FALSE, FALSE, tag, &zn->zn_zap); |
| 652 | zap = zn->zn_zap; |
| 653 | if (err != 0) |
| 654 | return (err); |
| 655 | ASSERT(!zap->zap_ismicro); |
| 656 | |
| 657 | while (old_prefix_len == |
| 658 | zap_f_phys(zap)->zap_ptrtbl.zt_shift) { |
| 659 | err = zap_grow_ptrtbl(zap, tx); |
| 660 | if (err != 0) |
| 661 | return (err); |
| 662 | } |
| 663 | |
| 664 | err = zap_deref_leaf(zap, hash, tx, RW_WRITER, &l); |
| 665 | if (err != 0) |
| 666 | return (err); |
| 667 | |
| 668 | if (zap_leaf_phys(l)->l_hdr.lh_prefix_len != old_prefix_len) { |
| 669 | /* it split while our locks were down */ |
| 670 | *lp = l; |
| 671 | return (0); |
| 672 | } |
| 673 | } |
| 674 | ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); |
| 675 | ASSERT3U(old_prefix_len, <, zap_f_phys(zap)->zap_ptrtbl.zt_shift); |
| 676 | ASSERT3U(ZAP_HASH_IDX(hash, old_prefix_len), ==, |
| 677 | zap_leaf_phys(l)->l_hdr.lh_prefix); |
| 678 | |
| 679 | int prefix_diff = zap_f_phys(zap)->zap_ptrtbl.zt_shift - |
| 680 | (old_prefix_len + 1); |
| 681 | uint64_t sibling = |
| 682 | (ZAP_HASH_IDX(hash, old_prefix_len + 1) | 1) << prefix_diff; |
| 683 | |
| 684 | /* check for i/o errors before doing zap_leaf_split */ |
no test coverage detected