From owner-svn-src-head@FreeBSD.ORG Thu Dec 13 22:03:08 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 41E267E6; Thu, 13 Dec 2012 22:03:08 +0000 (UTC) (envelope-from smh@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 272148FC0A; Thu, 13 Dec 2012 22:03:08 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qBDM382V022847; Thu, 13 Dec 2012 22:03:08 GMT (envelope-from smh@svn.freebsd.org) Received: (from smh@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qBDM38R3022846; Thu, 13 Dec 2012 22:03:08 GMT (envelope-from smh@svn.freebsd.org) Message-Id: <201212132203.qBDM38R3022846@svn.freebsd.org> From: Steven Hartland Date: Thu, 13 Dec 2012 22:03:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r244194 - head/cddl/contrib/opensolaris/lib/libzfs/common X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Dec 2012 22:03:08 -0000 Author: smh Date: Thu Dec 13 22:03:07 2012 New Revision: 244194 URL: http://svnweb.freebsd.org/changeset/base/244194 Log: Fixes zfs receive errors caused by snapshot replication being processed in a random order instead of creation order. Eliminates needless filesystem renames caused by removed parent snapshots which subsequently causes many more errors. PR: kern/172259 Submitted by: Steven Hartland Reviewed by: pjd (mentor) Approved by: pjd (mentor) MFC after: 2 weeks Modified: head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c Modified: head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c ============================================================================== --- head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c Thu Dec 13 21:40:11 2012 (r244193) +++ head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c Thu Dec 13 22:03:07 2012 (r244194) @@ -727,7 +727,7 @@ send_iterate_fs(zfs_handle_t *zhp, void sd->parent_fromsnap_guid = 0; VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0)); VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0)); - (void) zfs_iter_snapshots(zhp, B_FALSE, send_iterate_snap, sd); + (void) zfs_iter_snapshots_sorted(zhp, send_iterate_snap, sd); VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps)); VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops)); nvlist_free(sd->parent_snaps); @@ -1945,11 +1945,12 @@ recv_incremental_replication(libzfs_hand recvflags_t *flags, nvlist_t *stream_nv, avl_tree_t *stream_avl, nvlist_t *renamed) { - nvlist_t *local_nv; + nvlist_t *local_nv, *deleted = NULL; avl_tree_t *local_avl; nvpair_t *fselem, *nextfselem; char *fromsnap; char newname[ZFS_MAXNAMELEN]; + char guidname[32]; int error; boolean_t needagain, progress, recursive; char *s1, *s2; @@ -1965,6 +1966,8 @@ recv_incremental_replication(libzfs_hand again: needagain = progress = B_FALSE; + VERIFY(0 == nvlist_alloc(&deleted, NV_UNIQUE_NAME, 0)); + if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL, recursive, &local_nv, &local_avl)) != 0) return (error); @@ -2079,6 +2082,8 @@ again: needagain = B_TRUE; else progress = B_TRUE; + sprintf(guidname, "%lu", thisguid); + nvlist_add_boolean(deleted, guidname); continue; } @@ -2134,6 +2139,8 @@ again: needagain = B_TRUE; else progress = B_TRUE; + sprintf(guidname, "%lu", parent_fromsnap_guid); + nvlist_add_boolean(deleted, guidname); continue; } @@ -2156,6 +2163,24 @@ again: s2 = strrchr(stream_fsname, '/'); /* + * Check if we're going to rename based on parent guid change + * and the current parent guid was also deleted. If it was then + * rename will fail and is likely unneeded, so avoid this and + * force an early retry to determine the new + * parent_fromsnap_guid. + */ + if (stream_parent_fromsnap_guid != 0 && + parent_fromsnap_guid != 0 && + stream_parent_fromsnap_guid != parent_fromsnap_guid) { + sprintf(guidname, "%lu", parent_fromsnap_guid); + if (nvlist_exists(deleted, guidname)) { + progress = B_TRUE; + needagain = B_TRUE; + goto doagain; + } + } + + /* * Check for rename. If the exact receive path is specified, it * does not count as a rename, but we still need to check the * datasets beneath it. @@ -2209,8 +2234,10 @@ again: } } +doagain: fsavl_destroy(local_avl); nvlist_free(local_nv); + nvlist_free(deleted); if (needagain && progress) { /* do another pass to fix up temporary names */