Print this page
OS-1566 filesystem limits for ZFS datasets


   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