From owner-svn-src-all@FreeBSD.ORG Sat Apr 30 14:52:49 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EFAE11065670; Sat, 30 Apr 2011 14:52:49 +0000 (UTC) (envelope-from mm@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D28DC8FC15; Sat, 30 Apr 2011 14:52:49 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p3UEqnjE050163; Sat, 30 Apr 2011 14:52:49 GMT (envelope-from mm@svn.freebsd.org) Received: (from mm@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p3UEqneY050160; Sat, 30 Apr 2011 14:52:49 GMT (envelope-from mm@svn.freebsd.org) Message-Id: <201104301452.p3UEqneY050160@svn.freebsd.org> From: Martin Matuska Date: Sat, 30 Apr 2011 14:52:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r221263 - in head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs: . sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 30 Apr 2011 14:52:50 -0000 Author: mm Date: Sat Apr 30 14:52:49 2011 New Revision: 221263 URL: http://svn.freebsd.org/changeset/base/221263 Log: Fix deduplicated zfs receive (dmu_recv_stream builds incomplete guid_to_ds_map) Illumos-gate changeset: 13329:c48b8bf84ab7 MFC together with v28 Approved by: pjd Obtained from: Illumos (Bug #755) Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h 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 Sat Apr 30 14:22:45 2011 (r221262) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c Sat Apr 30 14:52:49 2011 (r221263) @@ -21,6 +21,9 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ +/* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + */ #include #include @@ -851,61 +854,6 @@ guid_compare(const void *arg1, const voi return (0); } -/* - * This function is a callback used by dmu_objset_find() (which - * enumerates the object sets) to build an avl tree that maps guids - * to datasets. The resulting table is used when processing DRR_WRITE_BYREF - * send stream records. These records, which are used in dedup'ed - * streams, do not contain data themselves, but refer to a copy - * of the data block that has already been written because it was - * earlier in the stream. That previous copy is identified by the - * guid of the dataset with the referenced data. - */ -int -find_ds_by_guid(const char *name, void *arg) -{ - avl_tree_t *guid_map = arg; - dsl_dataset_t *ds, *snapds; - guid_map_entry_t *gmep; - dsl_pool_t *dp; - int err; - uint64_t lastobj, firstobj; - - if (dsl_dataset_hold(name, FTAG, &ds) != 0) - return (0); - - dp = ds->ds_dir->dd_pool; - rw_enter(&dp->dp_config_rwlock, RW_READER); - firstobj = ds->ds_dir->dd_phys->dd_origin_obj; - lastobj = ds->ds_phys->ds_prev_snap_obj; - - while (lastobj != firstobj) { - err = dsl_dataset_hold_obj(dp, lastobj, guid_map, &snapds); - if (err) { - /* - * Skip this snapshot and move on. It's not - * clear why this would ever happen, but the - * remainder of the snapshot streadm can be - * processed. - */ - rw_exit(&dp->dp_config_rwlock); - dsl_dataset_rele(ds, FTAG); - return (0); - } - - gmep = kmem_alloc(sizeof (guid_map_entry_t), KM_SLEEP); - gmep->guid = snapds->ds_phys->ds_guid; - gmep->gme_ds = snapds; - avl_add(guid_map, gmep); - lastobj = snapds->ds_phys->ds_prev_snap_obj; - } - - rw_exit(&dp->dp_config_rwlock); - dsl_dataset_rele(ds, FTAG); - - return (0); -} - static void free_guid_map_onexit(void *arg) { @@ -1413,9 +1361,6 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, avl_create(ra.guid_to_ds_map, guid_compare, sizeof (guid_map_entry_t), offsetof(guid_map_entry_t, avlnode)); - (void) dmu_objset_find(drc->drc_top_ds, find_ds_by_guid, - (void *)ra.guid_to_ds_map, - DS_FIND_CHILDREN); ra.err = zfs_onexit_add_cb(minor, free_guid_map_onexit, ra.guid_to_ds_map, action_handlep); @@ -1427,6 +1372,8 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, if (ra.err) goto out; } + + drc->drc_guid_to_ds_map = ra.guid_to_ds_map; } /* @@ -1565,6 +1512,30 @@ recv_end_sync(void *arg1, void *arg2, dm } static int +add_ds_to_guidmap(avl_tree_t *guid_map, dsl_dataset_t *ds) +{ + dsl_pool_t *dp = ds->ds_dir->dd_pool; + uint64_t snapobj = ds->ds_phys->ds_prev_snap_obj; + dsl_dataset_t *snapds; + guid_map_entry_t *gmep; + int err; + + ASSERT(guid_map != NULL); + + rw_enter(&dp->dp_config_rwlock, RW_READER); + err = dsl_dataset_hold_obj(dp, snapobj, guid_map, &snapds); + if (err == 0) { + gmep = kmem_alloc(sizeof (guid_map_entry_t), KM_SLEEP); + gmep->guid = snapds->ds_phys->ds_guid; + gmep->gme_ds = snapds; + avl_add(guid_map, gmep); + } + + rw_exit(&dp->dp_config_rwlock); + return (err); +} + +static int dmu_recv_existing_end(dmu_recv_cookie_t *drc) { struct recvendsyncarg resa; @@ -1604,6 +1575,8 @@ dmu_recv_existing_end(dmu_recv_cookie_t out: mutex_exit(&ds->ds_recvlock); + if (err == 0 && drc->drc_guid_to_ds_map != NULL) + (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds); dsl_dataset_disown(ds, dmu_recv_tag); (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE); return (err); @@ -1633,6 +1606,8 @@ dmu_recv_new_end(dmu_recv_cookie_t *drc) /* clean up the fs we just recv'd into */ (void) dsl_dataset_destroy(ds, dmu_recv_tag, B_FALSE); } else { + if (drc->drc_guid_to_ds_map != NULL) + (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds); /* release the hold from dmu_recv_begin */ dsl_dataset_disown(ds, dmu_recv_tag); } Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h ============================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h Sat Apr 30 14:22:45 2011 (r221262) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h Sat Apr 30 14:52:49 2011 (r221263) @@ -21,6 +21,9 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ +/* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + */ /* Portions Copyright 2010 Robert Milkowski */ @@ -718,6 +721,7 @@ typedef struct dmu_recv_cookie { char *drc_top_ds; boolean_t drc_newfs; boolean_t drc_force; + struct avl_tree *drc_guid_to_ds_map; } dmu_recv_cookie_t; int dmu_recv_begin(char *tofs, char *tosnap, char *topds, struct drr_begin *,