21 /*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2013 by Delphix. All rights reserved.
24 * Copyright (c) 2013 Steven Hartland. All rights reserved.
25 */
26
27 #include <sys/zfs_context.h>
28 #include <sys/dsl_userhold.h>
29 #include <sys/dsl_dataset.h>
30 #include <sys/dsl_synctask.h>
31 #include <sys/dmu_tx.h>
32 #include <sys/dsl_pool.h>
33 #include <sys/dsl_dir.h>
34 #include <sys/dmu_traverse.h>
35 #include <sys/dsl_scan.h>
36 #include <sys/dmu_objset.h>
37 #include <sys/zap.h>
38 #include <sys/zfeature.h>
39 #include <sys/zfs_ioctl.h>
40 #include <sys/dsl_deleg.h>
41
42 typedef struct dmu_snapshots_destroy_arg {
43 nvlist_t *dsda_snaps;
44 nvlist_t *dsda_successful_snaps;
45 boolean_t dsda_defer;
46 nvlist_t *dsda_errlist;
47 } dmu_snapshots_destroy_arg_t;
48
49 int
50 dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boolean_t defer)
51 {
52 if (!dsl_dataset_is_snapshot(ds))
53 return (SET_ERROR(EINVAL));
54
55 if (dsl_dataset_long_held(ds))
56 return (SET_ERROR(EBUSY));
57
58 /*
59 * Only allow deferred destroy on pools that support it.
60 * NOTE: deferred destroy is only supported on snapshots.
431 dsl_dataset_rele(ds_head, FTAG);
432
433 if (ds_prev != NULL)
434 dsl_dataset_rele(ds_prev, FTAG);
435
436 spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
437
438 if (ds->ds_phys->ds_next_clones_obj != 0) {
439 uint64_t count;
440 ASSERT0(zap_count(mos,
441 ds->ds_phys->ds_next_clones_obj, &count) && count == 0);
442 VERIFY0(dmu_object_free(mos,
443 ds->ds_phys->ds_next_clones_obj, tx));
444 }
445 if (ds->ds_phys->ds_props_obj != 0)
446 VERIFY0(zap_destroy(mos, ds->ds_phys->ds_props_obj, tx));
447 if (ds->ds_phys->ds_userrefs_obj != 0)
448 VERIFY0(zap_destroy(mos, ds->ds_phys->ds_userrefs_obj, tx));
449 dsl_dir_rele(ds->ds_dir, ds);
450 ds->ds_dir = NULL;
451 VERIFY0(dmu_object_free(mos, obj, tx));
452 }
453
454 static void
455 dsl_destroy_snapshot_sync(void *arg, dmu_tx_t *tx)
456 {
457 dmu_snapshots_destroy_arg_t *dsda = arg;
458 dsl_pool_t *dp = dmu_tx_pool(tx);
459 nvpair_t *pair;
460
461 for (pair = nvlist_next_nvpair(dsda->dsda_successful_snaps, NULL);
462 pair != NULL;
463 pair = nvlist_next_nvpair(dsda->dsda_successful_snaps, pair)) {
464 dsl_dataset_t *ds;
465
466 VERIFY0(dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds));
467
468 dsl_destroy_snapshot_sync_impl(ds, dsda->dsda_defer, tx);
469 dsl_dataset_rele(ds, FTAG);
470 }
471 }
654 ASSERT0(dd->dd_phys->dd_head_dataset_obj);
655
656 /*
657 * Remove our reservation. The impl() routine avoids setting the
658 * actual property, which would require the (already destroyed) ds.
659 */
660 dsl_dir_set_reservation_sync_impl(dd, 0, tx);
661
662 ASSERT0(dd->dd_phys->dd_used_bytes);
663 ASSERT0(dd->dd_phys->dd_reserved);
664 for (t = 0; t < DD_USED_NUM; t++)
665 ASSERT0(dd->dd_phys->dd_used_breakdown[t]);
666
667 VERIFY0(zap_destroy(mos, dd->dd_phys->dd_child_dir_zapobj, tx));
668 VERIFY0(zap_destroy(mos, dd->dd_phys->dd_props_zapobj, tx));
669 VERIFY0(dsl_deleg_destroy(mos, dd->dd_phys->dd_deleg_zapobj, tx));
670 VERIFY0(zap_remove(mos,
671 dd->dd_parent->dd_phys->dd_child_dir_zapobj, dd->dd_myname, tx));
672
673 dsl_dir_rele(dd, FTAG);
674 VERIFY0(dmu_object_free(mos, ddobj, tx));
675 }
676
677 void
678 dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
679 {
680 dsl_pool_t *dp = dmu_tx_pool(tx);
681 objset_t *mos = dp->dp_meta_objset;
682 uint64_t obj, ddobj, prevobj = 0;
683 boolean_t rmorigin;
684
685 ASSERT3U(ds->ds_phys->ds_num_children, <=, 1);
686 ASSERT(ds->ds_prev == NULL ||
687 ds->ds_prev->ds_phys->ds_next_snap_obj != ds->ds_object);
688 ASSERT3U(ds->ds_phys->ds_bp.blk_birth, <=, tx->tx_txg);
689 ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
690
691 /* We need to log before removing it from the namespace. */
692 spa_history_log_internal_ds(ds, "destroy", tx, "");
693
694 rmorigin = (dsl_dir_is_clone(ds->ds_dir) &&
707 dsl_scan_ds_destroyed(ds, tx);
708
709 obj = ds->ds_object;
710
711 if (ds->ds_phys->ds_prev_snap_obj != 0) {
712 /* This is a clone */
713 ASSERT(ds->ds_prev != NULL);
714 ASSERT3U(ds->ds_prev->ds_phys->ds_next_snap_obj, !=, obj);
715 ASSERT0(ds->ds_phys->ds_next_snap_obj);
716
717 dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
718 if (ds->ds_prev->ds_phys->ds_next_clones_obj != 0) {
719 dsl_dataset_remove_from_next_clones(ds->ds_prev,
720 obj, tx);
721 }
722
723 ASSERT3U(ds->ds_prev->ds_phys->ds_num_children, >, 1);
724 ds->ds_prev->ds_phys->ds_num_children--;
725 }
726
727 zfeature_info_t *async_destroy =
728 &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY];
729 objset_t *os;
730
731 /*
732 * Destroy the deadlist. Unless it's a clone, the
733 * deadlist should be empty. (If it's a clone, it's
734 * safe to ignore the deadlist contents.)
735 */
736 dsl_deadlist_close(&ds->ds_deadlist);
737 dsl_deadlist_free(mos, ds->ds_phys->ds_deadlist_obj, tx);
738 dmu_buf_will_dirty(ds->ds_dbuf, tx);
739 ds->ds_phys->ds_deadlist_obj = 0;
740
741 VERIFY0(dmu_objset_from_ds(ds, &os));
742
743 if (!spa_feature_is_enabled(dp->dp_spa, async_destroy)) {
744 old_synchronous_dataset_destroy(ds, tx);
745 } else {
746 /*
747 * Move the bptree into the pool's list of trees to
748 * clean up and update space accounting information.
749 */
750 uint64_t used, comp, uncomp;
751
752 zil_destroy_sync(dmu_objset_zil(os), tx);
753
754 if (!spa_feature_is_active(dp->dp_spa, async_destroy)) {
755 dsl_scan_t *scn = dp->dp_scan;
756
757 spa_feature_incr(dp->dp_spa, async_destroy, tx);
758 dp->dp_bptree_obj = bptree_alloc(mos, tx);
759 VERIFY0(zap_add(mos,
760 DMU_POOL_DIRECTORY_OBJECT,
761 DMU_POOL_BPTREE_OBJ, sizeof (uint64_t), 1,
762 &dp->dp_bptree_obj, tx));
763 ASSERT(!scn->scn_async_destroying);
764 scn->scn_async_destroying = B_TRUE;
765 }
766
767 used = ds->ds_dir->dd_phys->dd_used_bytes;
768 comp = ds->ds_dir->dd_phys->dd_compressed_bytes;
769 uncomp = ds->ds_dir->dd_phys->dd_uncompressed_bytes;
770
771 ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) ||
772 ds->ds_phys->ds_unique_bytes == used);
773
774 bptree_add(mos, dp->dp_bptree_obj,
775 &ds->ds_phys->ds_bp, ds->ds_phys->ds_prev_snap_txg,
776 used, comp, uncomp, tx);
777 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD,
797 */
798 if (ds->ds_objset) {
799 dmu_objset_evict(ds->ds_objset);
800 ds->ds_objset = NULL;
801 }
802
803 /* Erase the link in the dir */
804 dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx);
805 ds->ds_dir->dd_phys->dd_head_dataset_obj = 0;
806 ddobj = ds->ds_dir->dd_object;
807 ASSERT(ds->ds_phys->ds_snapnames_zapobj != 0);
808 VERIFY0(zap_destroy(mos, ds->ds_phys->ds_snapnames_zapobj, tx));
809
810 spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
811
812 ASSERT0(ds->ds_phys->ds_next_clones_obj);
813 ASSERT0(ds->ds_phys->ds_props_obj);
814 ASSERT0(ds->ds_phys->ds_userrefs_obj);
815 dsl_dir_rele(ds->ds_dir, ds);
816 ds->ds_dir = NULL;
817 VERIFY0(dmu_object_free(mos, obj, tx));
818
819 dsl_dir_destroy_sync(ddobj, tx);
820
821 if (rmorigin) {
822 dsl_dataset_t *prev;
823 VERIFY0(dsl_dataset_hold_obj(dp, prevobj, FTAG, &prev));
824 dsl_destroy_snapshot_sync_impl(prev, B_FALSE, tx);
825 dsl_dataset_rele(prev, FTAG);
826 }
827 }
828
829 static void
830 dsl_destroy_head_sync(void *arg, dmu_tx_t *tx)
831 {
832 dsl_destroy_head_arg_t *ddha = arg;
833 dsl_pool_t *dp = dmu_tx_pool(tx);
834 dsl_dataset_t *ds;
835
836 VERIFY0(dsl_dataset_hold(dp, ddha->ddha_name, FTAG, &ds));
837 dsl_destroy_head_sync_impl(ds, tx);
853
854 spa_history_log_internal_ds(ds, "destroy begin", tx, "");
855 dsl_dataset_rele(ds, FTAG);
856 }
857
858 int
859 dsl_destroy_head(const char *name)
860 {
861 dsl_destroy_head_arg_t ddha;
862 int error;
863 spa_t *spa;
864 boolean_t isenabled;
865
866 #ifdef _KERNEL
867 zfs_destroy_unmount_origin(name);
868 #endif
869
870 error = spa_open(name, &spa, FTAG);
871 if (error != 0)
872 return (error);
873 isenabled = spa_feature_is_enabled(spa,
874 &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY]);
875 spa_close(spa, FTAG);
876
877 ddha.ddha_name = name;
878
879 if (!isenabled) {
880 objset_t *os;
881
882 error = dsl_sync_task(name, dsl_destroy_head_check,
883 dsl_destroy_head_begin_sync, &ddha, 0);
884 if (error != 0)
885 return (error);
886
887 /*
888 * Head deletion is processed in one txg on old pools;
889 * remove the objects from open context so that the txg sync
890 * is not too long.
891 */
892 error = dmu_objset_own(name, DMU_OST_ANY, B_FALSE, FTAG, &os);
893 if (error == 0) {
894 uint64_t prev_snap_txg =
|
21 /*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2013 by Delphix. All rights reserved.
24 * Copyright (c) 2013 Steven Hartland. All rights reserved.
25 */
26
27 #include <sys/zfs_context.h>
28 #include <sys/dsl_userhold.h>
29 #include <sys/dsl_dataset.h>
30 #include <sys/dsl_synctask.h>
31 #include <sys/dmu_tx.h>
32 #include <sys/dsl_pool.h>
33 #include <sys/dsl_dir.h>
34 #include <sys/dmu_traverse.h>
35 #include <sys/dsl_scan.h>
36 #include <sys/dmu_objset.h>
37 #include <sys/zap.h>
38 #include <sys/zfeature.h>
39 #include <sys/zfs_ioctl.h>
40 #include <sys/dsl_deleg.h>
41 #include <sys/dmu_impl.h>
42
43 typedef struct dmu_snapshots_destroy_arg {
44 nvlist_t *dsda_snaps;
45 nvlist_t *dsda_successful_snaps;
46 boolean_t dsda_defer;
47 nvlist_t *dsda_errlist;
48 } dmu_snapshots_destroy_arg_t;
49
50 int
51 dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boolean_t defer)
52 {
53 if (!dsl_dataset_is_snapshot(ds))
54 return (SET_ERROR(EINVAL));
55
56 if (dsl_dataset_long_held(ds))
57 return (SET_ERROR(EBUSY));
58
59 /*
60 * Only allow deferred destroy on pools that support it.
61 * NOTE: deferred destroy is only supported on snapshots.
432 dsl_dataset_rele(ds_head, FTAG);
433
434 if (ds_prev != NULL)
435 dsl_dataset_rele(ds_prev, FTAG);
436
437 spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
438
439 if (ds->ds_phys->ds_next_clones_obj != 0) {
440 uint64_t count;
441 ASSERT0(zap_count(mos,
442 ds->ds_phys->ds_next_clones_obj, &count) && count == 0);
443 VERIFY0(dmu_object_free(mos,
444 ds->ds_phys->ds_next_clones_obj, tx));
445 }
446 if (ds->ds_phys->ds_props_obj != 0)
447 VERIFY0(zap_destroy(mos, ds->ds_phys->ds_props_obj, tx));
448 if (ds->ds_phys->ds_userrefs_obj != 0)
449 VERIFY0(zap_destroy(mos, ds->ds_phys->ds_userrefs_obj, tx));
450 dsl_dir_rele(ds->ds_dir, ds);
451 ds->ds_dir = NULL;
452 dmu_object_free_zapified(mos, obj, tx);
453 }
454
455 static void
456 dsl_destroy_snapshot_sync(void *arg, dmu_tx_t *tx)
457 {
458 dmu_snapshots_destroy_arg_t *dsda = arg;
459 dsl_pool_t *dp = dmu_tx_pool(tx);
460 nvpair_t *pair;
461
462 for (pair = nvlist_next_nvpair(dsda->dsda_successful_snaps, NULL);
463 pair != NULL;
464 pair = nvlist_next_nvpair(dsda->dsda_successful_snaps, pair)) {
465 dsl_dataset_t *ds;
466
467 VERIFY0(dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds));
468
469 dsl_destroy_snapshot_sync_impl(ds, dsda->dsda_defer, tx);
470 dsl_dataset_rele(ds, FTAG);
471 }
472 }
655 ASSERT0(dd->dd_phys->dd_head_dataset_obj);
656
657 /*
658 * Remove our reservation. The impl() routine avoids setting the
659 * actual property, which would require the (already destroyed) ds.
660 */
661 dsl_dir_set_reservation_sync_impl(dd, 0, tx);
662
663 ASSERT0(dd->dd_phys->dd_used_bytes);
664 ASSERT0(dd->dd_phys->dd_reserved);
665 for (t = 0; t < DD_USED_NUM; t++)
666 ASSERT0(dd->dd_phys->dd_used_breakdown[t]);
667
668 VERIFY0(zap_destroy(mos, dd->dd_phys->dd_child_dir_zapobj, tx));
669 VERIFY0(zap_destroy(mos, dd->dd_phys->dd_props_zapobj, tx));
670 VERIFY0(dsl_deleg_destroy(mos, dd->dd_phys->dd_deleg_zapobj, tx));
671 VERIFY0(zap_remove(mos,
672 dd->dd_parent->dd_phys->dd_child_dir_zapobj, dd->dd_myname, tx));
673
674 dsl_dir_rele(dd, FTAG);
675 dmu_object_free_zapified(mos, ddobj, tx);
676 }
677
678 void
679 dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
680 {
681 dsl_pool_t *dp = dmu_tx_pool(tx);
682 objset_t *mos = dp->dp_meta_objset;
683 uint64_t obj, ddobj, prevobj = 0;
684 boolean_t rmorigin;
685
686 ASSERT3U(ds->ds_phys->ds_num_children, <=, 1);
687 ASSERT(ds->ds_prev == NULL ||
688 ds->ds_prev->ds_phys->ds_next_snap_obj != ds->ds_object);
689 ASSERT3U(ds->ds_phys->ds_bp.blk_birth, <=, tx->tx_txg);
690 ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
691
692 /* We need to log before removing it from the namespace. */
693 spa_history_log_internal_ds(ds, "destroy", tx, "");
694
695 rmorigin = (dsl_dir_is_clone(ds->ds_dir) &&
708 dsl_scan_ds_destroyed(ds, tx);
709
710 obj = ds->ds_object;
711
712 if (ds->ds_phys->ds_prev_snap_obj != 0) {
713 /* This is a clone */
714 ASSERT(ds->ds_prev != NULL);
715 ASSERT3U(ds->ds_prev->ds_phys->ds_next_snap_obj, !=, obj);
716 ASSERT0(ds->ds_phys->ds_next_snap_obj);
717
718 dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
719 if (ds->ds_prev->ds_phys->ds_next_clones_obj != 0) {
720 dsl_dataset_remove_from_next_clones(ds->ds_prev,
721 obj, tx);
722 }
723
724 ASSERT3U(ds->ds_prev->ds_phys->ds_num_children, >, 1);
725 ds->ds_prev->ds_phys->ds_num_children--;
726 }
727
728 /*
729 * Destroy the deadlist. Unless it's a clone, the
730 * deadlist should be empty. (If it's a clone, it's
731 * safe to ignore the deadlist contents.)
732 */
733 dsl_deadlist_close(&ds->ds_deadlist);
734 dsl_deadlist_free(mos, ds->ds_phys->ds_deadlist_obj, tx);
735 dmu_buf_will_dirty(ds->ds_dbuf, tx);
736 ds->ds_phys->ds_deadlist_obj = 0;
737
738 objset_t *os;
739 VERIFY0(dmu_objset_from_ds(ds, &os));
740
741 if (!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_ASYNC_DESTROY)) {
742 old_synchronous_dataset_destroy(ds, tx);
743 } else {
744 /*
745 * Move the bptree into the pool's list of trees to
746 * clean up and update space accounting information.
747 */
748 uint64_t used, comp, uncomp;
749
750 zil_destroy_sync(dmu_objset_zil(os), tx);
751
752 if (!spa_feature_is_active(dp->dp_spa,
753 SPA_FEATURE_ASYNC_DESTROY)) {
754 dsl_scan_t *scn = dp->dp_scan;
755 spa_feature_incr(dp->dp_spa, SPA_FEATURE_ASYNC_DESTROY,
756 tx);
757 dp->dp_bptree_obj = bptree_alloc(mos, tx);
758 VERIFY0(zap_add(mos,
759 DMU_POOL_DIRECTORY_OBJECT,
760 DMU_POOL_BPTREE_OBJ, sizeof (uint64_t), 1,
761 &dp->dp_bptree_obj, tx));
762 ASSERT(!scn->scn_async_destroying);
763 scn->scn_async_destroying = B_TRUE;
764 }
765
766 used = ds->ds_dir->dd_phys->dd_used_bytes;
767 comp = ds->ds_dir->dd_phys->dd_compressed_bytes;
768 uncomp = ds->ds_dir->dd_phys->dd_uncompressed_bytes;
769
770 ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) ||
771 ds->ds_phys->ds_unique_bytes == used);
772
773 bptree_add(mos, dp->dp_bptree_obj,
774 &ds->ds_phys->ds_bp, ds->ds_phys->ds_prev_snap_txg,
775 used, comp, uncomp, tx);
776 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD,
796 */
797 if (ds->ds_objset) {
798 dmu_objset_evict(ds->ds_objset);
799 ds->ds_objset = NULL;
800 }
801
802 /* Erase the link in the dir */
803 dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx);
804 ds->ds_dir->dd_phys->dd_head_dataset_obj = 0;
805 ddobj = ds->ds_dir->dd_object;
806 ASSERT(ds->ds_phys->ds_snapnames_zapobj != 0);
807 VERIFY0(zap_destroy(mos, ds->ds_phys->ds_snapnames_zapobj, tx));
808
809 spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
810
811 ASSERT0(ds->ds_phys->ds_next_clones_obj);
812 ASSERT0(ds->ds_phys->ds_props_obj);
813 ASSERT0(ds->ds_phys->ds_userrefs_obj);
814 dsl_dir_rele(ds->ds_dir, ds);
815 ds->ds_dir = NULL;
816 dmu_object_free_zapified(mos, obj, tx);
817
818 dsl_dir_destroy_sync(ddobj, tx);
819
820 if (rmorigin) {
821 dsl_dataset_t *prev;
822 VERIFY0(dsl_dataset_hold_obj(dp, prevobj, FTAG, &prev));
823 dsl_destroy_snapshot_sync_impl(prev, B_FALSE, tx);
824 dsl_dataset_rele(prev, FTAG);
825 }
826 }
827
828 static void
829 dsl_destroy_head_sync(void *arg, dmu_tx_t *tx)
830 {
831 dsl_destroy_head_arg_t *ddha = arg;
832 dsl_pool_t *dp = dmu_tx_pool(tx);
833 dsl_dataset_t *ds;
834
835 VERIFY0(dsl_dataset_hold(dp, ddha->ddha_name, FTAG, &ds));
836 dsl_destroy_head_sync_impl(ds, tx);
852
853 spa_history_log_internal_ds(ds, "destroy begin", tx, "");
854 dsl_dataset_rele(ds, FTAG);
855 }
856
857 int
858 dsl_destroy_head(const char *name)
859 {
860 dsl_destroy_head_arg_t ddha;
861 int error;
862 spa_t *spa;
863 boolean_t isenabled;
864
865 #ifdef _KERNEL
866 zfs_destroy_unmount_origin(name);
867 #endif
868
869 error = spa_open(name, &spa, FTAG);
870 if (error != 0)
871 return (error);
872 isenabled = spa_feature_is_enabled(spa, SPA_FEATURE_ASYNC_DESTROY);
873 spa_close(spa, FTAG);
874
875 ddha.ddha_name = name;
876
877 if (!isenabled) {
878 objset_t *os;
879
880 error = dsl_sync_task(name, dsl_destroy_head_check,
881 dsl_destroy_head_begin_sync, &ddha, 0);
882 if (error != 0)
883 return (error);
884
885 /*
886 * Head deletion is processed in one txg on old pools;
887 * remove the objects from open context so that the txg sync
888 * is not too long.
889 */
890 error = dmu_objset_own(name, DMU_OST_ANY, B_FALSE, FTAG, &os);
891 if (error == 0) {
892 uint64_t prev_snap_txg =
|