4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2012 by Delphix. All rights reserved.
24 */
25
26 /* Portions Copyright 2010 Robert Milkowski */
27
28 #include <sys/cred.h>
29 #include <sys/zfs_context.h>
30 #include <sys/dmu_objset.h>
31 #include <sys/dsl_dir.h>
32 #include <sys/dsl_dataset.h>
33 #include <sys/dsl_prop.h>
34 #include <sys/dsl_pool.h>
35 #include <sys/dsl_synctask.h>
36 #include <sys/dsl_deleg.h>
37 #include <sys/dnode.h>
38 #include <sys/dbuf.h>
39 #include <sys/zvol.h>
40 #include <sys/dmu_tx.h>
41 #include <sys/zap.h>
42 #include <sys/zil.h>
43 #include <sys/dmu_impl.h>
673 struct oscarg *oa = arg2;
674 objset_t *mos = dd->dd_pool->dp_meta_objset;
675 int err;
676 uint64_t ddobj;
677
678 err = zap_lookup(mos, dd->dd_phys->dd_child_dir_zapobj,
679 oa->lastname, sizeof (uint64_t), 1, &ddobj);
680 if (err != ENOENT)
681 return (err ? err : EEXIST);
682
683 if (oa->clone_origin != NULL) {
684 /* You can't clone across pools. */
685 if (oa->clone_origin->ds_dir->dd_pool != dd->dd_pool)
686 return (EXDEV);
687
688 /* You can only clone snapshots, not the head datasets. */
689 if (!dsl_dataset_is_snapshot(oa->clone_origin))
690 return (EINVAL);
691 }
692
693 return (0);
694 }
695
696 static void
697 dmu_objset_create_sync(void *arg1, void *arg2, dmu_tx_t *tx)
698 {
699 dsl_dir_t *dd = arg1;
700 spa_t *spa = dd->dd_pool->dp_spa;
701 struct oscarg *oa = arg2;
702 uint64_t obj;
703 dsl_dataset_t *ds;
704 blkptr_t *bp;
705
706 ASSERT(dmu_tx_is_syncing(tx));
707
708 obj = dsl_dataset_create_sync(dd, oa->lastname,
709 oa->clone_origin, oa->flags, oa->cr, tx);
710
711 VERIFY3U(0, ==, dsl_dataset_hold_obj(dd->dd_pool, obj, FTAG, &ds));
712 bp = dsl_dataset_get_blkptr(ds);
713 if (BP_IS_HOLE(bp)) {
714 objset_t *os =
715 dmu_objset_create_impl(spa, ds, bp, oa->type, tx);
716
717 if (oa->userfunc)
718 oa->userfunc(os, oa->userarg, oa->cr, tx);
719 }
720
721 if (oa->clone_origin == NULL) {
722 spa_history_log_internal_ds(ds, "create", tx, "");
723 } else {
724 char namebuf[MAXNAMELEN];
725 dsl_dataset_name(oa->clone_origin, namebuf);
726 spa_history_log_internal_ds(ds, "clone", tx,
727 "origin=%s (%llu)", namebuf, oa->clone_origin->ds_object);
801 }
802
803 return (error);
804 }
805
806 typedef struct snapallarg {
807 dsl_sync_task_group_t *saa_dstg;
808 boolean_t saa_needsuspend;
809 nvlist_t *saa_props;
810
811 /* the following are used only if 'temporary' is set: */
812 boolean_t saa_temporary;
813 const char *saa_htag;
814 struct dsl_ds_holdarg *saa_ha;
815 dsl_dataset_t *saa_newds;
816 } snapallarg_t;
817
818 typedef struct snaponearg {
819 const char *soa_longname; /* long snap name */
820 const char *soa_snapname; /* short snap name */
821 snapallarg_t *soa_saa;
822 } snaponearg_t;
823
824 static int
825 snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
826 {
827 objset_t *os = arg1;
828 snaponearg_t *soa = arg2;
829 snapallarg_t *saa = soa->soa_saa;
830 int error;
831
832 /* The props have already been checked by zfs_check_userprops(). */
833
834 error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
835 soa->soa_snapname, tx);
836 if (error)
837 return (error);
838
839 if (saa->saa_temporary) {
840 /*
841 * Ideally we would just call
842 * dsl_dataset_user_hold_check() and
843 * dsl_dataset_destroy_check() here. However the
844 * dataset we want to hold and destroy is the snapshot
845 * that we just confirmed we can create, but it won't
846 * exist until after these checks are run. Do any
847 * checks we can here and if more checks are added to
848 * those routines in the future, similar checks may be
849 * necessary here.
850 */
851 if (spa_version(os->os_spa) < SPA_VERSION_USERREFS)
852 return (ENOTSUP);
853 /*
854 * Not checking number of tags because the tag will be
855 * unique, as it will be the only tag.
880 pa.pa_props = saa->saa_props;
881 pa.pa_source = ZPROP_SRC_LOCAL;
882 dsl_props_set_sync(ds->ds_prev, &pa, tx);
883 }
884
885 if (saa->saa_temporary) {
886 struct dsl_ds_destroyarg da;
887
888 dsl_dataset_user_hold_sync(ds->ds_prev, saa->saa_ha, tx);
889 kmem_free(saa->saa_ha, sizeof (struct dsl_ds_holdarg));
890 saa->saa_ha = NULL;
891 saa->saa_newds = ds->ds_prev;
892
893 da.ds = ds->ds_prev;
894 da.defer = B_TRUE;
895 dsl_dataset_destroy_sync(&da, FTAG, tx);
896 }
897 }
898
899 static int
900 snapshot_one_impl(const char *snapname, void *arg)
901 {
902 char fsname[MAXPATHLEN];
903 snapallarg_t *saa = arg;
904 snaponearg_t *soa;
905 objset_t *os;
906 int err;
907
908 (void) strlcpy(fsname, snapname, sizeof (fsname));
909 strchr(fsname, '@')[0] = '\0';
910
911 err = dmu_objset_hold(fsname, saa, &os);
912 if (err != 0)
913 return (err);
914
915 /*
916 * If the objset is in an inconsistent state (eg, in the process
917 * of being destroyed), don't snapshot it.
918 */
919 if (os->os_dsl_dataset->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) {
920 dmu_objset_rele(os, saa);
921 return (EBUSY);
922 }
923
924 if (saa->saa_needsuspend) {
925 err = zil_suspend(dmu_objset_zil(os));
926 if (err) {
927 dmu_objset_rele(os, saa);
928 return (err);
929 }
930 }
931
932 soa = kmem_zalloc(sizeof (*soa), KM_SLEEP);
933 soa->soa_saa = saa;
934 soa->soa_longname = snapname;
935 soa->soa_snapname = strchr(snapname, '@') + 1;
936
937 dsl_sync_task_create(saa->saa_dstg, snapshot_check, snapshot_sync,
938 os, soa, 3);
939
940 return (0);
941 }
942
943 /*
944 * The snapshots must all be in the same pool.
945 */
946 int
947 dmu_objset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
948 {
949 dsl_sync_task_t *dst;
950 snapallarg_t saa = { 0 };
951 spa_t *spa;
952 int rv = 0;
953 int err;
954 nvpair_t *pair;
955
956 pair = nvlist_next_nvpair(snaps, NULL);
957 if (pair == NULL)
958 return (0);
959
960 err = spa_open(nvpair_name(pair), &spa, FTAG);
961 if (err)
962 return (err);
963 saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
964 saa.saa_props = props;
965 saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
966
967 for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
968 pair = nvlist_next_nvpair(snaps, pair)) {
969 err = snapshot_one_impl(nvpair_name(pair), &saa);
970 if (err != 0) {
971 if (errors != NULL) {
972 fnvlist_add_int32(errors,
973 nvpair_name(pair), err);
974 }
975 rv = err;
976 }
977 }
978
979 /*
980 * If any call to snapshot_one_impl() failed, don't execute the
981 * sync task. The error handling code below will clean up the
982 * snaponearg_t from any successful calls to
983 * snapshot_one_impl().
984 */
985 if (rv == 0)
986 err = dsl_sync_task_group_wait(saa.saa_dstg);
987 if (err != 0)
988 rv = err;
989
990 for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
991 dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
992 objset_t *os = dst->dst_arg1;
993 snaponearg_t *soa = dst->dst_arg2;
994 if (dst->dst_err != 0) {
995 if (errors != NULL) {
996 fnvlist_add_int32(errors,
997 soa->soa_longname, dst->dst_err);
998 }
1033 minor_t minor;
1034 int err;
1035
1036 err = spa_open(snapname, &spa, FTAG);
1037 if (err)
1038 return (err);
1039 saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
1040 saa.saa_htag = tag;
1041 saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
1042 saa.saa_temporary = B_TRUE;
1043
1044 if (cleanup_fd < 0) {
1045 spa_close(spa, FTAG);
1046 return (EINVAL);
1047 }
1048 if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
1049 spa_close(spa, FTAG);
1050 return (err);
1051 }
1052
1053 err = snapshot_one_impl(snapname, &saa);
1054
1055 if (err == 0)
1056 err = dsl_sync_task_group_wait(saa.saa_dstg);
1057
1058 for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
1059 dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
1060 objset_t *os = dst->dst_arg1;
1061 dsl_register_onexit_hold_cleanup(saa.saa_newds, tag, minor);
1062 if (saa.saa_needsuspend)
1063 zil_resume(dmu_objset_zil(os));
1064 dmu_objset_rele(os, &saa);
1065 }
1066
1067 zfs_onexit_fd_rele(cleanup_fd);
1068 dsl_sync_task_group_destroy(saa.saa_dstg);
1069 spa_close(spa, FTAG);
1070 return (err);
1071 }
1072
1073
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2012 by Delphix. All rights reserved.
24 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
25 */
26
27 /* Portions Copyright 2010 Robert Milkowski */
28
29 #include <sys/cred.h>
30 #include <sys/zfs_context.h>
31 #include <sys/dmu_objset.h>
32 #include <sys/dsl_dir.h>
33 #include <sys/dsl_dataset.h>
34 #include <sys/dsl_prop.h>
35 #include <sys/dsl_pool.h>
36 #include <sys/dsl_synctask.h>
37 #include <sys/dsl_deleg.h>
38 #include <sys/dnode.h>
39 #include <sys/dbuf.h>
40 #include <sys/zvol.h>
41 #include <sys/dmu_tx.h>
42 #include <sys/zap.h>
43 #include <sys/zil.h>
44 #include <sys/dmu_impl.h>
674 struct oscarg *oa = arg2;
675 objset_t *mos = dd->dd_pool->dp_meta_objset;
676 int err;
677 uint64_t ddobj;
678
679 err = zap_lookup(mos, dd->dd_phys->dd_child_dir_zapobj,
680 oa->lastname, sizeof (uint64_t), 1, &ddobj);
681 if (err != ENOENT)
682 return (err ? err : EEXIST);
683
684 if (oa->clone_origin != NULL) {
685 /* You can't clone across pools. */
686 if (oa->clone_origin->ds_dir->dd_pool != dd->dd_pool)
687 return (EXDEV);
688
689 /* You can only clone snapshots, not the head datasets. */
690 if (!dsl_dataset_is_snapshot(oa->clone_origin))
691 return (EINVAL);
692 }
693
694 return (dsl_dir_fscount_check(dd, 1, NULL));
695 }
696
697 static void
698 dmu_objset_create_sync(void *arg1, void *arg2, dmu_tx_t *tx)
699 {
700 dsl_dir_t *dd = arg1;
701 spa_t *spa = dd->dd_pool->dp_spa;
702 struct oscarg *oa = arg2;
703 uint64_t obj;
704 dsl_dataset_t *ds;
705 blkptr_t *bp;
706
707 ASSERT(dmu_tx_is_syncing(tx));
708
709 dsl_dir_fscount_adjust(dd, tx, 1, B_TRUE, B_TRUE);
710
711 obj = dsl_dataset_create_sync(dd, oa->lastname,
712 oa->clone_origin, oa->flags, oa->cr, tx);
713
714 VERIFY3U(0, ==, dsl_dataset_hold_obj(dd->dd_pool, obj, FTAG, &ds));
715 bp = dsl_dataset_get_blkptr(ds);
716 if (BP_IS_HOLE(bp)) {
717 objset_t *os =
718 dmu_objset_create_impl(spa, ds, bp, oa->type, tx);
719
720 if (oa->userfunc)
721 oa->userfunc(os, oa->userarg, oa->cr, tx);
722 }
723
724 if (oa->clone_origin == NULL) {
725 spa_history_log_internal_ds(ds, "create", tx, "");
726 } else {
727 char namebuf[MAXNAMELEN];
728 dsl_dataset_name(oa->clone_origin, namebuf);
729 spa_history_log_internal_ds(ds, "clone", tx,
730 "origin=%s (%llu)", namebuf, oa->clone_origin->ds_object);
804 }
805
806 return (error);
807 }
808
809 typedef struct snapallarg {
810 dsl_sync_task_group_t *saa_dstg;
811 boolean_t saa_needsuspend;
812 nvlist_t *saa_props;
813
814 /* the following are used only if 'temporary' is set: */
815 boolean_t saa_temporary;
816 const char *saa_htag;
817 struct dsl_ds_holdarg *saa_ha;
818 dsl_dataset_t *saa_newds;
819 } snapallarg_t;
820
821 typedef struct snaponearg {
822 const char *soa_longname; /* long snap name */
823 const char *soa_snapname; /* short snap name */
824 uint64_t soa_tot_cnt;
825 snapallarg_t *soa_saa;
826 } snaponearg_t;
827
828 static int
829 snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
830 {
831 objset_t *os = arg1;
832 snaponearg_t *soa = arg2;
833 snapallarg_t *saa = soa->soa_saa;
834 int error;
835
836 /* The props have already been checked by zfs_check_userprops(). */
837
838 error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
839 soa->soa_snapname, soa->soa_tot_cnt, tx);
840 if (error)
841 return (error);
842
843 if (saa->saa_temporary) {
844 /*
845 * Ideally we would just call
846 * dsl_dataset_user_hold_check() and
847 * dsl_dataset_destroy_check() here. However the
848 * dataset we want to hold and destroy is the snapshot
849 * that we just confirmed we can create, but it won't
850 * exist until after these checks are run. Do any
851 * checks we can here and if more checks are added to
852 * those routines in the future, similar checks may be
853 * necessary here.
854 */
855 if (spa_version(os->os_spa) < SPA_VERSION_USERREFS)
856 return (ENOTSUP);
857 /*
858 * Not checking number of tags because the tag will be
859 * unique, as it will be the only tag.
884 pa.pa_props = saa->saa_props;
885 pa.pa_source = ZPROP_SRC_LOCAL;
886 dsl_props_set_sync(ds->ds_prev, &pa, tx);
887 }
888
889 if (saa->saa_temporary) {
890 struct dsl_ds_destroyarg da;
891
892 dsl_dataset_user_hold_sync(ds->ds_prev, saa->saa_ha, tx);
893 kmem_free(saa->saa_ha, sizeof (struct dsl_ds_holdarg));
894 saa->saa_ha = NULL;
895 saa->saa_newds = ds->ds_prev;
896
897 da.ds = ds->ds_prev;
898 da.defer = B_TRUE;
899 dsl_dataset_destroy_sync(&da, FTAG, tx);
900 }
901 }
902
903 static int
904 snapshot_one_impl(const char *snapname, void *arg, uint64_t cnt)
905 {
906 char fsname[MAXPATHLEN];
907 snapallarg_t *saa = arg;
908 snaponearg_t *soa;
909 objset_t *os;
910 int err;
911
912 (void) strlcpy(fsname, snapname, sizeof (fsname));
913 strchr(fsname, '@')[0] = '\0';
914
915 err = dmu_objset_hold(fsname, saa, &os);
916 if (err != 0)
917 return (err);
918
919 /*
920 * If the objset is in an inconsistent state (eg, in the process
921 * of being destroyed), don't snapshot it.
922 */
923 if (os->os_dsl_dataset->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) {
924 dmu_objset_rele(os, saa);
925 return (EBUSY);
926 }
927
928 if (saa->saa_needsuspend) {
929 err = zil_suspend(dmu_objset_zil(os));
930 if (err) {
931 dmu_objset_rele(os, saa);
932 return (err);
933 }
934 }
935
936 soa = kmem_zalloc(sizeof (*soa), KM_SLEEP);
937 soa->soa_saa = saa;
938 soa->soa_longname = snapname;
939 soa->soa_snapname = strchr(snapname, '@') + 1;
940 soa->soa_tot_cnt = cnt;
941
942 dsl_sync_task_create(saa->saa_dstg, snapshot_check, snapshot_sync,
943 os, soa, 3);
944
945 return (0);
946 }
947
948 /*
949 * The snapshots must all be in the same pool.
950 */
951 int
952 dmu_objset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
953 {
954 dsl_sync_task_t *dst;
955 snapallarg_t saa = { 0 };
956 spa_t *spa;
957 int rv = 0;
958 int err;
959 nvpair_t *pair;
960 nvlist_t *cnt_track = NULL;
961 nvpair_t *pp;
962 char *pdelim;
963 uint64_t *pv;
964 char nm[MAXPATHLEN];
965
966 pair = nvlist_next_nvpair(snaps, NULL);
967 if (pair == NULL)
968 return (0);
969
970 err = spa_open(nvpair_name(pair), &spa, FTAG);
971 if (err)
972 return (err);
973 saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
974 saa.saa_props = props;
975 saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
976
977 /*
978 * Pre-compute how many total new snapshots will be created for each
979 * level in the tree and below. This is needed for validating the
980 * snapshot limit when taking a recursive snapshot.
981 *
982 * The problem is that the counts are not actually adjusted when
983 * we are checking, only when we finally sync. For a single snapshot,
984 * this is easy, the count will increase by 1 at each node up the tree,
985 * but its more complicated for recursive snapshots. Since we are
986 * validating each snapshot independently we need to be sure that we
987 * are validating the complete count for the entire set of snapshots.
988 * We do this by rolling up the counts for each component of the name
989 * into an nvlist then we'll use that count in the validation of each
990 * individual snapshot.
991 *
992 * We validated the snapshot names in zfs_ioc_snapshot so we know they
993 * have a '@'.
994 */
995 VERIFY(nvlist_alloc(&cnt_track, NV_UNIQUE_NAME, KM_SLEEP) == 0);
996
997 for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
998 pair = nvlist_next_nvpair(snaps, pair)) {
999 (void) strlcpy(nm, nvpair_name(pair), sizeof (nm));
1000 pdelim = strchr(nm, '@');
1001 *pdelim = '\0';
1002
1003 do {
1004 if (nvlist_lookup_nvpair(cnt_track, nm, &pp) != 0) {
1005 /* add to list */
1006 nvlist_add_uint64(cnt_track, nm, 1);
1007 } else {
1008 /* update existing entry */
1009 pv = (uint64_t *)NVP_VALUE(pp);
1010 *pv += 1;
1011 }
1012
1013 pdelim = strrchr(nm, '/');
1014 if (pdelim != NULL)
1015 *pdelim = '\0';
1016 } while (pdelim != NULL);
1017 }
1018
1019 /*
1020 * We've calculated the counts, now validate.
1021 */
1022 for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
1023 pair = nvlist_next_nvpair(snaps, pair)) {
1024 (void) strlcpy(nm, nvpair_name(pair), sizeof (nm));
1025 pdelim = strchr(nm, '@');
1026 *pdelim = '\0';
1027
1028 VERIFY(nvlist_lookup_nvpair(cnt_track, nm, &pp) == 0);
1029
1030 pv = (uint64_t *)NVP_VALUE(pp);
1031 err = snapshot_one_impl(nvpair_name(pair), &saa, *pv);
1032 if (err != 0) {
1033 if (errors != NULL) {
1034 fnvlist_add_int32(errors,
1035 nvpair_name(pair), err);
1036 }
1037 rv = err;
1038 }
1039 }
1040
1041 nvlist_free(cnt_track);
1042
1043 /*
1044 * If any call to snapshot_one_impl() failed, don't execute the
1045 * sync task. The error handling code below will clean up the
1046 * snaponearg_t from any successful calls to
1047 * snapshot_one_impl().
1048 */
1049 if (rv == 0)
1050 err = dsl_sync_task_group_wait(saa.saa_dstg);
1051 if (err != 0)
1052 rv = err;
1053
1054 for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
1055 dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
1056 objset_t *os = dst->dst_arg1;
1057 snaponearg_t *soa = dst->dst_arg2;
1058 if (dst->dst_err != 0) {
1059 if (errors != NULL) {
1060 fnvlist_add_int32(errors,
1061 soa->soa_longname, dst->dst_err);
1062 }
1097 minor_t minor;
1098 int err;
1099
1100 err = spa_open(snapname, &spa, FTAG);
1101 if (err)
1102 return (err);
1103 saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
1104 saa.saa_htag = tag;
1105 saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
1106 saa.saa_temporary = B_TRUE;
1107
1108 if (cleanup_fd < 0) {
1109 spa_close(spa, FTAG);
1110 return (EINVAL);
1111 }
1112 if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
1113 spa_close(spa, FTAG);
1114 return (err);
1115 }
1116
1117 err = snapshot_one_impl(snapname, &saa, 1);
1118
1119 if (err == 0)
1120 err = dsl_sync_task_group_wait(saa.saa_dstg);
1121
1122 for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
1123 dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
1124 objset_t *os = dst->dst_arg1;
1125 dsl_register_onexit_hold_cleanup(saa.saa_newds, tag, minor);
1126 if (saa.saa_needsuspend)
1127 zil_resume(dmu_objset_zil(os));
1128 dmu_objset_rele(os, &saa);
1129 }
1130
1131 zfs_onexit_fd_rele(cleanup_fd);
1132 dsl_sync_task_group_destroy(saa.saa_dstg);
1133 spa_close(spa, FTAG);
1134 return (err);
1135 }
1136
1137
|