706
707 if (zhp->zfs_dmustats.dds_origin[0]) {
708 zfs_handle_t *origin = zfs_open(zhp->zfs_hdl,
709 zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT);
710 if (origin == NULL)
711 return (-1);
712 VERIFY(0 == nvlist_add_uint64(nvfs, "origin",
713 origin->zfs_dmustats.dds_guid));
714 }
715
716 /* iterate over props */
717 VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
718 send_iterate_prop(zhp, nv);
719 VERIFY(0 == nvlist_add_nvlist(nvfs, "props", nv));
720 nvlist_free(nv);
721
722 /* iterate over snaps, and set sd->parent_fromsnap_guid */
723 sd->parent_fromsnap_guid = 0;
724 VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0));
725 VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0));
726 (void) zfs_iter_snapshots(zhp, send_iterate_snap, sd);
727 VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
728 VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops));
729 nvlist_free(sd->parent_snaps);
730 nvlist_free(sd->snapprops);
731
732 /* add this fs to nvlist */
733 (void) snprintf(guidstring, sizeof (guidstring),
734 "0x%llx", (longlong_t)guid);
735 VERIFY(0 == nvlist_add_nvlist(sd->fss, guidstring, nvfs));
736 nvlist_free(nvfs);
737
738 /* iterate over children */
739 if (sd->recursive)
740 rv = zfs_iter_filesystems(zhp, send_iterate_fs, sd);
741
742 sd->parent_fromsnap_guid = parent_fromsnap_guid_save;
743
744 zfs_close(zhp);
745 return (rv);
746 }
1919 create2 = zfs_prop_get_int(guid2hdl, ZFS_PROP_CREATETXG);
1920
1921 if (create1 < create2)
1922 rv = -1;
1923 else if (create1 > create2)
1924 rv = +1;
1925 else
1926 rv = 0;
1927
1928 zfs_close(guid1hdl);
1929 zfs_close(guid2hdl);
1930
1931 return (rv);
1932 }
1933
1934 static int
1935 recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
1936 recvflags_t *flags, nvlist_t *stream_nv, avl_tree_t *stream_avl,
1937 nvlist_t *renamed)
1938 {
1939 nvlist_t *local_nv;
1940 avl_tree_t *local_avl;
1941 nvpair_t *fselem, *nextfselem;
1942 char *fromsnap;
1943 char newname[ZFS_MAXNAMELEN];
1944 int error;
1945 boolean_t needagain, progress, recursive;
1946 char *s1, *s2;
1947
1948 VERIFY(0 == nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap));
1949
1950 recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
1951 ENOENT);
1952
1953 if (flags->dryrun)
1954 return (0);
1955
1956 again:
1957 needagain = progress = B_FALSE;
1958
1959 if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
1960 recursive, &local_nv, &local_avl)) != 0)
1961 return (error);
1962
1963 /*
1964 * Process deletes and renames
1965 */
1966 for (fselem = nvlist_next_nvpair(local_nv, NULL);
1967 fselem; fselem = nextfselem) {
1968 nvlist_t *nvfs, *snaps;
1969 nvlist_t *stream_nvfs = NULL;
1970 nvpair_t *snapelem, *nextsnapelem;
1971 uint64_t fromguid = 0;
1972 uint64_t originguid = 0;
1973 uint64_t stream_originguid = 0;
1974 uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid;
1975 char *fsname, *stream_fsname;
1976
1977 nextfselem = nvlist_next_nvpair(local_nv, fselem);
1978
1979 VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs));
1980 VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps));
1981 VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
1982 VERIFY(0 == nvlist_lookup_uint64(nvfs, "parentfromsnap",
2014 (void) printf("promoting %s\n", fsname);
2015
2016 origin_nvfs = fsavl_find(local_avl, originguid,
2017 NULL);
2018 VERIFY(0 == nvlist_lookup_string(origin_nvfs,
2019 "name", &origin_fsname));
2020 (void) strlcpy(zc.zc_value, origin_fsname,
2021 sizeof (zc.zc_value));
2022 (void) strlcpy(zc.zc_name, fsname,
2023 sizeof (zc.zc_name));
2024 error = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
2025 if (error == 0)
2026 progress = B_TRUE;
2027 break;
2028 }
2029 default:
2030 break;
2031 case -1:
2032 fsavl_destroy(local_avl);
2033 nvlist_free(local_nv);
2034 return (-1);
2035 }
2036 /*
2037 * We had/have the wrong origin, therefore our
2038 * list of snapshots is wrong. Need to handle
2039 * them on the next pass.
2040 */
2041 needagain = B_TRUE;
2042 continue;
2043 }
2044
2045 for (snapelem = nvlist_next_nvpair(snaps, NULL);
2046 snapelem; snapelem = nextsnapelem) {
2047 uint64_t thisguid;
2048 char *stream_snapname;
2049 nvlist_t *found, *props;
2050
2051 nextsnapelem = nvlist_next_nvpair(snaps, snapelem);
2052
2053 VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid));
2054 found = fsavl_find(stream_avl, thisguid,
2055 &stream_snapname);
2056
2057 /* check for delete */
2058 if (found == NULL) {
2059 char name[ZFS_MAXNAMELEN];
2060
2061 if (!flags->force)
2062 continue;
2063
2064 (void) snprintf(name, sizeof (name), "%s@%s",
2065 fsname, nvpair_name(snapelem));
2066
2067 error = recv_destroy(hdl, name,
2068 strlen(fsname)+1, newname, flags);
2069 if (error)
2070 needagain = B_TRUE;
2071 else
2072 progress = B_TRUE;
2073 continue;
2074 }
2075
2076 stream_nvfs = found;
2077
2078 if (0 == nvlist_lookup_nvlist(stream_nvfs, "snapprops",
2079 &props) && 0 == nvlist_lookup_nvlist(props,
2080 stream_snapname, &props)) {
2081 zfs_cmd_t zc = { 0 };
2082
2083 zc.zc_cookie = B_TRUE; /* received */
2084 (void) snprintf(zc.zc_name, sizeof (zc.zc_name),
2085 "%s@%s", fsname, nvpair_name(snapelem));
2086 if (zcmd_write_src_nvlist(hdl, &zc,
2087 props) == 0) {
2088 (void) zfs_ioctl(hdl,
2089 ZFS_IOC_SET_PROP, &zc);
2090 zcmd_free_nvlists(&zc);
2091 }
2092 }
2108 needagain = B_TRUE;
2109 else
2110 progress = B_TRUE;
2111 }
2112
2113 if (strcmp(stream_snapname, fromsnap) == 0)
2114 fromguid = thisguid;
2115 }
2116
2117 /* check for delete */
2118 if (stream_nvfs == NULL) {
2119 if (!flags->force)
2120 continue;
2121
2122 error = recv_destroy(hdl, fsname, strlen(tofs)+1,
2123 newname, flags);
2124 if (error)
2125 needagain = B_TRUE;
2126 else
2127 progress = B_TRUE;
2128 continue;
2129 }
2130
2131 if (fromguid == 0) {
2132 if (flags->verbose) {
2133 (void) printf("local fs %s does not have "
2134 "fromsnap (%s in stream); must have "
2135 "been deleted locally; ignoring\n",
2136 fsname, fromsnap);
2137 }
2138 continue;
2139 }
2140
2141 VERIFY(0 == nvlist_lookup_string(stream_nvfs,
2142 "name", &stream_fsname));
2143 VERIFY(0 == nvlist_lookup_uint64(stream_nvfs,
2144 "parentfromsnap", &stream_parent_fromsnap_guid));
2145
2146 s1 = strrchr(fsname, '/');
2147 s2 = strrchr(stream_fsname, '/');
2148
2149 /*
2150 * Check for rename. If the exact receive path is specified, it
2151 * does not count as a rename, but we still need to check the
2152 * datasets beneath it.
2153 */
2154 if ((stream_parent_fromsnap_guid != 0 &&
2155 parent_fromsnap_guid != 0 &&
2156 stream_parent_fromsnap_guid != parent_fromsnap_guid) ||
2157 ((flags->isprefix || strcmp(tofs, fsname) != 0) &&
2158 (s1 != NULL) && (s2 != NULL) && strcmp(s1, s2) != 0)) {
2159 nvlist_t *parent;
2160 char tryname[ZFS_MAXNAMELEN];
2161
2162 parent = fsavl_find(local_avl,
2163 stream_parent_fromsnap_guid, NULL);
2164 /*
2165 * NB: parent might not be found if we used the
2166 * tosnap for stream_parent_fromsnap_guid,
2167 * because the parent is a newly-created fs;
2168 * we'll be able to rename it after we recv the
2169 * new fs.
2183 }
2184 }
2185
2186 newname[0] = '\0';
2187
2188 error = recv_rename(hdl, fsname, tryname,
2189 strlen(tofs)+1, newname, flags);
2190
2191 if (renamed != NULL && newname[0] != '\0') {
2192 VERIFY(0 == nvlist_add_boolean(renamed,
2193 newname));
2194 }
2195
2196 if (error)
2197 needagain = B_TRUE;
2198 else
2199 progress = B_TRUE;
2200 }
2201 }
2202
2203 fsavl_destroy(local_avl);
2204 nvlist_free(local_nv);
2205
2206 if (needagain && progress) {
2207 /* do another pass to fix up temporary names */
2208 if (flags->verbose)
2209 (void) printf("another pass:\n");
2210 goto again;
2211 }
2212
2213 return (needagain);
2214 }
2215
2216 static int
2217 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2218 recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2219 char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2220 {
2221 nvlist_t *stream_nv = NULL;
2222 avl_tree_t *stream_avl = NULL;
2223 char *fromsnap = NULL;
2224 char *cp;
|
706
707 if (zhp->zfs_dmustats.dds_origin[0]) {
708 zfs_handle_t *origin = zfs_open(zhp->zfs_hdl,
709 zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT);
710 if (origin == NULL)
711 return (-1);
712 VERIFY(0 == nvlist_add_uint64(nvfs, "origin",
713 origin->zfs_dmustats.dds_guid));
714 }
715
716 /* iterate over props */
717 VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
718 send_iterate_prop(zhp, nv);
719 VERIFY(0 == nvlist_add_nvlist(nvfs, "props", nv));
720 nvlist_free(nv);
721
722 /* iterate over snaps, and set sd->parent_fromsnap_guid */
723 sd->parent_fromsnap_guid = 0;
724 VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0));
725 VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0));
726 (void) zfs_iter_snapshots_sorted(zhp, send_iterate_snap, sd);
727 VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
728 VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops));
729 nvlist_free(sd->parent_snaps);
730 nvlist_free(sd->snapprops);
731
732 /* add this fs to nvlist */
733 (void) snprintf(guidstring, sizeof (guidstring),
734 "0x%llx", (longlong_t)guid);
735 VERIFY(0 == nvlist_add_nvlist(sd->fss, guidstring, nvfs));
736 nvlist_free(nvfs);
737
738 /* iterate over children */
739 if (sd->recursive)
740 rv = zfs_iter_filesystems(zhp, send_iterate_fs, sd);
741
742 sd->parent_fromsnap_guid = parent_fromsnap_guid_save;
743
744 zfs_close(zhp);
745 return (rv);
746 }
1919 create2 = zfs_prop_get_int(guid2hdl, ZFS_PROP_CREATETXG);
1920
1921 if (create1 < create2)
1922 rv = -1;
1923 else if (create1 > create2)
1924 rv = +1;
1925 else
1926 rv = 0;
1927
1928 zfs_close(guid1hdl);
1929 zfs_close(guid2hdl);
1930
1931 return (rv);
1932 }
1933
1934 static int
1935 recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
1936 recvflags_t *flags, nvlist_t *stream_nv, avl_tree_t *stream_avl,
1937 nvlist_t *renamed)
1938 {
1939 nvlist_t *local_nv, *deleted = NULL;
1940 avl_tree_t *local_avl;
1941 nvpair_t *fselem, *nextfselem;
1942 char *fromsnap;
1943 char newname[ZFS_MAXNAMELEN], guidname[32];
1944 int error;
1945 boolean_t needagain, progress, recursive;
1946 char *s1, *s2;
1947
1948 VERIFY(0 == nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap));
1949
1950 recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
1951 ENOENT);
1952
1953 if (flags->dryrun)
1954 return (0);
1955
1956 again:
1957 needagain = progress = B_FALSE;
1958
1959 if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
1960 recursive, &local_nv, &local_avl)) != 0)
1961 return (error);
1962
1963 deleted = fnvlist_alloc();
1964
1965 /*
1966 * Process deletes and renames
1967 */
1968 for (fselem = nvlist_next_nvpair(local_nv, NULL);
1969 fselem; fselem = nextfselem) {
1970 nvlist_t *nvfs, *snaps;
1971 nvlist_t *stream_nvfs = NULL;
1972 nvpair_t *snapelem, *nextsnapelem;
1973 uint64_t fromguid = 0;
1974 uint64_t originguid = 0;
1975 uint64_t stream_originguid = 0;
1976 uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid;
1977 char *fsname, *stream_fsname;
1978
1979 nextfselem = nvlist_next_nvpair(local_nv, fselem);
1980
1981 VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs));
1982 VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps));
1983 VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
1984 VERIFY(0 == nvlist_lookup_uint64(nvfs, "parentfromsnap",
2016 (void) printf("promoting %s\n", fsname);
2017
2018 origin_nvfs = fsavl_find(local_avl, originguid,
2019 NULL);
2020 VERIFY(0 == nvlist_lookup_string(origin_nvfs,
2021 "name", &origin_fsname));
2022 (void) strlcpy(zc.zc_value, origin_fsname,
2023 sizeof (zc.zc_value));
2024 (void) strlcpy(zc.zc_name, fsname,
2025 sizeof (zc.zc_name));
2026 error = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
2027 if (error == 0)
2028 progress = B_TRUE;
2029 break;
2030 }
2031 default:
2032 break;
2033 case -1:
2034 fsavl_destroy(local_avl);
2035 nvlist_free(local_nv);
2036 nvlist_free(deleted);
2037 return (-1);
2038 }
2039 /*
2040 * We had/have the wrong origin, therefore our
2041 * list of snapshots is wrong. Need to handle
2042 * them on the next pass.
2043 */
2044 needagain = B_TRUE;
2045 continue;
2046 }
2047
2048 for (snapelem = nvlist_next_nvpair(snaps, NULL);
2049 snapelem; snapelem = nextsnapelem) {
2050 uint64_t thisguid;
2051 char *stream_snapname;
2052 nvlist_t *found, *props;
2053
2054 nextsnapelem = nvlist_next_nvpair(snaps, snapelem);
2055
2056 VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid));
2057 found = fsavl_find(stream_avl, thisguid,
2058 &stream_snapname);
2059
2060 /* check for delete */
2061 if (found == NULL) {
2062 char name[ZFS_MAXNAMELEN];
2063
2064 if (!flags->force)
2065 continue;
2066
2067 (void) snprintf(name, sizeof (name), "%s@%s",
2068 fsname, nvpair_name(snapelem));
2069
2070 error = recv_destroy(hdl, name,
2071 strlen(fsname)+1, newname, flags);
2072 if (error)
2073 needagain = B_TRUE;
2074 else
2075 progress = B_TRUE;
2076 (void) sprintf(guidname, "%llu",
2077 (u_longlong_t)thisguid);
2078 fnvlist_add_boolean(deleted, guidname);
2079 continue;
2080 }
2081
2082 stream_nvfs = found;
2083
2084 if (0 == nvlist_lookup_nvlist(stream_nvfs, "snapprops",
2085 &props) && 0 == nvlist_lookup_nvlist(props,
2086 stream_snapname, &props)) {
2087 zfs_cmd_t zc = { 0 };
2088
2089 zc.zc_cookie = B_TRUE; /* received */
2090 (void) snprintf(zc.zc_name, sizeof (zc.zc_name),
2091 "%s@%s", fsname, nvpair_name(snapelem));
2092 if (zcmd_write_src_nvlist(hdl, &zc,
2093 props) == 0) {
2094 (void) zfs_ioctl(hdl,
2095 ZFS_IOC_SET_PROP, &zc);
2096 zcmd_free_nvlists(&zc);
2097 }
2098 }
2114 needagain = B_TRUE;
2115 else
2116 progress = B_TRUE;
2117 }
2118
2119 if (strcmp(stream_snapname, fromsnap) == 0)
2120 fromguid = thisguid;
2121 }
2122
2123 /* check for delete */
2124 if (stream_nvfs == NULL) {
2125 if (!flags->force)
2126 continue;
2127
2128 error = recv_destroy(hdl, fsname, strlen(tofs)+1,
2129 newname, flags);
2130 if (error)
2131 needagain = B_TRUE;
2132 else
2133 progress = B_TRUE;
2134 (void) sprintf(guidname, "%llu",
2135 (u_longlong_t)parent_fromsnap_guid);
2136 fnvlist_add_boolean(deleted, guidname);
2137 continue;
2138 }
2139
2140 if (fromguid == 0) {
2141 if (flags->verbose) {
2142 (void) printf("local fs %s does not have "
2143 "fromsnap (%s in stream); must have "
2144 "been deleted locally; ignoring\n",
2145 fsname, fromsnap);
2146 }
2147 continue;
2148 }
2149
2150 VERIFY(0 == nvlist_lookup_string(stream_nvfs,
2151 "name", &stream_fsname));
2152 VERIFY(0 == nvlist_lookup_uint64(stream_nvfs,
2153 "parentfromsnap", &stream_parent_fromsnap_guid));
2154
2155 s1 = strrchr(fsname, '/');
2156 s2 = strrchr(stream_fsname, '/');
2157
2158 /*
2159 * Check if we're going to rename based on parent guid change
2160 * and the current parent guid was also deleted. If it was then
2161 * the rename will fail so avoid this and force an early retry
2162 * to determine the new parent_fromsnap_guid.
2163 */
2164 if (stream_parent_fromsnap_guid != 0 &&
2165 parent_fromsnap_guid != 0 &&
2166 stream_parent_fromsnap_guid != parent_fromsnap_guid) {
2167 (void) sprintf(guidname, "%llu",
2168 (u_longlong_t)parent_fromsnap_guid);
2169 if (nvlist_exists(deleted, guidname)) {
2170 progress = B_TRUE;
2171 needagain = B_TRUE;
2172 goto doagain;
2173 }
2174 }
2175
2176 /*
2177 * Check for rename. If the exact receive path is specified, it
2178 * does not count as a rename, but we still need to check the
2179 * datasets beneath it.
2180 */
2181 if ((stream_parent_fromsnap_guid != 0 &&
2182 parent_fromsnap_guid != 0 &&
2183 stream_parent_fromsnap_guid != parent_fromsnap_guid) ||
2184 ((flags->isprefix || strcmp(tofs, fsname) != 0) &&
2185 (s1 != NULL) && (s2 != NULL) && strcmp(s1, s2) != 0)) {
2186 nvlist_t *parent;
2187 char tryname[ZFS_MAXNAMELEN];
2188
2189 parent = fsavl_find(local_avl,
2190 stream_parent_fromsnap_guid, NULL);
2191 /*
2192 * NB: parent might not be found if we used the
2193 * tosnap for stream_parent_fromsnap_guid,
2194 * because the parent is a newly-created fs;
2195 * we'll be able to rename it after we recv the
2196 * new fs.
2210 }
2211 }
2212
2213 newname[0] = '\0';
2214
2215 error = recv_rename(hdl, fsname, tryname,
2216 strlen(tofs)+1, newname, flags);
2217
2218 if (renamed != NULL && newname[0] != '\0') {
2219 VERIFY(0 == nvlist_add_boolean(renamed,
2220 newname));
2221 }
2222
2223 if (error)
2224 needagain = B_TRUE;
2225 else
2226 progress = B_TRUE;
2227 }
2228 }
2229
2230 doagain:
2231 fsavl_destroy(local_avl);
2232 nvlist_free(local_nv);
2233 nvlist_free(deleted);
2234
2235 if (needagain && progress) {
2236 /* do another pass to fix up temporary names */
2237 if (flags->verbose)
2238 (void) printf("another pass:\n");
2239 goto again;
2240 }
2241
2242 return (needagain);
2243 }
2244
2245 static int
2246 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2247 recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2248 char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2249 {
2250 nvlist_t *stream_nv = NULL;
2251 avl_tree_t *stream_avl = NULL;
2252 char *fromsnap = NULL;
2253 char *cp;
|