Date: Thu, 13 Dec 2012 22:03:07 +0000 (UTC) From: Steven Hartland <smh@FreeBSD.org> 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 Message-ID: <201212132203.qBDM38R3022846@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212132203.qBDM38R3022846>