summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2013-07-30 21:20:12 +0000
committerdelphij <delphij@FreeBSD.org>2013-07-30 21:20:12 +0000
commit6cd9d0f4540cebd88fc799aa2cb692e8d3d49dcd (patch)
tree6904009d0609c6dda7915ddfa32d00f57b965ee7 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
parentc5affee6a3a59d69c44d3493fa98bec9080bb11f (diff)
downloadFreeBSD-src-6cd9d0f4540cebd88fc799aa2cb692e8d3d49dcd.zip
FreeBSD-src-6cd9d0f4540cebd88fc799aa2cb692e8d3d49dcd.tar.gz
MFV r253782:
To quote Illumos issue #3888: When 'zfs recv -F' is used with an incremental recv it rolls back any changes made since the last snapshot in case new changes were made to the file system while the recv is in progress (without -F the recv would fail when it does it's final check to commit the recv-ed data as the recv-ed data conflicts with the newly written data). However, if there is a snapshot taken after the recv began rolling back to the 'latest' snapshot will not help and the recv will still fail. 'zfs recv -F' should be extended to destroy any snapshots created since the source snapshot when finishing the recv (effectively rolling back through all snapshots, instead of just to the latest snapshot). Illumos ZFS issues: 3888 zfs recv -F should destroy any snapshots created since the incremental source MFC after: 2 weeks
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
index 774f354..1faebc1 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
@@ -1593,16 +1593,16 @@ dsl_dataset_space(dsl_dataset_t *ds,
}
boolean_t
-dsl_dataset_modified_since_lastsnap(dsl_dataset_t *ds)
+dsl_dataset_modified_since_snap(dsl_dataset_t *ds, dsl_dataset_t *snap)
{
dsl_pool_t *dp = ds->ds_dir->dd_pool;
ASSERT(dsl_pool_config_held(dp));
- if (ds->ds_prev == NULL)
+ if (snap == NULL)
return (B_FALSE);
if (ds->ds_phys->ds_bp.blk_birth >
- ds->ds_prev->ds_phys->ds_creation_txg) {
- objset_t *os, *os_prev;
+ snap->ds_phys->ds_creation_txg) {
+ objset_t *os, *os_snap;
/*
* It may be that only the ZIL differs, because it was
* reset in the head. Don't count that as being
@@ -1610,10 +1610,10 @@ dsl_dataset_modified_since_lastsnap(dsl_dataset_t *ds)
*/
if (dmu_objset_from_ds(ds, &os) != 0)
return (B_TRUE);
- if (dmu_objset_from_ds(ds->ds_prev, &os_prev) != 0)
+ if (dmu_objset_from_ds(snap, &os_snap) != 0)
return (B_TRUE);
return (bcmp(&os->os_phys->os_meta_dnode,
- &os_prev->os_phys->os_meta_dnode,
+ &os_snap->os_phys->os_meta_dnode,
sizeof (os->os_phys->os_meta_dnode)) != 0);
}
return (B_FALSE);
@@ -2436,15 +2436,14 @@ dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
dsl_dataset_is_snapshot(origin_head))
return (SET_ERROR(EINVAL));
- /* the branch point should be just before them */
- if (clone->ds_prev != origin_head->ds_prev)
+ /* if we are not forcing, the branch point should be just before them */
+ if (!force && clone->ds_prev != origin_head->ds_prev)
return (SET_ERROR(EINVAL));
/* clone should be the clone (unless they are unrelated) */
if (clone->ds_prev != NULL &&
clone->ds_prev != clone->ds_dir->dd_pool->dp_origin_snap &&
- origin_head->ds_object !=
- clone->ds_prev->ds_phys->ds_next_snap_obj)
+ origin_head->ds_dir != clone->ds_prev->ds_dir)
return (SET_ERROR(EINVAL));
/* the clone should be a child of the origin */
@@ -2452,7 +2451,8 @@ dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
return (SET_ERROR(EINVAL));
/* origin_head shouldn't be modified unless 'force' */
- if (!force && dsl_dataset_modified_since_lastsnap(origin_head))
+ if (!force &&
+ dsl_dataset_modified_since_snap(origin_head, origin_head->ds_prev))
return (SET_ERROR(ETXTBSY));
/* origin_head should have no long holds (e.g. is not mounted) */
@@ -2489,6 +2489,7 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
ASSERT(clone->ds_reserved == 0);
ASSERT(origin_head->ds_quota == 0 ||
clone->ds_phys->ds_unique_bytes <= origin_head->ds_quota);
+ ASSERT3P(clone->ds_prev, ==, origin_head->ds_prev);
dmu_buf_will_dirty(clone->ds_dbuf, tx);
dmu_buf_will_dirty(origin_head->ds_dbuf, tx);
OpenPOWER on IntegriCloud