* This routine "consumes" the caller's hold on the dbuf, which must * have the specified tag. */
| 505 | * have the specified tag. |
| 506 | */ |
| 507 | static int |
| 508 | zap_lockdir_impl(dmu_buf_t *db, void *tag, dmu_tx_t *tx, |
| 509 | krw_t lti, boolean_t fatreader, boolean_t adding, zap_t **zapp) |
| 510 | { |
| 511 | ASSERT0(db->db_offset); |
| 512 | objset_t *os = dmu_buf_get_objset(db); |
| 513 | uint64_t obj = db->db_object; |
| 514 | dmu_object_info_t doi; |
| 515 | |
| 516 | *zapp = NULL; |
| 517 | |
| 518 | dmu_object_info_from_db(db, &doi); |
| 519 | if (DMU_OT_BYTESWAP(doi.doi_type) != DMU_BSWAP_ZAP) |
| 520 | return (SET_ERROR(EINVAL)); |
| 521 | |
| 522 | zap_t *zap = dmu_buf_get_user(db); |
| 523 | if (zap == NULL) { |
| 524 | zap = mzap_open(os, obj, db); |
| 525 | if (zap == NULL) { |
| 526 | /* |
| 527 | * mzap_open() didn't like what it saw on-disk. |
| 528 | * Check for corruption! |
| 529 | */ |
| 530 | return (SET_ERROR(EIO)); |
| 531 | } |
| 532 | } |
| 533 | |
| 534 | /* |
| 535 | * We're checking zap_ismicro without the lock held, in order to |
| 536 | * tell what type of lock we want. Once we have some sort of |
| 537 | * lock, see if it really is the right type. In practice this |
| 538 | * can only be different if it was upgraded from micro to fat, |
| 539 | * and micro wanted WRITER but fat only needs READER. |
| 540 | */ |
| 541 | krw_t lt = (!zap->zap_ismicro && fatreader) ? RW_READER : lti; |
| 542 | rw_enter(&zap->zap_rwlock, lt); |
| 543 | if (lt != ((!zap->zap_ismicro && fatreader) ? RW_READER : lti)) { |
| 544 | /* it was upgraded, now we only need reader */ |
| 545 | ASSERT(lt == RW_WRITER); |
| 546 | ASSERT(RW_READER == |
| 547 | ((!zap->zap_ismicro && fatreader) ? RW_READER : lti)); |
| 548 | rw_downgrade(&zap->zap_rwlock); |
| 549 | lt = RW_READER; |
| 550 | } |
| 551 | |
| 552 | zap->zap_objset = os; |
| 553 | |
| 554 | if (lt == RW_WRITER) |
| 555 | dmu_buf_will_dirty(db, tx); |
| 556 | |
| 557 | ASSERT3P(zap->zap_dbuf, ==, db); |
| 558 | |
| 559 | ASSERT(!zap->zap_ismicro || |
| 560 | zap->zap_m.zap_num_entries <= zap->zap_m.zap_num_chunks); |
| 561 | if (zap->zap_ismicro && tx && adding && |
| 562 | zap->zap_m.zap_num_entries == zap->zap_m.zap_num_chunks) { |
| 563 | uint64_t newsz = db->db_size + SPA_MINBLOCKSIZE; |
| 564 | if (newsz > MZAP_MAX_BLKSZ) { |
no test coverage detected