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, "a);
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, "a);
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 */
|