MFV r351075: 10406 large_dnode changes broke zfs recv of legacy stream

illumos/illumos-gate@811964cd9f
811964cd9f

https://www.illumos.org/issues/10406
  The large dnode changes from 8423 caused problems in zfs recv for a legacy
  stream. This manifests when attempting to mount the received stream, but the
  problem is in the receive code. We missed the following commit from ZoL which
  fixes this.
  commit da2feb42fb
  Author: Tom Caputi <tcaputi@datto.com>
  Date: Thu Jun 28 17:55:11 2018 -0400
  Fix 'zfs recv' of non large_dnode send streams
  Currently, there is a bug where older send streams without the
      DMU_BACKUP_FEATURE_LARGE_DNODE flag are not handled correctly.
      The code in receive_object() fails to handle cases where
      drro->drr_dn_slots is set to 0, which is always the case when the
      sending code does not support this feature flag. This patch fixes
      the issue by ensuring that that a value of 0 is treated as
      DNODE_MIN_SLOTS.

Author: Tom Caputi <tcaputi@datto.com>

MFC after:	3 weeks
X-MFC after:	r351074
This commit is contained in:
Andriy Gapon 2019-08-15 15:11:20 +00:00
commit 30f7381b8e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=351076
2 changed files with 10 additions and 5 deletions

View File

@ -275,6 +275,9 @@ dmu_object_reclaim_dnsize(objset_t *os, uint64_t object, dmu_object_type_t ot,
int dn_slots = dnodesize >> DNODE_SHIFT;
int err;
if (dn_slots == 0)
dn_slots = DNODE_MIN_SLOTS;
if (object == DMU_META_DNODE_OBJECT)
return (SET_ERROR(EBADF));

View File

@ -2153,6 +2153,8 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
dmu_tx_t *tx;
uint64_t object;
int err;
uint8_t dn_slots = drro->drr_dn_slots != 0 ?
drro->drr_dn_slots : DNODE_MIN_SLOTS;
if (drro->drr_type == DMU_OT_NONE ||
!DMU_OT_IS_VALID(drro->drr_type) ||
@ -2164,7 +2166,7 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
drro->drr_blksz > spa_maxblocksize(dmu_objset_spa(rwa->os)) ||
drro->drr_bonuslen >
DN_BONUS_SIZE(spa_maxdnodesize(dmu_objset_spa(rwa->os))) ||
drro->drr_dn_slots >
dn_slots >
(spa_maxdnodesize(dmu_objset_spa(rwa->os)) >> DNODE_SHIFT)) {
return (SET_ERROR(EINVAL));
}
@ -2192,7 +2194,7 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
if (drro->drr_blksz != doi.doi_data_block_size ||
nblkptr < doi.doi_nblkptr ||
drro->drr_dn_slots != doi.doi_dnodesize >> DNODE_SHIFT) {
dn_slots != doi.doi_dnodesize >> DNODE_SHIFT) {
err = dmu_free_long_range(rwa->os, drro->drr_object,
0, DMU_OBJECT_END);
if (err != 0)
@ -2219,11 +2221,11 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
* another object from the previous snapshot. We must free
* these objects before we attempt to allocate the new dnode.
*/
if (drro->drr_dn_slots > 1) {
if (dn_slots > 1) {
boolean_t need_sync = B_FALSE;
for (uint64_t slot = drro->drr_object + 1;
slot < drro->drr_object + drro->drr_dn_slots;
slot < drro->drr_object + dn_slots;
slot++) {
dmu_object_info_t slot_doi;
@ -2258,7 +2260,7 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
err = dmu_object_claim_dnsize(rwa->os, drro->drr_object,
drro->drr_type, drro->drr_blksz,
drro->drr_bonustype, drro->drr_bonuslen,
drro->drr_dn_slots << DNODE_SHIFT, tx);
dn_slots << DNODE_SHIFT, tx);
} else if (drro->drr_type != doi.doi_type ||
drro->drr_blksz != doi.doi_data_block_size ||
drro->drr_bonustype != doi.doi_bonus_type ||