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) 2013 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
950 if ((dmu_tx_is_syncing(tx) || towrite == 0) &&
951 (newval < ds->ds_dir->dd_phys->dd_reserved ||
952 newval < ds->ds_dir->dd_phys->dd_used_bytes + towrite)) {
953 error = SET_ERROR(ENOSPC);
954 }
955 mutex_exit(&ds->ds_dir->dd_lock);
956 dsl_dataset_rele(ds, FTAG);
957 return (error);
958 }
959
960 static void
961 dsl_dir_set_quota_sync(void *arg, dmu_tx_t *tx)
962 {
963 dsl_dir_set_qr_arg_t *ddsqra = arg;
964 dsl_pool_t *dp = dmu_tx_pool(tx);
965 dsl_dataset_t *ds;
966 uint64_t newval;
967
968 VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
969
970 dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_QUOTA),
971 ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
972 &ddsqra->ddsqra_value, tx);
973
974 VERIFY0(dsl_prop_get_int_ds(ds,
975 zfs_prop_to_name(ZFS_PROP_QUOTA), &newval));
976
977 dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx);
978 mutex_enter(&ds->ds_dir->dd_lock);
979 ds->ds_dir->dd_phys->dd_quota = newval;
980 mutex_exit(&ds->ds_dir->dd_lock);
981 dsl_dataset_rele(ds, FTAG);
982 }
983
984 int
985 dsl_dir_set_quota(const char *ddname, zprop_source_t source, uint64_t quota)
986 {
987 dsl_dir_set_qr_arg_t ddsqra;
988
989 ddsqra.ddsqra_name = ddname;
990 ddsqra.ddsqra_source = source;
991 ddsqra.ddsqra_value = quota;
992
993 return (dsl_sync_task(ddname, dsl_dir_set_quota_check,
994 dsl_dir_set_quota_sync, &ddsqra, 0));
995 }
1066
1067 if (dd->dd_parent != NULL) {
1068 /* Roll up this additional usage into our ancestors */
1069 dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD_RSRV,
1070 delta, 0, 0, tx);
1071 }
1072 mutex_exit(&dd->dd_lock);
1073 }
1074
1075
1076 static void
1077 dsl_dir_set_reservation_sync(void *arg, dmu_tx_t *tx)
1078 {
1079 dsl_dir_set_qr_arg_t *ddsqra = arg;
1080 dsl_pool_t *dp = dmu_tx_pool(tx);
1081 dsl_dataset_t *ds;
1082 uint64_t newval;
1083
1084 VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
1085
1086 dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_RESERVATION),
1087 ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
1088 &ddsqra->ddsqra_value, tx);
1089
1090 VERIFY0(dsl_prop_get_int_ds(ds,
1091 zfs_prop_to_name(ZFS_PROP_RESERVATION), &newval));
1092
1093 dsl_dir_set_reservation_sync_impl(ds->ds_dir, newval, tx);
1094 dsl_dataset_rele(ds, FTAG);
1095 }
1096
1097 int
1098 dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
1099 uint64_t reservation)
1100 {
1101 dsl_dir_set_qr_arg_t ddsqra;
1102
1103 ddsqra.ddsqra_name = ddname;
1104 ddsqra.ddsqra_source = source;
1105 ddsqra.ddsqra_value = reservation;
1106
1107 return (dsl_sync_task(ddname, dsl_dir_set_reservation_check,
1108 dsl_dir_set_reservation_sync, &ddsqra, 0));
1109 }
1110
1111 static dsl_dir_t *
|
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) 2013 by Delphix. All rights reserved.
24 * Copyright (c) 2013 Martin Matuska. All rights reserved.
25 */
26
27 #include <sys/dmu.h>
28 #include <sys/dmu_objset.h>
29 #include <sys/dmu_tx.h>
30 #include <sys/dsl_dataset.h>
31 #include <sys/dsl_dir.h>
32 #include <sys/dsl_prop.h>
33 #include <sys/dsl_synctask.h>
34 #include <sys/dsl_deleg.h>
35 #include <sys/spa.h>
36 #include <sys/metaslab.h>
37 #include <sys/zap.h>
38 #include <sys/zio.h>
39 #include <sys/arc.h>
40 #include <sys/sunddi.h>
41 #include "zfs_namecheck.h"
42
43 static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
44
951 if ((dmu_tx_is_syncing(tx) || towrite == 0) &&
952 (newval < ds->ds_dir->dd_phys->dd_reserved ||
953 newval < ds->ds_dir->dd_phys->dd_used_bytes + towrite)) {
954 error = SET_ERROR(ENOSPC);
955 }
956 mutex_exit(&ds->ds_dir->dd_lock);
957 dsl_dataset_rele(ds, FTAG);
958 return (error);
959 }
960
961 static void
962 dsl_dir_set_quota_sync(void *arg, dmu_tx_t *tx)
963 {
964 dsl_dir_set_qr_arg_t *ddsqra = arg;
965 dsl_pool_t *dp = dmu_tx_pool(tx);
966 dsl_dataset_t *ds;
967 uint64_t newval;
968
969 VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
970
971 if (spa_version(dp->dp_spa) >= SPA_VERSION_RECVD_PROPS) {
972 dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_QUOTA),
973 ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
974 &ddsqra->ddsqra_value, tx);
975
976 VERIFY0(dsl_prop_get_int_ds(ds,
977 zfs_prop_to_name(ZFS_PROP_QUOTA), &newval));
978 } else {
979 newval = ddsqra->ddsqra_value;
980 spa_history_log_internal_ds(ds, "set", tx, "%s=%lld",
981 zfs_prop_to_name(ZFS_PROP_QUOTA), (longlong_t)newval);
982 }
983
984 dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx);
985 mutex_enter(&ds->ds_dir->dd_lock);
986 ds->ds_dir->dd_phys->dd_quota = newval;
987 mutex_exit(&ds->ds_dir->dd_lock);
988 dsl_dataset_rele(ds, FTAG);
989 }
990
991 int
992 dsl_dir_set_quota(const char *ddname, zprop_source_t source, uint64_t quota)
993 {
994 dsl_dir_set_qr_arg_t ddsqra;
995
996 ddsqra.ddsqra_name = ddname;
997 ddsqra.ddsqra_source = source;
998 ddsqra.ddsqra_value = quota;
999
1000 return (dsl_sync_task(ddname, dsl_dir_set_quota_check,
1001 dsl_dir_set_quota_sync, &ddsqra, 0));
1002 }
1073
1074 if (dd->dd_parent != NULL) {
1075 /* Roll up this additional usage into our ancestors */
1076 dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD_RSRV,
1077 delta, 0, 0, tx);
1078 }
1079 mutex_exit(&dd->dd_lock);
1080 }
1081
1082
1083 static void
1084 dsl_dir_set_reservation_sync(void *arg, dmu_tx_t *tx)
1085 {
1086 dsl_dir_set_qr_arg_t *ddsqra = arg;
1087 dsl_pool_t *dp = dmu_tx_pool(tx);
1088 dsl_dataset_t *ds;
1089 uint64_t newval;
1090
1091 VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
1092
1093 if (spa_version(dp->dp_spa) >= SPA_VERSION_RECVD_PROPS) {
1094 dsl_prop_set_sync_impl(ds,
1095 zfs_prop_to_name(ZFS_PROP_RESERVATION),
1096 ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
1097 &ddsqra->ddsqra_value, tx);
1098
1099 VERIFY0(dsl_prop_get_int_ds(ds,
1100 zfs_prop_to_name(ZFS_PROP_RESERVATION), &newval));
1101 } else {
1102 newval = ddsqra->ddsqra_value;
1103 spa_history_log_internal_ds(ds, "set", tx, "%s=%lld",
1104 zfs_prop_to_name(ZFS_PROP_RESERVATION),
1105 (longlong_t)newval);
1106 }
1107
1108 dsl_dir_set_reservation_sync_impl(ds->ds_dir, newval, tx);
1109 dsl_dataset_rele(ds, FTAG);
1110 }
1111
1112 int
1113 dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
1114 uint64_t reservation)
1115 {
1116 dsl_dir_set_qr_arg_t ddsqra;
1117
1118 ddsqra.ddsqra_name = ddname;
1119 ddsqra.ddsqra_source = source;
1120 ddsqra.ddsqra_value = reservation;
1121
1122 return (dsl_sync_task(ddname, dsl_dir_set_reservation_check,
1123 dsl_dir_set_reservation_sync, &ddsqra, 0));
1124 }
1125
1126 static dsl_dir_t *
|