From 57df39fcce550d0cc38ef07c4c2643059707752a 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" Signed-off-by: Fabian Grünbichler --- 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); }