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);


 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