Skip to content

Commit

Permalink
Merge pull request #147 from truenas/NAS-123123-3.3
Browse files Browse the repository at this point in the history
NAS-123123 / None / Fix raw receive with different indirect block size.
  • Loading branch information
amotin authored Jul 20, 2023
2 parents 079b475 + dd8c3b8 commit 3620e54
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 25 deletions.
22 changes: 12 additions & 10 deletions module/zfs/dmu_recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1524,17 +1524,19 @@ receive_handle_existing_object(const struct receive_writer_arg *rwa,
}

/*
* The dmu does not currently support decreasing nlevels
* or changing the number of dnode slots on an object. For
* non-raw sends, this does not matter and the new object
* can just use the previous one's nlevels. For raw sends,
* however, the structure of the received dnode (including
* nlevels and dnode slots) must match that of the send
* side. Therefore, instead of using dmu_object_reclaim(),
* we must free the object completely and call
* dmu_object_claim_dnsize() instead.
* The dmu does not currently support decreasing nlevels or changing
* indirect block size if there is already one, same as changing the
* number of of dnode slots on an object. For non-raw sends this
* does not matter and the new object can just use the previous one's
* parameters. For raw sends, however, the structure of the received
* dnode (including indirects and dnode slots) must match that of the
* send side. Therefore, instead of using dmu_object_reclaim(), we
* must free the object completely and call dmu_object_claim_dnsize()
* instead.
*/
if ((rwa->raw && drro->drr_nlevels < doi->doi_indirection) ||
if ((rwa->raw && ((doi->doi_indirection > 1 &&
indblksz != doi->doi_metadata_block_size) ||
drro->drr_nlevels < doi->doi_indirection)) ||
dn_slots != doi->doi_dnodesize >> DNODE_SHIFT) {
err = dmu_free_long_object(rwa->os, drro->drr_object);
if (err != 0)
Expand Down
31 changes: 16 additions & 15 deletions module/zfs/dnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1891,7 +1891,7 @@ dnode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx)
if (ibs == dn->dn_indblkshift)
ibs = 0;

if (size >> SPA_MINBLOCKSHIFT == dn->dn_datablkszsec && ibs == 0)
if (size == dn->dn_datablksz && ibs == 0)
return (0);

rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
Expand All @@ -1914,24 +1914,25 @@ dnode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx)
if (ibs && dn->dn_nlevels != 1)
goto fail;

/* resize the old block */
err = dbuf_hold_impl(dn, 0, 0, TRUE, FALSE, FTAG, &db);
if (err == 0) {
dbuf_new_size(db, size, tx);
} else if (err != ENOENT) {
goto fail;
}

dnode_setdblksz(dn, size);
dnode_setdirty(dn, tx);
dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = size;
if (size != dn->dn_datablksz) {
/* resize the old block */
err = dbuf_hold_impl(dn, 0, 0, TRUE, FALSE, FTAG, &db);
if (err == 0) {
dbuf_new_size(db, size, tx);
} else if (err != ENOENT) {
goto fail;
}

dnode_setdblksz(dn, size);
dn->dn_next_blksz[tx->tx_txg & TXG_MASK] = size;
if (db)
dbuf_rele(db, FTAG);
}
if (ibs) {
dn->dn_indblkshift = ibs;
dn->dn_next_indblkshift[tx->tx_txg&TXG_MASK] = ibs;
dn->dn_next_indblkshift[tx->tx_txg & TXG_MASK] = ibs;
}
/* release after we have fixed the blocksize in the dnode */
if (db)
dbuf_rele(db, FTAG);

rw_exit(&dn->dn_struct_rwlock);
return (0);
Expand Down

0 comments on commit 3620e54

Please sign in to comment.