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);
790
791 int
792 dmu_objset_destroy(const char *name, boolean_t defer)
793 {
794 dsl_dataset_t *ds;
795 int error;
796
797 error = dsl_dataset_own(name, B_TRUE, FTAG, &ds);
798 if (error == 0) {
799 error = dsl_dataset_destroy(ds, FTAG, defer);
800 /* dsl_dataset_destroy() closes the ds. */
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, oa->cr));
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);
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);
793
794 int
795 dmu_objset_destroy(const char *name, boolean_t defer)
796 {
797 dsl_dataset_t *ds;
798 int error;
799
800 error = dsl_dataset_own(name, B_TRUE, FTAG, &ds);
801 if (error == 0) {
802 error = dsl_dataset_destroy(ds, FTAG, defer);
803 /* dsl_dataset_destroy() closes the ds. */
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 cred_t *saa_cr;
814
815 /* the following are used only if 'temporary' is set: */
816 boolean_t saa_temporary;
817 const char *saa_htag;
818 struct dsl_ds_holdarg *saa_ha;
819 dsl_dataset_t *saa_newds;
820 } snapallarg_t;
821
822 typedef struct snaponearg {
823 const char *soa_longname; /* long snap name */
824 const char *soa_snapname; /* short snap name */
825 uint64_t soa_tot_cnt;
826 snapallarg_t *soa_saa;
827 } snaponearg_t;
828
829 static int
830 snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
831 {
832 objset_t *os = arg1;
833 snaponearg_t *soa = arg2;
834 snapallarg_t *saa = soa->soa_saa;
835 int error;
836
837 /* The props have already been checked by zfs_check_userprops(). */
838
839 error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
840 soa->soa_snapname, soa->soa_tot_cnt, tx, saa->saa_cr);
841 if (error)
842 return (error);
843
844 if (saa->saa_temporary) {
845 /*
846 * Ideally we would just call
847 * dsl_dataset_user_hold_check() and
848 * dsl_dataset_destroy_check() here. However the
849 * dataset we want to hold and destroy is the snapshot
850 * that we just confirmed we can create, but it won't
851 * exist until after these checks are run. Do any
852 * checks we can here and if more checks are added to
853 * those routines in the future, similar checks may be
854 * necessary here.
855 */
856 if (spa_version(os->os_spa) < SPA_VERSION_USERREFS)
857 return (ENOTSUP);
858 /*
859 * Not checking number of tags because the tag will be
860 * unique, as it will be the only tag.
885 pa.pa_props = saa->saa_props;
886 pa.pa_source = ZPROP_SRC_LOCAL;
887 dsl_props_set_sync(ds->ds_prev, &pa, tx);
888 }
889
890 if (saa->saa_temporary) {
891 struct dsl_ds_destroyarg da;
892
893 dsl_dataset_user_hold_sync(ds->ds_prev, saa->saa_ha, tx);
894 kmem_free(saa->saa_ha, sizeof (struct dsl_ds_holdarg));
895 saa->saa_ha = NULL;
896 saa->saa_newds = ds->ds_prev;
897
898 da.ds = ds->ds_prev;
899 da.defer = B_TRUE;
900 dsl_dataset_destroy_sync(&da, FTAG, tx);
901 }
902 }
903
904 static int
905 snapshot_one_impl(const char *snapname, void *arg, uint64_t cnt)
906 {
907 char fsname[MAXPATHLEN];
908 snapallarg_t *saa = arg;
909 snaponearg_t *soa;
910 objset_t *os;
911 int err;
912
913 (void) strlcpy(fsname, snapname, sizeof (fsname));
914 strchr(fsname, '@')[0] = '\0';
915
916 err = dmu_objset_hold(fsname, saa, &os);
917 if (err != 0)
918 return (err);
919
920 /*
921 * If the objset is in an inconsistent state (eg, in the process
922 * of being destroyed), don't snapshot it.
923 */
924 if (os->os_dsl_dataset->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) {
925 dmu_objset_rele(os, saa);
926 return (EBUSY);
927 }
928
929 if (saa->saa_needsuspend) {
930 err = zil_suspend(dmu_objset_zil(os));
931 if (err) {
932 dmu_objset_rele(os, saa);
933 return (err);
934 }
935 }
936
937 soa = kmem_zalloc(sizeof (*soa), KM_SLEEP);
938 soa->soa_saa = saa;
939 soa->soa_longname = snapname;
940 soa->soa_snapname = strchr(snapname, '@') + 1;
941 soa->soa_tot_cnt = cnt;
942
943 dsl_sync_task_create(saa->saa_dstg, snapshot_check, snapshot_sync,
944 os, soa, 3);
945
946 return (0);
947 }
948
949 /*
950 * The snapshots must all be in the same pool.
951 */
952 int
953 dmu_objset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
954 {
955 dsl_sync_task_t *dst;
956 snapallarg_t saa = { 0 };
957 spa_t *spa;
958 int rv = 0;
959 int err;
960 nvpair_t *pair;
961 nvlist_t *cnt_track = NULL;
962 char *pdelim;
963 uint64_t val;
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 saa.saa_cr = CRED();
977
978 /*
979 * Pre-compute how many total new snapshots will be created for each
980 * level in the tree and below. This is needed for validating the
981 * snapshot limit when taking a recursive snapshot.
982 *
983 * The problem is that the counts are not actually adjusted when
984 * we are checking, only when we finally sync. For a single snapshot,
985 * this is easy, the count will increase by 1 at each node up the tree,
986 * but its more complicated for recursive snapshots. Since we are
987 * validating each snapshot independently we need to be sure that we
988 * are validating the complete count for the entire set of snapshots.
989 * We do this by rolling up the counts for each component of the name
990 * into an nvlist then we'll use that count in the validation of each
991 * individual snapshot.
992 *
993 * We validated the snapshot names in zfs_ioc_snapshot so we know they
994 * have a '@'.
995 */
996 cnt_track = fnvlist_alloc();
997
998 for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
999 pair = nvlist_next_nvpair(snaps, pair)) {
1000 (void) strlcpy(nm, nvpair_name(pair), sizeof (nm));
1001 pdelim = strchr(nm, '@');
1002 *pdelim = '\0';
1003
1004 do {
1005 if (nvlist_lookup_uint64(cnt_track, nm, &val) == 0) {
1006 /* update existing entry */
1007 fnvlist_add_uint64(cnt_track, nm, val + 1);
1008 } else {
1009 /* add to list */
1010 fnvlist_add_uint64(cnt_track, nm, 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 val = fnvlist_lookup_uint64(cnt_track, nm);
1029 err = snapshot_one_impl(nvpair_name(pair), &saa, val);
1030 if (err != 0) {
1031 if (errors != NULL) {
1032 fnvlist_add_int32(errors,
1033 nvpair_name(pair), err);
1034 }
1035 rv = err;
1036 }
1037 }
1038
1039 nvlist_free(cnt_track);
1040
1041 /*
1042 * If any call to snapshot_one_impl() failed, don't execute the
1043 * sync task. The error handling code below will clean up the
1044 * snaponearg_t from any successful calls to
1045 * snapshot_one_impl().
1046 */
1047 if (rv == 0)
1048 err = dsl_sync_task_group_wait(saa.saa_dstg);
1049 if (err != 0)
1050 rv = err;
1051
1052 for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
1053 dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
1054 objset_t *os = dst->dst_arg1;
1055 snaponearg_t *soa = dst->dst_arg2;
1056 if (dst->dst_err != 0) {
1057 if (errors != NULL) {
1058 fnvlist_add_int32(errors,
1059 soa->soa_longname, dst->dst_err);
1060 }
1095 minor_t minor;
1096 int err;
1097
1098 err = spa_open(snapname, &spa, FTAG);
1099 if (err)
1100 return (err);
1101 saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
1102 saa.saa_htag = tag;
1103 saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
1104 saa.saa_temporary = B_TRUE;
1105
1106 if (cleanup_fd < 0) {
1107 spa_close(spa, FTAG);
1108 return (EINVAL);
1109 }
1110 if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
1111 spa_close(spa, FTAG);
1112 return (err);
1113 }
1114
1115 err = snapshot_one_impl(snapname, &saa, 1);
1116
1117 if (err == 0)
1118 err = dsl_sync_task_group_wait(saa.saa_dstg);
1119
1120 for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
1121 dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
1122 objset_t *os = dst->dst_arg1;
1123 dsl_register_onexit_hold_cleanup(saa.saa_newds, tag, minor);
1124 if (saa.saa_needsuspend)
1125 zil_resume(dmu_objset_zil(os));
1126 dmu_objset_rele(os, &saa);
1127 }
1128
1129 zfs_onexit_fd_rele(cleanup_fd);
1130 dsl_sync_task_group_destroy(saa.saa_dstg);
1131 spa_close(spa, FTAG);
1132 return (err);
1133 }
1134
1135
|