From 4b20a6f50999366b9ea17180838235c7733e5a53 Mon Sep 17 00:00:00 2001 From: Matthew Ahrens Date: Fri, 12 Sep 2014 05:45:50 +0200 Subject: [PATCH] Illumos 5150 - zfs clone of a defer_destroy snapshot causes strangeness When a clone is created of a snapshot that has been marked for deferred destroy (with "zfs destroy -d"), the clone "inherits" the defer_destroy flag from the origin, and any snapshots of the clone "inherit" the defer_destroy flag from the clone. This causes a strange situation where the clone's snapshots are marked for defer_destroy but they have no holds or clones. If the clone's snapshot gets a hold or clone, which is then deleted, we will honor the incorrectly-set defer_destroy flag and delete the snapshot! Steps to reproduce: * zpool create test c1t1d0 * zfs create test/fs * zfs snapshot test/fs@a * zfs clone test/fs@a test/clone * zfs destroy -d test/fs@a * zfs clone test/fs@a test/clone2 * zfs snapshot test/clone2@a * zfs hold hld test/clone2@a * zfs release hld test/clone2@a * zfs list -r -t all test We noticed that this causes dcenter to get very confused, because it treats snapshots that are marked defer_destroy as not existing. So it won't see any snapshots of the clone that's marked defer_destroy. 5150 - zfs clone of a defer_destroy snapshot causes strangeness Reviewed by: Christopher Siden Reviewed by: George Wilson Reviewed by: Max Grossman Reviewed by: Saso Kiselkov Reviewed by: Richard Elling Approved by: Robert Mustacchi References: https://www.illumos.org/projects/illumos-gate//issues/5150 https://github.com/illumos/illumos-gate/commit/42fcb65 Ported by: Turbo Fredriksson Signed-off-by: Brian Behlendorf Closes #2690 --- module/zfs/dsl_dataset.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c index 91d9120a5..3d5551cc4 100644 --- a/module/zfs/dsl_dataset.c +++ b/module/zfs/dsl_dataset.c @@ -686,7 +686,13 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin, dsphys->ds_uncompressed_bytes = origin->ds_phys->ds_uncompressed_bytes; dsphys->ds_bp = origin->ds_phys->ds_bp; - dsphys->ds_flags |= origin->ds_phys->ds_flags; + + /* + * Inherit flags that describe the dataset's contents + * (INCONSISTENT) or properties (Case Insensitive). + */ + dsphys->ds_flags |= origin->ds_phys->ds_flags & + (DS_FLAG_INCONSISTENT | DS_FLAG_CI_DATASET); dmu_buf_will_dirty(origin->ds_dbuf, tx); origin->ds_phys->ds_num_children++;