Skip to content

Commit 4099119

Browse files
committed
7247 zfs receive of deduplicated stream fails
This resolves two 'zfs recv' issues. First, when receiving into an existing filesystem, a snapshot created during the receive process is not added to the guid->dataset map for the stream, resulting in failed lookups for deduped streams when a WRITE_BYREF record refers to a snapshot received earlier in the stream. Second, the newly created snapshot was also not set properly, referencing the snapshot before the new receiving dataset rather than the existing filesystem. Closes #159 Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Dan Kimmel <dan.kimmel@delphix.com> Author: Chris Williamson <chris.williamson@delphix.com> openzfs/openzfs@b09697c
1 parent e172733 commit 4099119

File tree

1 file changed

+21
-23
lines changed

1 file changed

+21
-23
lines changed

uts/common/fs/zfs/dmu_send.c

+21-23
Original file line numberDiff line numberDiff line change
@@ -3047,6 +3047,9 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx)
30473047
dsl_dataset_phys(origin_head)->ds_flags &=
30483048
~DS_FLAG_INCONSISTENT;
30493049

3050+
drc->drc_newsnapobj =
3051+
dsl_dataset_phys(origin_head)->ds_prev_snap_obj;
3052+
30503053
dsl_dataset_rele(origin_head, FTAG);
30513054
dsl_destroy_head_sync_impl(drc->drc_ds, tx);
30523055

@@ -3082,8 +3085,9 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx)
30823085
(void) zap_remove(dp->dp_meta_objset, ds->ds_object,
30833086
DS_FIELD_RESUME_TONAME, tx);
30843087
}
3088+
drc->drc_newsnapobj =
3089+
dsl_dataset_phys(drc->drc_ds)->ds_prev_snap_obj;
30853090
}
3086-
drc->drc_newsnapobj = dsl_dataset_phys(drc->drc_ds)->ds_prev_snap_obj;
30873091
/*
30883092
* Release the hold from dmu_recv_begin. This must be done before
30893093
* we return to open context, so that when we free the dataset's dnode,
@@ -3126,8 +3130,6 @@ static int dmu_recv_end_modified_blocks = 3;
31263130
static int
31273131
dmu_recv_existing_end(dmu_recv_cookie_t *drc)
31283132
{
3129-
int error;
3130-
31313133
#ifdef _KERNEL
31323134
/*
31333135
* We will be destroying the ds; make sure its origin is unmounted if
@@ -3138,23 +3140,30 @@ dmu_recv_existing_end(dmu_recv_cookie_t *drc)
31383140
zfs_destroy_unmount_origin(name);
31393141
#endif
31403142

3141-
error = dsl_sync_task(drc->drc_tofs,
3143+
return (dsl_sync_task(drc->drc_tofs,
31423144
dmu_recv_end_check, dmu_recv_end_sync, drc,
3143-
dmu_recv_end_modified_blocks, ZFS_SPACE_CHECK_NORMAL);
3144-
3145-
if (error != 0)
3146-
dmu_recv_cleanup_ds(drc);
3147-
return (error);
3145+
dmu_recv_end_modified_blocks, ZFS_SPACE_CHECK_NORMAL));
31483146
}
31493147

31503148
static int
31513149
dmu_recv_new_end(dmu_recv_cookie_t *drc)
3150+
{
3151+
return (dsl_sync_task(drc->drc_tofs,
3152+
dmu_recv_end_check, dmu_recv_end_sync, drc,
3153+
dmu_recv_end_modified_blocks, ZFS_SPACE_CHECK_NORMAL));
3154+
}
3155+
3156+
int
3157+
dmu_recv_end(dmu_recv_cookie_t *drc, void *owner)
31523158
{
31533159
int error;
31543160

3155-
error = dsl_sync_task(drc->drc_tofs,
3156-
dmu_recv_end_check, dmu_recv_end_sync, drc,
3157-
dmu_recv_end_modified_blocks, ZFS_SPACE_CHECK_NORMAL);
3161+
drc->drc_owner = owner;
3162+
3163+
if (drc->drc_newfs)
3164+
error = dmu_recv_new_end(drc);
3165+
else
3166+
error = dmu_recv_existing_end(drc);
31583167

31593168
if (error != 0) {
31603169
dmu_recv_cleanup_ds(drc);
@@ -3166,17 +3175,6 @@ dmu_recv_new_end(dmu_recv_cookie_t *drc)
31663175
return (error);
31673176
}
31683177

3169-
int
3170-
dmu_recv_end(dmu_recv_cookie_t *drc, void *owner)
3171-
{
3172-
drc->drc_owner = owner;
3173-
3174-
if (drc->drc_newfs)
3175-
return (dmu_recv_new_end(drc));
3176-
else
3177-
return (dmu_recv_existing_end(drc));
3178-
}
3179-
31803178
/*
31813179
* Return TRUE if this objset is currently being received into.
31823180
*/

0 commit comments

Comments
 (0)