From ab2e23b0f490112194f052da43db5b68dd062db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= Date: Mon, 4 Sep 2017 15:04:21 +0200 Subject: [PATCH] backport freeobjects receive handling from 0.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this combines changes from e6d3a843d6ced970cbc74a3f809d744c30a7ec7c OpenZFS 6393 - zfs receive a full send as a clone and 50c957f702ea6d08a634e42f73e8a49931dd8055 Implement large_dnode pool feature to hopefully allow sending regular streams from 0.7.x to 0.6.5.x based systems. the problematic records of the following kind now no longer lead to an infinite loop, but instead allow the receive to complete: drr_type = FREEOBJECTS firstobj = 64 numobjs = 36028797018963904 err = 0 see issues #5699 (older incompatibility between FreeNAS and <= 0.6.5.11) and #6507 (recent incompatibility between 0.7.x and <= 0.6.5.11) Signed-off-by: Fabian Grünbichler Requires-spl: spl-0\.6\.5-release --- module/zfs/dmu_send.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c index 940454977c69..e572d04e9224 100644 --- a/module/zfs/dmu_send.c +++ b/module/zfs/dmu_send.c @@ -1600,22 +1600,30 @@ restore_freeobjects(struct restorearg *ra, objset_t *os, struct drr_freeobjects *drrfo) { uint64_t obj; + int next_err = 0; if (drrfo->drr_firstobj + drrfo->drr_numobjs < drrfo->drr_firstobj) return (SET_ERROR(EINVAL)); - for (obj = drrfo->drr_firstobj; - obj < drrfo->drr_firstobj + drrfo->drr_numobjs; - (void) dmu_object_next(os, &obj, FALSE, 0)) { + for (obj = drrfo->drr_firstobj == 0 ? 1 : drrfo->drr_firstobj; + obj < drrfo->drr_firstobj + drrfo->drr_numobjs && next_err == 0; + next_err = dmu_object_next(os, &obj, FALSE, 0)) { int err; - if (dmu_object_info(os, obj, NULL) != 0) + err = dmu_object_info(os, obj, NULL); + if (err == ENOENT) { + obj++; continue; + } else if (err != 0) { + return (err); + } err = dmu_free_long_object(os, obj); if (err != 0) return (err); } + if (next_err != ESRCH) + return (next_err); return (0); }