Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Aug 2019 15:11:21 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r351076 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201908151511.x7FFBLZ4046737@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Thu Aug 15 15:11:20 2019
New Revision: 351076
URL: https://svnweb.freebsd.org/changeset/base/351076

Log:
  MFV r351075: 10406 large_dnode changes broke zfs recv of legacy stream
  
  illumos/illumos-gate@811964cd9f1fbae0fc3b93d116269e9b1fca090a
  https://github.com/illumos/illumos-gate/commit/811964cd9f1fbae0fc3b93d116269e9b1fca090a
  
  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 da2feb42fb5c7a8c1e1cc67f7a880da9d8e97bc2
    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

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
Directory Properties:
  head/sys/cddl/contrib/opensolaris/   (props changed)

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c	Thu Aug 15 15:07:17 2019	(r351075)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c	Thu Aug 15 15:11:20 2019	(r351076)
@@ -275,6 +275,9 @@ dmu_object_reclaim_dnsize(objset_t *os, uint64_t objec
 	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));
 

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c	Thu Aug 15 15:07:17 2019	(r351075)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c	Thu Aug 15 15:11:20 2019	(r351076)
@@ -2153,6 +2153,8 @@ receive_object(struct receive_writer_arg *rwa, struct 
 	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 
 	    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 
 
 		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 
 	 * 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 
 		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 ||



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201908151511.x7FFBLZ4046737>