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 #include <sys/dmu.h>
  26 #include <sys/dmu_objset.h>
  27 #include <sys/dmu_tx.h>
  28 #include <sys/dsl_dataset.h>
  29 #include <sys/dsl_dir.h>
  30 #include <sys/dsl_prop.h>
  31 #include <sys/dsl_synctask.h>
  32 #include <sys/dsl_deleg.h>
  33 #include <sys/spa.h>
  34 #include <sys/metaslab.h>
  35 #include <sys/zap.h>
  36 #include <sys/zio.h>
  37 #include <sys/arc.h>
  38 #include <sys/sunddi.h>
  39 #include "zfs_namecheck.h"
  40 
  41 static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
  42 static void dsl_dir_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx);
  43 
  44 
  45 /* ARGSUSED */
  46 static void
  47 dsl_dir_evict(dmu_buf_t *db, void *arg)
  48 {
  49         dsl_dir_t *dd = arg;
  50         dsl_pool_t *dp = dd->dd_pool;
  51         int t;
  52 
  53         for (t = 0; t < TXG_SIZE; t++) {
  54                 ASSERT(!txg_list_member(&dp->dp_dirty_dirs, dd, t));
  55                 ASSERT(dd->dd_tempreserved[t] == 0);
  56                 ASSERT(dd->dd_space_towrite[t] == 0);
  57         }
  58 
  59         if (dd->dd_parent)
  60                 dsl_dir_close(dd->dd_parent, dd);
  61 
  62         spa_close(dd->dd_pool->dp_spa, dd);
  63 


 430         ddphys = dbuf->db_data;
 431 
 432         ddphys->dd_creation_time = gethrestime_sec();
 433         if (pds)
 434                 ddphys->dd_parent_obj = pds->dd_object;
 435         ddphys->dd_props_zapobj = zap_create(mos,
 436             DMU_OT_DSL_PROPS, DMU_OT_NONE, 0, tx);
 437         ddphys->dd_child_dir_zapobj = zap_create(mos,
 438             DMU_OT_DSL_DIR_CHILD_MAP, DMU_OT_NONE, 0, tx);
 439         if (spa_version(dp->dp_spa) >= SPA_VERSION_USED_BREAKDOWN)
 440                 ddphys->dd_flags |= DD_FLAG_USED_BREAKDOWN;
 441         dmu_buf_rele(dbuf, FTAG);
 442 
 443         return (ddobj);
 444 }
 445 
 446 /* ARGSUSED */
 447 int
 448 dsl_dir_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx)
 449 {
 450         dsl_dataset_t *ds = arg1;
 451         dsl_dir_t *dd = ds->ds_dir;
 452         dsl_pool_t *dp = dd->dd_pool;
 453         objset_t *mos = dp->dp_meta_objset;
 454         int err;
 455         uint64_t count;
 456 
 457         /*
 458          * There should be exactly two holds, both from
 459          * dsl_dataset_destroy: one on the dd directory, and one on its
 460          * head ds.  Otherwise, someone is trying to lookup something
 461          * inside this dir while we want to destroy it.  The
 462          * config_rwlock ensures that nobody else opens it after we
 463          * check.
 464          */
 465         if (dmu_buf_refcount(dd->dd_dbuf) > 2)
 466                 return (EBUSY);
 467 
 468         err = zap_count(mos, dd->dd_phys->dd_child_dir_zapobj, &count);
 469         if (err)
 470                 return (err);
 471         if (count != 0)
 472                 return (EEXIST);
 473 
 474         return (0);
 475 }
 476 
 477 void
 478 dsl_dir_destroy_sync(void *arg1, void *tag, dmu_tx_t *tx)
 479 {
 480         dsl_dataset_t *ds = arg1;
 481         dsl_dir_t *dd = ds->ds_dir;
 482         objset_t *mos = dd->dd_pool->dp_meta_objset;
 483         dsl_prop_setarg_t psa;
 484         uint64_t value = 0;
 485         uint64_t obj;
 486         dd_used_t t;
 487 
 488         ASSERT(RW_WRITE_HELD(&dd->dd_pool->dp_config_rwlock));
 489         ASSERT(dd->dd_phys->dd_head_dataset_obj == 0);
 490 
 491         /* Remove our reservation. */
 492         dsl_prop_setarg_init_uint64(&psa, "reservation",
 493             (ZPROP_SRC_NONE | ZPROP_SRC_LOCAL | ZPROP_SRC_RECEIVED),
 494             &value);
 495         psa.psa_effective_value = 0;    /* predict default value */
 496 
 497         dsl_dir_set_reservation_sync(ds, &psa, tx);
 498 
 499         ASSERT3U(dd->dd_phys->dd_used_bytes, ==, 0);
 500         ASSERT3U(dd->dd_phys->dd_reserved, ==, 0);
 501         for (t = 0; t < DD_USED_NUM; t++)
 502                 ASSERT3U(dd->dd_phys->dd_used_breakdown[t], ==, 0);
 503 
 504         VERIFY(0 == zap_destroy(mos, dd->dd_phys->dd_child_dir_zapobj, tx));
 505         VERIFY(0 == zap_destroy(mos, dd->dd_phys->dd_props_zapobj, tx));
 506         VERIFY(0 == dsl_deleg_destroy(mos, dd->dd_phys->dd_deleg_zapobj, tx));
 507         VERIFY(0 == zap_remove(mos,
 508             dd->dd_parent->dd_phys->dd_child_dir_zapobj, dd->dd_myname, tx));
 509 
 510         obj = dd->dd_object;
 511         dsl_dir_close(dd, tag);
 512         VERIFY(0 == dmu_object_free(mos, obj, tx));
 513 }
 514 
 515 boolean_t
 516 dsl_dir_is_clone(dsl_dir_t *dd)
 517 {


1043 
1044 extern dsl_syncfunc_t dsl_prop_set_sync;
1045 
1046 static void
1047 dsl_dir_set_quota_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1048 {
1049         dsl_dataset_t *ds = arg1;
1050         dsl_dir_t *dd = ds->ds_dir;
1051         dsl_prop_setarg_t *psa = arg2;
1052         uint64_t effective_value = psa->psa_effective_value;
1053 
1054         dsl_prop_set_sync(ds, psa, tx);
1055         DSL_PROP_CHECK_PREDICTION(dd, psa);
1056 
1057         dmu_buf_will_dirty(dd->dd_dbuf, tx);
1058 
1059         mutex_enter(&dd->dd_lock);
1060         dd->dd_phys->dd_quota = effective_value;
1061         mutex_exit(&dd->dd_lock);
1062 
1063         spa_history_log_internal(LOG_DS_QUOTA, dd->dd_pool->dp_spa,
1064             tx, "%lld dataset = %llu ",
1065             (longlong_t)effective_value, dd->dd_phys->dd_head_dataset_obj);
1066 }
1067 
1068 int
1069 dsl_dir_set_quota(const char *ddname, zprop_source_t source, uint64_t quota)
1070 {
1071         dsl_dir_t *dd;
1072         dsl_dataset_t *ds;
1073         dsl_prop_setarg_t psa;
1074         int err;
1075 
1076         dsl_prop_setarg_init_uint64(&psa, "quota", source, &quota);
1077 
1078         err = dsl_dataset_hold(ddname, FTAG, &ds);
1079         if (err)
1080                 return (err);
1081 
1082         err = dsl_dir_open(ddname, FTAG, &dd, NULL);
1083         if (err) {
1084                 dsl_dataset_rele(ds, FTAG);
1085                 return (err);


1132                     NULL, 0, FALSE);
1133         } else {
1134                 avail = dsl_pool_adjustedsize(dd->dd_pool, B_FALSE) - used;
1135         }
1136 
1137         if (MAX(used, effective_value) > MAX(used, dd->dd_phys->dd_reserved)) {
1138                 uint64_t delta = MAX(used, effective_value) -
1139                     MAX(used, dd->dd_phys->dd_reserved);
1140 
1141                 if (delta > avail)
1142                         return (ENOSPC);
1143                 if (dd->dd_phys->dd_quota > 0 &&
1144                     effective_value > dd->dd_phys->dd_quota)
1145                         return (ENOSPC);
1146         }
1147 
1148         return (0);
1149 }
1150 
1151 static void
1152 dsl_dir_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1153 {
1154         dsl_dataset_t *ds = arg1;
1155         dsl_dir_t *dd = ds->ds_dir;
1156         dsl_prop_setarg_t *psa = arg2;
1157         uint64_t effective_value = psa->psa_effective_value;
1158         uint64_t used;
1159         int64_t delta;
1160 
1161         dsl_prop_set_sync(ds, psa, tx);
1162         DSL_PROP_CHECK_PREDICTION(dd, psa);
1163 
1164         dmu_buf_will_dirty(dd->dd_dbuf, tx);
1165 
1166         mutex_enter(&dd->dd_lock);
1167         used = dd->dd_phys->dd_used_bytes;
1168         delta = MAX(used, effective_value) -
1169             MAX(used, dd->dd_phys->dd_reserved);
1170         dd->dd_phys->dd_reserved = effective_value;
1171 
1172         if (dd->dd_parent != NULL) {
1173                 /* Roll up this additional usage into our ancestors */
1174                 dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD_RSRV,
1175                     delta, 0, 0, tx);
1176         }
1177         mutex_exit(&dd->dd_lock);


