Print this page
2882 implement libzfs_core
2883 changing "canmount" property to "on" should not always remount dataset
2900 "zfs snapshot" should be able to create multiple, arbitrary snapshots at once
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Chris Siden <christopher.siden@delphix.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Bill Pijewski <wdp@joyent.com>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>


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