3 *
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 */
24
25 /* Portions Copyright 2010 Robert Milkowski */
26
27 #include <sys/cred.h>
28 #include <sys/zfs_context.h>
29 #include <sys/dmu_objset.h>
30 #include <sys/dsl_dir.h>
31 #include <sys/dsl_dataset.h>
32 #include <sys/dsl_prop.h>
33 #include <sys/dsl_pool.h>
34 #include <sys/dsl_synctask.h>
35 #include <sys/dsl_deleg.h>
36 #include <sys/dnode.h>
37 #include <sys/dbuf.h>
38 #include <sys/zvol.h>
39 #include <sys/dmu_tx.h>
40 #include <sys/zap.h>
41 #include <sys/zil.h>
42 #include <sys/dmu_impl.h>
682 if (oa->clone_origin != NULL) {
683 /* You can't clone across pools. */
684 if (oa->clone_origin->ds_dir->dd_pool != dd->dd_pool)
685 return (EXDEV);
686
687 /* You can only clone snapshots, not the head datasets. */
688 if (!dsl_dataset_is_snapshot(oa->clone_origin))
689 return (EINVAL);
690 }
691
692 return (0);
693 }
694
695 static void
696 dmu_objset_create_sync(void *arg1, void *arg2, dmu_tx_t *tx)
697 {
698 dsl_dir_t *dd = arg1;
699 spa_t *spa = dd->dd_pool->dp_spa;
700 struct oscarg *oa = arg2;
701 uint64_t obj;
702
703 ASSERT(dmu_tx_is_syncing(tx));
704
705 obj = dsl_dataset_create_sync(dd, oa->lastname,
706 oa->clone_origin, oa->flags, oa->cr, tx);
707
708 if (oa->clone_origin == NULL) {
709 dsl_pool_t *dp = dd->dd_pool;
710 dsl_dataset_t *ds;
711 blkptr_t *bp;
712 objset_t *os;
713
714 VERIFY3U(0, ==, dsl_dataset_hold_obj(dp, obj, FTAG, &ds));
715 bp = dsl_dataset_get_blkptr(ds);
716 ASSERT(BP_IS_HOLE(bp));
717
718 os = 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 dsl_dataset_rele(ds, FTAG);
723 }
724
725 spa_history_log_internal(LOG_DS_CREATE, spa, tx, "dataset = %llu", obj);
726 }
727
728 int
729 dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
730 void (*func)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx), void *arg)
731 {
732 dsl_dir_t *pdd;
733 const char *tail;
734 int err = 0;
735 struct oscarg oa = { 0 };
736
737 ASSERT(strchr(name, '@') == NULL);
738 err = dsl_dir_open(name, FTAG, &pdd, &tail);
739 if (err)
740 return (err);
741 if (tail == NULL) {
742 dsl_dir_close(pdd, FTAG);
743 return (EEXIST);
744 }
745
782 dmu_objset_create_sync, pdd, &oa, 5);
783 dsl_dir_close(pdd, FTAG);
784 return (err);
785 }
786
787 int
788 dmu_objset_destroy(const char *name, boolean_t defer)
789 {
790 dsl_dataset_t *ds;
791 int error;
792
793 error = dsl_dataset_own(name, B_TRUE, FTAG, &ds);
794 if (error == 0) {
795 error = dsl_dataset_destroy(ds, FTAG, defer);
796 /* dsl_dataset_destroy() closes the ds. */
797 }
798
799 return (error);
800 }
801
802 struct snaparg {
803 dsl_sync_task_group_t *dstg;
804 char *snapname;
805 char *htag;
806 char failed[MAXPATHLEN];
807 boolean_t recursive;
808 boolean_t needsuspend;
809 boolean_t temporary;
810 nvlist_t *props;
811 struct dsl_ds_holdarg *ha; /* only needed in the temporary case */
812 dsl_dataset_t *newds;
813 };
814
815 static int
816 snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
817 {
818 objset_t *os = arg1;
819 struct snaparg *sn = arg2;
820 int error;
821
822 /* The props have already been checked by zfs_check_userprops(). */
823
824 error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
825 sn->snapname, tx);
826 if (error)
827 return (error);
828
829 if (sn->temporary) {
830 /*
831 * Ideally we would just call
832 * dsl_dataset_user_hold_check() and
833 * dsl_dataset_destroy_check() here. However the
834 * dataset we want to hold and destroy is the snapshot
835 * that we just confirmed we can create, but it won't
836 * exist until after these checks are run. Do any
837 * checks we can here and if more checks are added to
838 * those routines in the future, similar checks may be
839 * necessary here.
840 */
841 if (spa_version(os->os_spa) < SPA_VERSION_USERREFS)
842 return (ENOTSUP);
843 /*
844 * Not checking number of tags because the tag will be
845 * unique, as it will be the only tag.
846 */
847 if (strlen(sn->htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
848 return (E2BIG);
849
850 sn->ha = kmem_alloc(sizeof (struct dsl_ds_holdarg), KM_SLEEP);
851 sn->ha->temphold = B_TRUE;
852 sn->ha->htag = sn->htag;
853 }
854 return (error);
855 }
856
857 static void
858 snapshot_sync(void *arg1, void *arg2, dmu_tx_t *tx)
859 {
860 objset_t *os = arg1;
861 dsl_dataset_t *ds = os->os_dsl_dataset;
862 struct snaparg *sn = arg2;
863
864 dsl_dataset_snapshot_sync(ds, sn->snapname, tx);
865
866 if (sn->props) {
867 dsl_props_arg_t pa;
868 pa.pa_props = sn->props;
869 pa.pa_source = ZPROP_SRC_LOCAL;
870 dsl_props_set_sync(ds->ds_prev, &pa, tx);
871 }
872
873 if (sn->temporary) {
874 struct dsl_ds_destroyarg da;
875
876 dsl_dataset_user_hold_sync(ds->ds_prev, sn->ha, tx);
877 kmem_free(sn->ha, sizeof (struct dsl_ds_holdarg));
878 sn->ha = NULL;
879 sn->newds = ds->ds_prev;
880
881 da.ds = ds->ds_prev;
882 da.defer = B_TRUE;
883 dsl_dataset_destroy_sync(&da, FTAG, tx);
884 }
885 }
886
887 static int
888 dmu_objset_snapshot_one(const char *name, void *arg)
889 {
890 struct snaparg *sn = arg;
891 objset_t *os;
892 int err;
893 char *cp;
894
895 /*
896 * If the objset starts with a '%', then ignore it unless it was
897 * explicitly named (ie, not recursive). These hidden datasets
898 * are always inconsistent, and by not opening them here, we can
899 * avoid a race with dsl_dir_destroy_check().
900 */
901 cp = strrchr(name, '/');
902 if (cp && cp[1] == '%' && sn->recursive)
903 return (0);
904
905 (void) strcpy(sn->failed, name);
906
907 /*
908 * Check permissions if we are doing a recursive snapshot. The
909 * permission checks for the starting dataset have already been
910 * performed in zfs_secpolicy_snapshot()
911 */
912 if (sn->recursive && (err = zfs_secpolicy_snapshot_perms(name, CRED())))
913 return (err);
914
915 err = dmu_objset_hold(name, sn, &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. As with %hidden
922 * datasets, we return EBUSY if this name was explicitly
923 * requested (ie, not recursive), and otherwise ignore it.
924 */
925 if (os->os_dsl_dataset->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) {
926 dmu_objset_rele(os, sn);
927 return (sn->recursive ? 0 : EBUSY);
928 }
929
930 if (sn->needsuspend) {
931 err = zil_suspend(dmu_objset_zil(os));
932 if (err) {
933 dmu_objset_rele(os, sn);
934 return (err);
935 }
936 }
937 dsl_sync_task_create(sn->dstg, snapshot_check, snapshot_sync,
938 os, sn, 3);
939
940 return (0);
941 }
942
943 int
944 dmu_objset_snapshot(char *fsname, char *snapname, char *tag,
945 nvlist_t *props, boolean_t recursive, boolean_t temporary, int cleanup_fd)
946 {
947 dsl_sync_task_t *dst;
948 struct snaparg sn;
949 spa_t *spa;
950 minor_t minor;
951 int err;
952
953 (void) strcpy(sn.failed, fsname);
954
955 err = spa_open(fsname, &spa, FTAG);
956 if (err)
957 return (err);
958
959 if (temporary) {
960 if (cleanup_fd < 0) {
961 spa_close(spa, FTAG);
962 return (EINVAL);
963 }
964 if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
965 spa_close(spa, FTAG);
966 return (err);
967 }
968 }
969
970 sn.dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
971 sn.snapname = snapname;
972 sn.htag = tag;
973 sn.props = props;
974 sn.recursive = recursive;
975 sn.needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
976 sn.temporary = temporary;
977 sn.ha = NULL;
978 sn.newds = NULL;
979
980 if (recursive) {
981 err = dmu_objset_find(fsname,
982 dmu_objset_snapshot_one, &sn, DS_FIND_CHILDREN);
983 } else {
984 err = dmu_objset_snapshot_one(fsname, &sn);
985 }
986
987 if (err == 0)
988 err = dsl_sync_task_group_wait(sn.dstg);
989
990 for (dst = list_head(&sn.dstg->dstg_tasks); dst;
991 dst = list_next(&sn.dstg->dstg_tasks, dst)) {
992 objset_t *os = dst->dst_arg1;
993 dsl_dataset_t *ds = os->os_dsl_dataset;
994 if (dst->dst_err) {
995 dsl_dataset_name(ds, sn.failed);
996 } else if (temporary) {
997 dsl_register_onexit_hold_cleanup(sn.newds, tag, minor);
998 }
999 if (sn.needsuspend)
1000 zil_resume(dmu_objset_zil(os));
1001 dmu_objset_rele(os, &sn);
1002 }
1003
1004 if (err)
1005 (void) strcpy(fsname, sn.failed);
1006 if (temporary)
1007 zfs_onexit_fd_rele(cleanup_fd);
1008 dsl_sync_task_group_destroy(sn.dstg);
1009 spa_close(spa, FTAG);
1010 return (err);
1011 }
1012
1013 static void
1014 dmu_objset_sync_dnodes(list_t *list, list_t *newlist, dmu_tx_t *tx)
1015 {
1016 dnode_t *dn;
1017
1018 while (dn = list_head(list)) {
1019 ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT);
1020 ASSERT(dn->dn_dbuf->db_data_pending);
1021 /*
1022 * Initialize dn_zio outside dnode_sync() because the
1023 * meta-dnode needs to set it ouside dnode_sync().
1024 */
1025 dn->dn_zio = dn->dn_dbuf->db_data_pending->dr_zio;
1026 ASSERT(dn->dn_zio);
1027
1028 ASSERT3U(dn->dn_nlevels, <=, DN_MAX_LEVELS);
1029 list_remove(list, dn);
1030
1031 if (newlist) {
1032 (void) dnode_add_ref(dn, newlist);
|
3 *
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>
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);
728 }
729 dsl_dataset_rele(ds, FTAG);
730 }
731
732 int
733 dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
734 void (*func)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx), void *arg)
735 {
736 dsl_dir_t *pdd;
737 const char *tail;
738 int err = 0;
739 struct oscarg oa = { 0 };
740
741 ASSERT(strchr(name, '@') == NULL);
742 err = dsl_dir_open(name, FTAG, &pdd, &tail);
743 if (err)
744 return (err);
745 if (tail == NULL) {
746 dsl_dir_close(pdd, FTAG);
747 return (EEXIST);
748 }
749
786 dmu_objset_create_sync, pdd, &oa, 5);
787 dsl_dir_close(pdd, FTAG);
788 return (err);
789 }
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.
856 */
857 if (strlen(saa->saa_htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
858 return (E2BIG);
859
860 saa->saa_ha = kmem_alloc(sizeof (struct dsl_ds_holdarg),
861 KM_SLEEP);
862 saa->saa_ha->temphold = B_TRUE;
863 saa->saa_ha->htag = saa->saa_htag;
864 }
865 return (error);
866 }
867
868 static void
869 snapshot_sync(void *arg1, void *arg2, dmu_tx_t *tx)
870 {
871 objset_t *os = arg1;
872 dsl_dataset_t *ds = os->os_dsl_dataset;
873 snaponearg_t *soa = arg2;
874 snapallarg_t *saa = soa->soa_saa;
875
876 dsl_dataset_snapshot_sync(ds, soa->soa_snapname, tx);
877
878 if (saa->saa_props != NULL) {
879 dsl_props_arg_t pa;
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 }
999 rv = dst->dst_err;
1000 }
1001
1002 if (saa.saa_needsuspend)
1003 zil_resume(dmu_objset_zil(os));
1004 dmu_objset_rele(os, &saa);
1005 kmem_free(soa, sizeof (*soa));
1006 }
1007
1008 dsl_sync_task_group_destroy(saa.saa_dstg);
1009 spa_close(spa, FTAG);
1010 return (rv);
1011 }
1012
1013 int
1014 dmu_objset_snapshot_one(const char *fsname, const char *snapname)
1015 {
1016 int err;
1017 char *longsnap = kmem_asprintf("%s@%s", fsname, snapname);
1018 nvlist_t *snaps = fnvlist_alloc();
1019
1020 fnvlist_add_boolean(snaps, longsnap);
1021 err = dmu_objset_snapshot(snaps, NULL, NULL);
1022 fnvlist_free(snaps);
1023 strfree(longsnap);
1024 return (err);
1025 }
1026
1027 int
1028 dmu_objset_snapshot_tmp(const char *snapname, const char *tag, int cleanup_fd)
1029 {
1030 dsl_sync_task_t *dst;
1031 snapallarg_t saa = { 0 };
1032 spa_t *spa;
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
1074 static void
1075 dmu_objset_sync_dnodes(list_t *list, list_t *newlist, dmu_tx_t *tx)
1076 {
1077 dnode_t *dn;
1078
1079 while (dn = list_head(list)) {
1080 ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT);
1081 ASSERT(dn->dn_dbuf->db_data_pending);
1082 /*
1083 * Initialize dn_zio outside dnode_sync() because the
1084 * meta-dnode needs to set it ouside dnode_sync().
1085 */
1086 dn->dn_zio = dn->dn_dbuf->db_data_pending->dr_zio;
1087 ASSERT(dn->dn_zio);
1088
1089 ASSERT3U(dn->dn_nlevels, <=, DN_MAX_LEVELS);
1090 list_remove(list, dn);
1091
1092 if (newlist) {
1093 (void) dnode_add_ref(dn, newlist);
|