Print this page
NEX-5366 Race between unique_insert() and unique_remove() causes ZFS fsid change
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Dan Vatca <dan.vatca@gmail.com>
6160 /usr/lib/fs/zfs/bootinstall should use bootadm
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Reviewed by: Adam Števko <adam.stevko@gmail.com>
Reviewed by: Josef Sipek <jeffpc@josefsipek.net>
Approved by: Richard Lowe <richlowe@richlowe.net>
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R (NULL is not an int)
6171 dsl_prop_unregister() slows down dataset eviction.
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
5610 zfs clone from different source and target pools produces coredump
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code


 110  * For consistency, the filesystem limit is also not enforced if the user can
 111  * modify the limit.
 112  *
 113  * The filesystem and snapshot limits are validated by dsl_fs_ss_limit_check()
 114  * and updated by dsl_fs_ss_count_adjust(). A new limit value is setup in
 115  * dsl_dir_activate_fs_ss_limit() and the counts are adjusted, if necessary, by
 116  * dsl_dir_init_fs_ss_count().
 117  *
 118  * There is a special case when we receive a filesystem that already exists. In
 119  * this case a temporary clone name of %X is created (see dmu_recv_begin). We
 120  * never update the filesystem counts for temporary clones.
 121  *
 122  * Likewise, we do not update the snapshot counts for temporary snapshots,
 123  * such as those created by zfs diff.
 124  */
 125 
 126 extern inline dsl_dir_phys_t *dsl_dir_phys(dsl_dir_t *dd);
 127 
 128 static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
 129 
 130 typedef struct ddulrt_arg {
 131         dsl_dir_t       *ddulrta_dd;
 132         uint64_t        ddlrta_txg;
 133 } ddulrt_arg_t;
 134 
 135 static void
 136 dsl_dir_evict_async(void *dbu)
 137 {
 138         dsl_dir_t *dd = dbu;
 139         dsl_pool_t *dp = dd->dd_pool;
 140         int t;
 141 
 142         dd->dd_dbuf = NULL;
 143 
 144         for (t = 0; t < TXG_SIZE; t++) {
 145                 ASSERT(!txg_list_member(&dp->dp_dirty_dirs, dd, t));
 146                 ASSERT(dd->dd_tempreserved[t] == 0);
 147                 ASSERT(dd->dd_space_towrite[t] == 0);
 148         }
 149 
 150         if (dd->dd_parent)
 151                 dsl_dir_async_rele(dd->dd_parent, dd);
 152 
 153         spa_async_close(dd->dd_pool->dp_spa, dd);
 154 


 717         if ((obj = dsl_dir_phys(dd)->dd_head_dataset_obj) == 0)
 718                 return (ENFORCE_ALWAYS);
 719 
 720         ASSERT(dsl_pool_config_held(dd->dd_pool));
 721 
 722         if (dsl_dataset_hold_obj(dd->dd_pool, obj, FTAG, &ds) != 0)
 723                 return (ENFORCE_ALWAYS);
 724 
 725         if (dsl_prop_get_ds(ds, "zoned", 8, 1, &zoned, NULL) || zoned) {
 726                 /* Only root can access zoned fs's from the GZ */
 727                 enforce = ENFORCE_ALWAYS;
 728         } else {
 729                 if (dsl_deleg_access_impl(ds, zfs_prop_to_name(prop), cr) == 0)
 730                         enforce = ENFORCE_ABOVE;
 731         }
 732 
 733         dsl_dataset_rele(ds, FTAG);
 734         return (enforce);
 735 }
 736 
 737 static void
 738 dsl_dir_update_last_remap_txg_sync(void *varg, dmu_tx_t *tx)
 739 {
 740         ddulrt_arg_t *arg = varg;
 741         uint64_t last_remap_txg;
 742         dsl_dir_t *dd = arg->ddulrta_dd;
 743         objset_t *mos = dd->dd_pool->dp_meta_objset;
 744 
 745         dsl_dir_zapify(dd, tx);
 746         if (zap_lookup(mos, dd->dd_object, DD_FIELD_LAST_REMAP_TXG,
 747             sizeof (last_remap_txg), 1, &last_remap_txg) != 0 ||
 748             last_remap_txg < arg->ddlrta_txg) {
 749                 VERIFY0(zap_update(mos, dd->dd_object, DD_FIELD_LAST_REMAP_TXG,
 750                     sizeof (arg->ddlrta_txg), 1, &arg->ddlrta_txg, tx));
 751         }
 752 }
 753 
 754 int
 755 dsl_dir_update_last_remap_txg(dsl_dir_t *dd, uint64_t txg)
 756 {
 757         ddulrt_arg_t arg;
 758         arg.ddulrta_dd = dd;
 759         arg.ddlrta_txg = txg;
 760 
 761         return (dsl_sync_task(spa_name(dd->dd_pool->dp_spa),
 762             NULL, dsl_dir_update_last_remap_txg_sync, &arg,
 763             1, ZFS_SPACE_CHECK_RESERVED));
 764 }
 765 
 766 /*
 767  * Check if adding additional child filesystem(s) would exceed any filesystem
 768  * limits or adding additional snapshot(s) would exceed any snapshot limits.
 769  * The prop argument indicates which limit to check.
 770  *
 771  * Note that all filesystem limits up to the root (or the highest
 772  * initialized) filesystem or the given ancestor must be satisfied.
 773  */
 774 int
 775 dsl_fs_ss_limit_check(dsl_dir_t *dd, uint64_t delta, zfs_prop_t prop,
 776     dsl_dir_t *ancestor, cred_t *cr)
 777 {
 778         objset_t *os = dd->dd_pool->dp_meta_objset;
 779         uint64_t limit, count;
 780         char *count_prop;
 781         enforce_res_t enforce;
 782         int err = 0;
 783 
 784         ASSERT(dsl_pool_config_held(dd->dd_pool));
 785         ASSERT(prop == ZFS_PROP_FILESYSTEM_LIMIT ||


1037                 objset_t *os = dd->dd_pool->dp_meta_objset;
1038                 return (zap_lookup(os, dd->dd_object, DD_FIELD_FILESYSTEM_COUNT,
1039                     sizeof (*count), 1, count));
1040         } else {
1041                 return (ENOENT);
1042         }
1043 }
1044 
1045 int
1046 dsl_dir_get_snapshot_count(dsl_dir_t *dd, uint64_t *count)
1047 {
1048         if (dsl_dir_is_zapified(dd)) {
1049                 objset_t *os = dd->dd_pool->dp_meta_objset;
1050                 return (zap_lookup(os, dd->dd_object, DD_FIELD_SNAPSHOT_COUNT,
1051                     sizeof (*count), 1, count));
1052         } else {
1053                 return (ENOENT);
1054         }
1055 }
1056 
1057 int
1058 dsl_dir_get_remaptxg(dsl_dir_t *dd, uint64_t *count)
1059 {
1060         if (dsl_dir_is_zapified(dd)) {
1061                 objset_t *os = dd->dd_pool->dp_meta_objset;
1062                 return (zap_lookup(os, dd->dd_object, DD_FIELD_LAST_REMAP_TXG,
1063                     sizeof (*count), 1, count));
1064         } else {
1065                 return (ENOENT);
1066         }
1067 }
1068 
1069 void
1070 dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv)
1071 {
1072         mutex_enter(&dd->dd_lock);
1073         dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_QUOTA,
1074             dsl_dir_get_quota(dd));
1075         dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_RESERVATION,
1076             dsl_dir_get_reservation(dd));
1077         dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALUSED,
1078             dsl_dir_get_logicalused(dd));
1079         if (dsl_dir_phys(dd)->dd_flags & DD_FLAG_USED_BREAKDOWN) {
1080                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDSNAP,
1081                     dsl_dir_get_usedsnap(dd));
1082                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDDS,
1083                     dsl_dir_get_usedds(dd));
1084                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDREFRESERV,
1085                     dsl_dir_get_usedrefreserv(dd));
1086                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDCHILD,
1087                     dsl_dir_get_usedchild(dd));
1088         }
1089         mutex_exit(&dd->dd_lock);
1090 
1091         uint64_t count;
1092         if (dsl_dir_get_filesystem_count(dd, &count) == 0) {
1093                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_FILESYSTEM_COUNT,
1094                     count);
1095         }
1096         if (dsl_dir_get_snapshot_count(dd, &count) == 0) {
1097                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_SNAPSHOT_COUNT,
1098                     count);
1099         }
1100         if (dsl_dir_get_remaptxg(dd, &count) == 0) {
1101                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REMAPTXG,
1102                     count);
1103         }
1104 
1105         if (dsl_dir_is_clone(dd)) {
1106                 char buf[ZFS_MAX_DATASET_NAME_LEN];
1107                 dsl_dir_get_origin(dd, buf);
1108                 dsl_prop_nvlist_add_string(nv, ZFS_PROP_ORIGIN, buf);
1109         }
1110 
1111 }
1112 
1113 void
1114 dsl_dir_dirty(dsl_dir_t *dd, dmu_tx_t *tx)
1115 {
1116         dsl_pool_t *dp = dd->dd_pool;
1117 
1118         ASSERT(dsl_dir_phys(dd));
1119 
1120         if (txg_list_add(&dp->dp_dirty_dirs, dd, tx->tx_txg)) {
1121                 /* up the hold count until we can be written out */
1122                 dmu_buf_add_ref(dd->dd_dbuf, dd);
1123         }




 110  * For consistency, the filesystem limit is also not enforced if the user can
 111  * modify the limit.
 112  *
 113  * The filesystem and snapshot limits are validated by dsl_fs_ss_limit_check()
 114  * and updated by dsl_fs_ss_count_adjust(). A new limit value is setup in
 115  * dsl_dir_activate_fs_ss_limit() and the counts are adjusted, if necessary, by
 116  * dsl_dir_init_fs_ss_count().
 117  *
 118  * There is a special case when we receive a filesystem that already exists. In
 119  * this case a temporary clone name of %X is created (see dmu_recv_begin). We
 120  * never update the filesystem counts for temporary clones.
 121  *
 122  * Likewise, we do not update the snapshot counts for temporary snapshots,
 123  * such as those created by zfs diff.
 124  */
 125 
 126 extern inline dsl_dir_phys_t *dsl_dir_phys(dsl_dir_t *dd);
 127 
 128 static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
 129 





 130 static void
 131 dsl_dir_evict_async(void *dbu)
 132 {
 133         dsl_dir_t *dd = dbu;
 134         dsl_pool_t *dp = dd->dd_pool;
 135         int t;
 136 
 137         dd->dd_dbuf = NULL;
 138 
 139         for (t = 0; t < TXG_SIZE; t++) {
 140                 ASSERT(!txg_list_member(&dp->dp_dirty_dirs, dd, t));
 141                 ASSERT(dd->dd_tempreserved[t] == 0);
 142                 ASSERT(dd->dd_space_towrite[t] == 0);
 143         }
 144 
 145         if (dd->dd_parent)
 146                 dsl_dir_async_rele(dd->dd_parent, dd);
 147 
 148         spa_async_close(dd->dd_pool->dp_spa, dd);
 149 


 712         if ((obj = dsl_dir_phys(dd)->dd_head_dataset_obj) == 0)
 713                 return (ENFORCE_ALWAYS);
 714 
 715         ASSERT(dsl_pool_config_held(dd->dd_pool));
 716 
 717         if (dsl_dataset_hold_obj(dd->dd_pool, obj, FTAG, &ds) != 0)
 718                 return (ENFORCE_ALWAYS);
 719 
 720         if (dsl_prop_get_ds(ds, "zoned", 8, 1, &zoned, NULL) || zoned) {
 721                 /* Only root can access zoned fs's from the GZ */
 722                 enforce = ENFORCE_ALWAYS;
 723         } else {
 724                 if (dsl_deleg_access_impl(ds, zfs_prop_to_name(prop), cr) == 0)
 725                         enforce = ENFORCE_ABOVE;
 726         }
 727 
 728         dsl_dataset_rele(ds, FTAG);
 729         return (enforce);
 730 }
 731 





























 732 /*
 733  * Check if adding additional child filesystem(s) would exceed any filesystem
 734  * limits or adding additional snapshot(s) would exceed any snapshot limits.
 735  * The prop argument indicates which limit to check.
 736  *
 737  * Note that all filesystem limits up to the root (or the highest
 738  * initialized) filesystem or the given ancestor must be satisfied.
 739  */
 740 int
 741 dsl_fs_ss_limit_check(dsl_dir_t *dd, uint64_t delta, zfs_prop_t prop,
 742     dsl_dir_t *ancestor, cred_t *cr)
 743 {
 744         objset_t *os = dd->dd_pool->dp_meta_objset;
 745         uint64_t limit, count;
 746         char *count_prop;
 747         enforce_res_t enforce;
 748         int err = 0;
 749 
 750         ASSERT(dsl_pool_config_held(dd->dd_pool));
 751         ASSERT(prop == ZFS_PROP_FILESYSTEM_LIMIT ||


1003                 objset_t *os = dd->dd_pool->dp_meta_objset;
1004                 return (zap_lookup(os, dd->dd_object, DD_FIELD_FILESYSTEM_COUNT,
1005                     sizeof (*count), 1, count));
1006         } else {
1007                 return (ENOENT);
1008         }
1009 }
1010 
1011 int
1012 dsl_dir_get_snapshot_count(dsl_dir_t *dd, uint64_t *count)
1013 {
1014         if (dsl_dir_is_zapified(dd)) {
1015                 objset_t *os = dd->dd_pool->dp_meta_objset;
1016                 return (zap_lookup(os, dd->dd_object, DD_FIELD_SNAPSHOT_COUNT,
1017                     sizeof (*count), 1, count));
1018         } else {
1019                 return (ENOENT);
1020         }
1021 }
1022 












1023 void
1024 dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv)
1025 {
1026         mutex_enter(&dd->dd_lock);
1027         dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_QUOTA,
1028             dsl_dir_get_quota(dd));
1029         dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_RESERVATION,
1030             dsl_dir_get_reservation(dd));
1031         dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALUSED,
1032             dsl_dir_get_logicalused(dd));
1033         if (dsl_dir_phys(dd)->dd_flags & DD_FLAG_USED_BREAKDOWN) {
1034                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDSNAP,
1035                     dsl_dir_get_usedsnap(dd));
1036                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDDS,
1037                     dsl_dir_get_usedds(dd));
1038                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDREFRESERV,
1039                     dsl_dir_get_usedrefreserv(dd));
1040                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDCHILD,
1041                     dsl_dir_get_usedchild(dd));
1042         }
1043         mutex_exit(&dd->dd_lock);
1044 
1045         uint64_t count;
1046         if (dsl_dir_get_filesystem_count(dd, &count) == 0) {
1047                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_FILESYSTEM_COUNT,
1048                     count);
1049         }
1050         if (dsl_dir_get_snapshot_count(dd, &count) == 0) {
1051                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_SNAPSHOT_COUNT,
1052                     count);
1053         }




1054 
1055         if (dsl_dir_is_clone(dd)) {
1056                 char buf[ZFS_MAX_DATASET_NAME_LEN];
1057                 dsl_dir_get_origin(dd, buf);
1058                 dsl_prop_nvlist_add_string(nv, ZFS_PROP_ORIGIN, buf);
1059         }
1060 
1061 }
1062 
1063 void
1064 dsl_dir_dirty(dsl_dir_t *dd, dmu_tx_t *tx)
1065 {
1066         dsl_pool_t *dp = dd->dd_pool;
1067 
1068         ASSERT(dsl_dir_phys(dd));
1069 
1070         if (txg_list_add(&dp->dp_dirty_dirs, dd, tx->tx_txg)) {
1071                 /* up the hold count until we can be written out */
1072                 dmu_buf_add_ref(dd->dd_dbuf, dd);
1073         }