1178 
1179         spa_history_log_internal(LOG_DS_RESERVATION, dd->dd_pool->dp_spa,
1180             tx, "%lld dataset = %llu",
1181             (longlong_t)effective_value, dd->dd_phys->dd_head_dataset_obj);












1182 }
1183 
1184 int
1185 dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
1186     uint64_t reservation)
1187 {
1188         dsl_dir_t *dd;
1189         dsl_dataset_t *ds;
1190         dsl_prop_setarg_t psa;
1191         int err;
1192 
1193         dsl_prop_setarg_init_uint64(&psa, "reservation", source, &reservation);
1194 
1195         err = dsl_dataset_hold(ddname, FTAG, &ds);
1196         if (err)
1197                 return (err);
1198 
1199         err = dsl_dir_open(ddname, FTAG, &dd, NULL);
1200         if (err) {
1201                 dsl_dataset_rele(ds, FTAG);


1282                 /* no rename into our descendant */
1283                 if (closest_common_ancestor(dd, ra->newparent) == dd)
1284                         return (EINVAL);
1285 
1286                 if (err = dsl_dir_transfer_possible(dd->dd_parent,
1287                     ra->newparent, myspace))
1288                         return (err);
1289         }
1290 
1291         return (0);
1292 }
1293 
1294 static void
1295 dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1296 {
1297         dsl_dir_t *dd = arg1;
1298         struct renamearg *ra = arg2;
1299         dsl_pool_t *dp = dd->dd_pool;
1300         objset_t *mos = dp->dp_meta_objset;
1301         int err;

1302 
1303         ASSERT(dmu_buf_refcount(dd->dd_dbuf) <= 2);
1304 





1305         if (ra->newparent != dd->dd_parent) {
1306                 dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD,
1307                     -dd->dd_phys->dd_used_bytes,
1308                     -dd->dd_phys->dd_compressed_bytes,
1309                     -dd->dd_phys->dd_uncompressed_bytes, tx);
1310                 dsl_dir_diduse_space(ra->newparent, DD_USED_CHILD,
1311                     dd->dd_phys->dd_used_bytes,
1312                     dd->dd_phys->dd_compressed_bytes,
1313                     dd->dd_phys->dd_uncompressed_bytes, tx);
1314 
1315                 if (dd->dd_phys->dd_reserved > dd->dd_phys->dd_used_bytes) {
1316                         uint64_t unused_rsrv = dd->dd_phys->dd_reserved -
1317                             dd->dd_phys->dd_used_bytes;
1318 
1319                         dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD_RSRV,
1320                             -unused_rsrv, 0, 0, tx);
1321                         dsl_dir_diduse_space(ra->newparent, DD_USED_CHILD_RSRV,
1322                             unused_rsrv, 0, 0, tx);
1323                 }
1324         }
1325 
1326         dmu_buf_will_dirty(dd->dd_dbuf, tx);
1327 
1328         /* remove from old parent zapobj */
1329         err = zap_remove(mos, dd->dd_parent->dd_phys->dd_child_dir_zapobj,
1330             dd->dd_myname, tx);
1331         ASSERT3U(err, ==, 0);
1332 
1333         (void) strcpy(dd->dd_myname, ra->mynewname);
1334         dsl_dir_close(dd->dd_parent, dd);
1335         dd->dd_phys->dd_parent_obj = ra->newparent->dd_object;
1336         VERIFY(0 == dsl_dir_open_obj(dd->dd_pool,
1337             ra->newparent->dd_object, NULL, dd, &dd->dd_parent));
1338 
1339         /* add to new parent zapobj */
1340         err = zap_add(mos, ra->newparent->dd_phys->dd_child_dir_zapobj,
1341             dd->dd_myname, 8, 1, &dd->dd_object, tx);
1342         ASSERT3U(err, ==, 0);
1343 
1344         spa_history_log_internal(LOG_DS_RENAME, dd->dd_pool->dp_spa,
1345             tx, "dataset = %llu", dd->dd_phys->dd_head_dataset_obj);
1346 }
1347 
1348 int
1349 dsl_dir_rename(dsl_dir_t *dd, const char *newname)
1350 {
1351         struct renamearg ra;
1352         int err;
1353 
1354         /* new parent should exist */
1355         err = dsl_dir_open(newname, FTAG, &ra.newparent, &ra.mynewname);
1356         if (err)
1357                 return (err);
1358 
1359         /* can't rename to different pool */
1360         if (dd->dd_pool != ra.newparent->dd_pool) {
1361                 err = ENXIO;
1362                 goto out;
1363         }
1364 
1365         /* new name should not already exist */




   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 #include <sys/dmu.h>
  27 #include <sys/dmu_objset.h>
  28 #include <sys/dmu_tx.h>
  29 #include <sys/dsl_dataset.h>
  30 #include <sys/dsl_dir.h>
  31 #include <sys/dsl_prop.h>
  32 #include <sys/dsl_synctask.h>
  33 #include <sys/dsl_deleg.h>
  34 #include <sys/spa.h>
  35 #include <sys/metaslab.h>
  36 #include <sys/zap.h>
  37 #include <sys/zio.h>
  38 #include <sys/arc.h>
  39 #include <sys/sunddi.h>
  40 #include "zfs_namecheck.h"
  41 
  42 static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
  43 static void dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd,
  44     uint64_t value, dmu_tx_t *tx);
  45 
  46 /* ARGSUSED */
  47 static void
  48 dsl_dir_evict(dmu_buf_t *db, void *arg)
  49 {
  50         dsl_dir_t *dd = arg;
  51         dsl_pool_t *dp = dd->dd_pool;
  52         int t;
  53 
  54         for (t = 0; t < TXG_SIZE; t++) {
  55                 ASSERT(!txg_list_member(&dp->dp_dirty_dirs, dd, t));
  56                 ASSERT(dd->dd_tempreserved[t] == 0);
  57                 ASSERT(dd->dd_space_towrite[t] == 0);
  58         }
  59 
  60         if (dd->dd_parent)
  61                 dsl_dir_close(dd->dd_parent, dd);
  62 
  63         spa_close(dd->dd_pool->dp_spa, dd);
  64 


 431         ddphys = dbuf->db_data;
 432 
 433         ddphys->dd_creation_time = gethrestime_sec();
 434         if (pds)
 435                 ddphys->dd_parent_obj = pds->dd_object;
 436         ddphys->dd_props_zapobj = zap_create(mos,
 437             DMU_OT_DSL_PROPS, DMU_OT_NONE, 0, tx);
 438         ddphys->dd_child_dir_zapobj = zap_create(mos,
 439             DMU_OT_DSL_DIR_CHILD_MAP, DMU_OT_NONE, 0, tx);
 440         if (spa_version(dp->dp_spa) >= SPA_VERSION_USED_BREAKDOWN)
 441                 ddphys->dd_flags |= DD_FLAG_USED_BREAKDOWN;
 442         dmu_buf_rele(dbuf, FTAG);
 443 
 444         return (ddobj);
 445 }
 446 
 447 /* ARGSUSED */
 448 int
 449 dsl_dir_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx)
 450 {
 451         dsl_dir_t *dd = arg1;

 452         dsl_pool_t *dp = dd->dd_pool;
 453         objset_t *mos = dp->dp_meta_objset;
 454         int err;
 455         uint64_t count;
 456 
 457         /*
 458          * There should be exactly two holds, both from
 459          * dsl_dataset_destroy: one on the dd directory, and one on its
 460          * head ds.  Otherwise, someone is trying to lookup something
 461          * inside this dir while we want to destroy it.  The
 462          * config_rwlock ensures that nobody else opens it after we
 463          * check.
 464          */
 465         if (dmu_buf_refcount(dd->dd_dbuf) > 2)
 466                 return (EBUSY);
 467 
 468         err = zap_count(mos, dd->dd_phys->dd_child_dir_zapobj, &count);
 469         if (err)
 470                 return (err);
 471         if (count != 0)
 472                 return (EEXIST);
 473 
 474         return (0);
 475 }
 476 
 477 void
 478 dsl_dir_destroy_sync(void *arg1, void *tag, dmu_tx_t *tx)
 479 {
 480         dsl_dir_t *dd = arg1;

 481         objset_t *mos = dd->dd_pool->dp_meta_objset;


 482         uint64_t obj;
 483         dd_used_t t;
 484 
 485         ASSERT(RW_WRITE_HELD(&dd->dd_pool->dp_config_rwlock));
 486         ASSERT(dd->dd_phys->dd_head_dataset_obj == 0);
 487 
 488         /*
 489          * Remove our reservation. The impl() routine avoids setting the
 490          * actual property, which would require the (already destroyed) ds.
 491          */
 492         dsl_dir_set_reservation_sync_impl(dd, 0, tx);


 493 
 494         ASSERT3U(dd->dd_phys->dd_used_bytes, ==, 0);
 495         ASSERT3U(dd->dd_phys->dd_reserved, ==, 0);
 496         for (t = 0; t < DD_USED_NUM; t++)
 497                 ASSERT3U(dd->dd_phys->dd_used_breakdown[t], ==, 0);
 498 
 499         VERIFY(0 == zap_destroy(mos, dd->dd_phys->dd_child_dir_zapobj, tx));
 500         VERIFY(0 == zap_destroy(mos, dd->dd_phys->dd_props_zapobj, tx));
 501         VERIFY(0 == dsl_deleg_destroy(mos, dd->dd_phys->dd_deleg_zapobj, tx));
 502         VERIFY(0 == zap_remove(mos,
 503             dd->dd_parent->dd_phys->dd_child_dir_zapobj, dd->dd_myname, tx));
 504 
 505         obj = dd->dd_object;
 506         dsl_dir_close(dd, tag);
 507         VERIFY(0 == dmu_object_free(mos, obj, tx));
 508 }
 509 
 510 boolean_t
 511 dsl_dir_is_clone(dsl_dir_t *dd)
 512 {


1038 
1039 extern dsl_syncfunc_t dsl_prop_set_sync;
1040 
1041 static void
1042 dsl_dir_set_quota_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1043 {
1044         dsl_dataset_t *ds = arg1;
1045         dsl_dir_t *dd = ds->ds_dir;
1046         dsl_prop_setarg_t *psa = arg2;
1047         uint64_t effective_value = psa->psa_effective_value;
1048 
1049         dsl_prop_set_sync(ds, psa, tx);
1050         DSL_PROP_CHECK_PREDICTION(dd, psa);
1051 
1052         dmu_buf_will_dirty(dd->dd_dbuf, tx);
1053 
1054         mutex_enter(&dd->dd_lock);
1055         dd->dd_phys->dd_quota = effective_value;
1056         mutex_exit(&dd->dd_lock);
1057 
1058         spa_history_log_internal_dd(dd, "set quota", tx,
1059             "quota=%lld", (longlong_t)effective_value);

1060 }
1061 
1062 int
1063 dsl_dir_set_quota(const char *ddname, zprop_source_t source, uint64_t quota)
1064 {
1065         dsl_dir_t *dd;
1066         dsl_dataset_t *ds;
1067         dsl_prop_setarg_t psa;
1068         int err;
1069 
1070         dsl_prop_setarg_init_uint64(&psa, "quota", source, &quota);
1071 
1072         err = dsl_dataset_hold(ddname, FTAG, &ds);
1073         if (err)
1074                 return (err);
1075 
1076         err = dsl_dir_open(ddname, FTAG, &dd, NULL);
1077         if (err) {
1078                 dsl_dataset_rele(ds, FTAG);
1079                 return (err);


1126                     NULL, 0, FALSE);
1127         } else {
1128                 avail = dsl_pool_adjustedsize(dd->dd_pool, B_FALSE) - used;
1129         }
1130 
1131         if (MAX(used, effective_value) > MAX(used, dd->dd_phys->dd_reserved)) {
1132                 uint64_t delta = MAX(used, effective_value) -
1133                     MAX(used, dd->dd_phys->dd_reserved);
1134 
1135                 if (delta > avail)
1136                         return (ENOSPC);
1137                 if (dd->dd_phys->dd_quota > 0 &&
1138                     effective_value > dd->dd_phys->dd_quota)
1139                         return (ENOSPC);
1140         }
1141 
1142         return (0);
1143 }
1144 
1145 static void
1146 dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd, uint64_t value, dmu_tx_t *tx)
1147 {




1148         uint64_t used;
1149         int64_t delta;
1150 



1151         dmu_buf_will_dirty(dd->dd_dbuf, tx);
1152 
1153         mutex_enter(&dd->dd_lock);
1154         used = dd->dd_phys->dd_used_bytes;
1155         delta = MAX(used, value) - MAX(used, dd->dd_phys->dd_reserved);
1156         dd->dd_phys->dd_reserved = value;

1157 
1158         if (dd->dd_parent != NULL) {
1159                 /* Roll up this additional usage into our ancestors */
1160                 dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD_RSRV,
1161                     delta, 0, 0, tx);
1162         }
1163         mutex_exit(&dd->dd_lock);
1164 }
1165 
1166 
1167 static void
1168 dsl_dir_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1169 {
1170         dsl_dataset_t *ds = arg1;
1171         dsl_dir_t *dd = ds->ds_dir;
1172         dsl_prop_setarg_t *psa = arg2;
1173         uint64_t value = psa->psa_effective_value;
1174 
1175         dsl_prop_set_sync(ds, psa, tx);
1176         DSL_PROP_CHECK_PREDICTION(dd, psa);
1177 
1178         dsl_dir_set_reservation_sync_impl(dd, value, tx);
1179 
1180         spa_history_log_internal_dd(dd, "set reservation", tx,
1181             "reservation=%lld", (longlong_t)value);
1182 }
1183 
1184 int
1185 dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
1186     uint64_t reservation)
1187 {
1188         dsl_dir_t *dd;
1189         dsl_dataset_t *ds;
1190         dsl_prop_setarg_t psa;
1191         int err;
1192 
1193         dsl_prop_setarg_init_uint64(&psa, "reservation", source, &reservation);
1194 
1195         err = dsl_dataset_hold(ddname, FTAG, &ds);
1196         if (err)
1197                 return (err);
1198 
1199         err = dsl_dir_open(ddname, FTAG, &dd, NULL);
1200         if (err) {
1201                 dsl_dataset_rele(ds, FTAG);


1282                 /* no rename into our descendant */
1283                 if (closest_common_ancestor(dd, ra->newparent) == dd)
1284                         return (EINVAL);
1285 
1286                 if (err = dsl_dir_transfer_possible(dd->dd_parent,
1287                     ra->newparent, myspace))
1288                         return (err);
1289         }
1290 
1291         return (0);
1292 }
1293 
1294 static void
1295 dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1296 {
1297         dsl_dir_t *dd = arg1;
1298         struct renamearg *ra = arg2;
1299         dsl_pool_t *dp = dd->dd_pool;
1300         objset_t *mos = dp->dp_meta_objset;
1301         int err;
1302         char namebuf[MAXNAMELEN];
1303 
1304         ASSERT(dmu_buf_refcount(dd->dd_dbuf) <= 2);
1305 
1306         /* Log this before we change the name. */
1307         dsl_dir_name(ra->newparent, namebuf);
1308         spa_history_log_internal_dd(dd, "rename", tx,
1309             "-> %s/%s", namebuf, ra->mynewname);
1310 
1311         if (ra->newparent != dd->dd_parent) {
1312                 dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD,
1313                     -dd->dd_phys->dd_used_bytes,
1314                     -dd->dd_phys->dd_compressed_bytes,
1315                     -dd->dd_phys->dd_uncompressed_bytes, tx);
1316                 dsl_dir_diduse_space(ra->newparent, DD_USED_CHILD,
1317                     dd->dd_phys->dd_used_bytes,
1318                     dd->dd_phys->dd_compressed_bytes,
1319                     dd->dd_phys->dd_uncompressed_bytes, tx);
1320 
1321                 if (dd->dd_phys->dd_reserved > dd->dd_phys->dd_used_bytes) {
1322                         uint64_t unused_rsrv = dd->dd_phys->dd_reserved -
1323                             dd->dd_phys->dd_used_bytes;
1324 
1325                         dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD_RSRV,
1326                             -unused_rsrv, 0, 0, tx);
1327                         dsl_dir_diduse_space(ra->newparent, DD_USED_CHILD_RSRV,
1328                             unused_rsrv, 0, 0, tx);
1329                 }
1330         }
1331 
1332         dmu_buf_will_dirty(dd->dd_dbuf, tx);
1333 
1334         /* remove from old parent zapobj */
1335         err = zap_remove(mos, dd->dd_parent->dd_phys->dd_child_dir_zapobj,
1336             dd->dd_myname, tx);
1337         ASSERT3U(err, ==, 0);
1338 
1339         (void) strcpy(dd->dd_myname, ra->mynewname);
1340         dsl_dir_close(dd->dd_parent, dd);
1341         dd->dd_phys->dd_parent_obj = ra->newparent->dd_object;
1342         VERIFY(0 == dsl_dir_open_obj(dd->dd_pool,
1343             ra->newparent->dd_object, NULL, dd, &dd->dd_parent));
1344 
1345         /* add to new parent zapobj */
1346         err = zap_add(mos, ra->newparent->dd_phys->dd_child_dir_zapobj,
1347             dd->dd_myname, 8, 1, &dd->dd_object, tx);
1348         ASSERT3U(err, ==, 0);
1349 


1350 }
1351 
1352 int
1353 dsl_dir_rename(dsl_dir_t *dd, const char *newname)
1354 {
1355         struct renamearg ra;
1356         int err;
1357 
1358         /* new parent should exist */
1359         err = dsl_dir_open(newname, FTAG, &ra.newparent, &ra.mynewname);
1360         if (err)
1361                 return (err);
1362 
1363         /* can't rename to different pool */
1364         if (dd->dd_pool != ra.newparent->dd_pool) {
1365                 err = ENXIO;
1366                 goto out;
1367         }
1368 
1369         /* new name should not already exist */