Some additional send stream validity checking

Check in the DMU whether an object record in a send stream being
received contains an unsupported dnode slot count, and return an
error if it does. Failure to catch an unsupported dnode slot count
would result in a panic when the SPA attempts to increment the
reference count for the large_dnode feature and the pool has the
feature disabled. This is not normally an issue for a well-formed
send stream which would have the DMU_BACKUP_FEATURE_LARGE_DNODE flag
set if it contains large dnodes, so it will be rejected as
unsupported if the required feature is disabled. This change adds a
missing object record field validation.

Add missing stream feature flag checks in
dmu_recv_resume_begin_check().

Consolidate repetitive comment blocks in dmu_recv_begin_check().

Update zstreamdump to print the dnode slot count (dn_slots) for an
object record when running in verbose mode.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Giuseppe Di Natale <dinatale2@llnl.gov>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Signed-off-by: Ned Bass <bass6@llnl.gov>
Closes #6396
This commit is contained in:
Ned Bass 2017-07-25 18:52:40 -07:00 committed by Brian Behlendorf
parent 3f759c0c73
commit 73aac4aa41
2 changed files with 22 additions and 10 deletions

View File

@ -422,12 +422,14 @@ main(int argc, char *argv[])
} }
if (verbose) { if (verbose) {
(void) printf("OBJECT object = %llu type = %u " (void) printf("OBJECT object = %llu type = %u "
"bonustype = %u blksz = %u bonuslen = %u\n", "bonustype = %u blksz = %u bonuslen = %u "
"dn_slots = %u\n",
(u_longlong_t)drro->drr_object, (u_longlong_t)drro->drr_object,
drro->drr_type, drro->drr_type,
drro->drr_bonustype, drro->drr_bonustype,
drro->drr_blksz, drro->drr_blksz,
drro->drr_bonuslen); drro->drr_bonuslen,
drro->drr_dn_slots);
} }
if (drro->drr_bonuslen > 0) { if (drro->drr_bonuslen > 0) {
(void) ssread(buf, (void) ssread(buf,

View File

@ -1428,17 +1428,12 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
/* /*
* The receiving code doesn't know how to translate large blocks * The receiving code doesn't know how to translate large blocks
* to smaller ones, so the pool must have the LARGE_BLOCKS * to smaller ones, so the pool must have the LARGE_BLOCKS
* feature enabled if the stream has LARGE_BLOCKS. * feature enabled if the stream has LARGE_BLOCKS. Same with
* large dnodes.
*/ */
if ((featureflags & DMU_BACKUP_FEATURE_LARGE_BLOCKS) && if ((featureflags & DMU_BACKUP_FEATURE_LARGE_BLOCKS) &&
!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS)) !spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS))
return (SET_ERROR(ENOTSUP)); return (SET_ERROR(ENOTSUP));
/*
* The receiving code doesn't know how to translate large dnodes
* to smaller ones, so the pool must have the LARGE_DNODE
* feature enabled if the stream has LARGE_DNODE.
*/
if ((featureflags & DMU_BACKUP_FEATURE_LARGE_DNODE) && if ((featureflags & DMU_BACKUP_FEATURE_LARGE_DNODE) &&
!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LARGE_DNODE)) !spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LARGE_DNODE))
return (SET_ERROR(ENOTSUP)); return (SET_ERROR(ENOTSUP));
@ -1678,6 +1673,19 @@ dmu_recv_resume_begin_check(void *arg, dmu_tx_t *tx)
!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LZ4_COMPRESS)) !spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LZ4_COMPRESS))
return (SET_ERROR(ENOTSUP)); return (SET_ERROR(ENOTSUP));
/*
* The receiving code doesn't know how to translate large blocks
* to smaller ones, so the pool must have the LARGE_BLOCKS
* feature enabled if the stream has LARGE_BLOCKS. Same with
* large dnodes.
*/
if ((featureflags & DMU_BACKUP_FEATURE_LARGE_BLOCKS) &&
!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS))
return (SET_ERROR(ENOTSUP));
if ((featureflags & DMU_BACKUP_FEATURE_LARGE_DNODE) &&
!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LARGE_DNODE))
return (SET_ERROR(ENOTSUP));
(void) snprintf(recvname, sizeof (recvname), "%s/%s", (void) snprintf(recvname, sizeof (recvname), "%s/%s",
tofs, recv_clone_name); tofs, recv_clone_name);
@ -2121,7 +2129,9 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
drro->drr_blksz < SPA_MINBLOCKSIZE || drro->drr_blksz < SPA_MINBLOCKSIZE ||
drro->drr_blksz > spa_maxblocksize(dmu_objset_spa(rwa->os)) || drro->drr_blksz > spa_maxblocksize(dmu_objset_spa(rwa->os)) ||
drro->drr_bonuslen > drro->drr_bonuslen >
DN_BONUS_SIZE(spa_maxdnodesize(dmu_objset_spa(rwa->os)))) { DN_BONUS_SIZE(spa_maxdnodesize(dmu_objset_spa(rwa->os))) ||
drro->drr_dn_slots >
(spa_maxdnodesize(dmu_objset_spa(rwa->os)) >> DNODE_SHIFT)) {
return (SET_ERROR(EINVAL)); return (SET_ERROR(EINVAL));
} }