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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dsl_dir.c
          +++ new/usr/src/uts/common/fs/zfs/dsl_dir.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright (c) 2012 by Delphix. All rights reserved.
  23   24   */
  24   25  
  25   26  #include <sys/dmu.h>
  26   27  #include <sys/dmu_objset.h>
  27   28  #include <sys/dmu_tx.h>
  28   29  #include <sys/dsl_dataset.h>
  29   30  #include <sys/dsl_dir.h>
  30   31  #include <sys/dsl_prop.h>
  31   32  #include <sys/dsl_synctask.h>
  32   33  #include <sys/dsl_deleg.h>
  33   34  #include <sys/spa.h>
  34   35  #include <sys/metaslab.h>
  35   36  #include <sys/zap.h>
  36   37  #include <sys/zio.h>
  37   38  #include <sys/arc.h>
  38   39  #include <sys/sunddi.h>
  39   40  #include "zfs_namecheck.h"
  40   41  
  41   42  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      -
       43 +static void dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd,
       44 +    uint64_t value, dmu_tx_t *tx);
  44   45  
  45   46  /* ARGSUSED */
  46   47  static void
  47   48  dsl_dir_evict(dmu_buf_t *db, void *arg)
  48   49  {
  49   50          dsl_dir_t *dd = arg;
  50   51          dsl_pool_t *dp = dd->dd_pool;
  51   52          int t;
  52   53  
  53   54          for (t = 0; t < TXG_SIZE; t++) {
↓ open down ↓ 386 lines elided ↑ open up ↑
 440  441                  ddphys->dd_flags |= DD_FLAG_USED_BREAKDOWN;
 441  442          dmu_buf_rele(dbuf, FTAG);
 442  443  
 443  444          return (ddobj);
 444  445  }
 445  446  
 446  447  /* ARGSUSED */
 447  448  int
 448  449  dsl_dir_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx)
 449  450  {
 450      -        dsl_dataset_t *ds = arg1;
 451      -        dsl_dir_t *dd = ds->ds_dir;
      451 +        dsl_dir_t *dd = arg1;
 452  452          dsl_pool_t *dp = dd->dd_pool;
 453  453          objset_t *mos = dp->dp_meta_objset;
 454  454          int err;
 455  455          uint64_t count;
 456  456  
 457  457          /*
 458  458           * There should be exactly two holds, both from
 459  459           * dsl_dataset_destroy: one on the dd directory, and one on its
 460  460           * head ds.  Otherwise, someone is trying to lookup something
 461  461           * inside this dir while we want to destroy it.  The
↓ open down ↓ 8 lines elided ↑ open up ↑
 470  470                  return (err);
 471  471          if (count != 0)
 472  472                  return (EEXIST);
 473  473  
 474  474          return (0);
 475  475  }
 476  476  
 477  477  void
 478  478  dsl_dir_destroy_sync(void *arg1, void *tag, dmu_tx_t *tx)
 479  479  {
 480      -        dsl_dataset_t *ds = arg1;
 481      -        dsl_dir_t *dd = ds->ds_dir;
      480 +        dsl_dir_t *dd = arg1;
 482  481          objset_t *mos = dd->dd_pool->dp_meta_objset;
 483      -        dsl_prop_setarg_t psa;
 484      -        uint64_t value = 0;
 485  482          uint64_t obj;
 486  483          dd_used_t t;
 487  484  
 488  485          ASSERT(RW_WRITE_HELD(&dd->dd_pool->dp_config_rwlock));
 489  486          ASSERT(dd->dd_phys->dd_head_dataset_obj == 0);
 490  487  
 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);
      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);
 498  493  
 499  494          ASSERT3U(dd->dd_phys->dd_used_bytes, ==, 0);
 500  495          ASSERT3U(dd->dd_phys->dd_reserved, ==, 0);
 501  496          for (t = 0; t < DD_USED_NUM; t++)
 502  497                  ASSERT3U(dd->dd_phys->dd_used_breakdown[t], ==, 0);
 503  498  
 504  499          VERIFY(0 == zap_destroy(mos, dd->dd_phys->dd_child_dir_zapobj, tx));
 505  500          VERIFY(0 == zap_destroy(mos, dd->dd_phys->dd_props_zapobj, tx));
 506  501          VERIFY(0 == dsl_deleg_destroy(mos, dd->dd_phys->dd_deleg_zapobj, tx));
 507  502          VERIFY(0 == zap_remove(mos,
↓ open down ↓ 545 lines elided ↑ open up ↑
1053 1048  
1054 1049          dsl_prop_set_sync(ds, psa, tx);
1055 1050          DSL_PROP_CHECK_PREDICTION(dd, psa);
1056 1051  
1057 1052          dmu_buf_will_dirty(dd->dd_dbuf, tx);
1058 1053  
1059 1054          mutex_enter(&dd->dd_lock);
1060 1055          dd->dd_phys->dd_quota = effective_value;
1061 1056          mutex_exit(&dd->dd_lock);
1062 1057  
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);
     1058 +        spa_history_log_internal_dd(dd, "set quota", tx,
     1059 +            "quota=%lld", (longlong_t)effective_value);
1066 1060  }
1067 1061  
1068 1062  int
1069 1063  dsl_dir_set_quota(const char *ddname, zprop_source_t source, uint64_t quota)
1070 1064  {
1071 1065          dsl_dir_t *dd;
1072 1066          dsl_dataset_t *ds;
1073 1067          dsl_prop_setarg_t psa;
1074 1068          int err;
1075 1069  
↓ open down ↓ 66 lines elided ↑ open up ↑
1142 1136                          return (ENOSPC);
1143 1137                  if (dd->dd_phys->dd_quota > 0 &&
1144 1138                      effective_value > dd->dd_phys->dd_quota)
1145 1139                          return (ENOSPC);
1146 1140          }
1147 1141  
1148 1142          return (0);
1149 1143  }
1150 1144  
1151 1145  static void
1152      -dsl_dir_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     1146 +dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd, uint64_t value, dmu_tx_t *tx)
1153 1147  {
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 1148          uint64_t used;
1159 1149          int64_t delta;
1160 1150  
1161      -        dsl_prop_set_sync(ds, psa, tx);
1162      -        DSL_PROP_CHECK_PREDICTION(dd, psa);
1163      -
1164 1151          dmu_buf_will_dirty(dd->dd_dbuf, tx);
1165 1152  
1166 1153          mutex_enter(&dd->dd_lock);
1167 1154          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;
     1155 +        delta = MAX(used, value) - MAX(used, dd->dd_phys->dd_reserved);
     1156 +        dd->dd_phys->dd_reserved = value;
1171 1157  
1172 1158          if (dd->dd_parent != NULL) {
1173 1159                  /* Roll up this additional usage into our ancestors */
1174 1160                  dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD_RSRV,
1175 1161                      delta, 0, 0, tx);
1176 1162          }
1177 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);
1178 1177  
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);
     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 1182  }
1183 1183  
1184 1184  int
1185 1185  dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
1186 1186      uint64_t reservation)
1187 1187  {
1188 1188          dsl_dir_t *dd;
1189 1189          dsl_dataset_t *ds;
1190 1190          dsl_prop_setarg_t psa;
1191 1191          int err;
↓ open down ↓ 100 lines elided ↑ open up ↑
1292 1292  }
1293 1293  
1294 1294  static void
1295 1295  dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1296 1296  {
1297 1297          dsl_dir_t *dd = arg1;
1298 1298          struct renamearg *ra = arg2;
1299 1299          dsl_pool_t *dp = dd->dd_pool;
1300 1300          objset_t *mos = dp->dp_meta_objset;
1301 1301          int err;
     1302 +        char namebuf[MAXNAMELEN];
1302 1303  
1303 1304          ASSERT(dmu_buf_refcount(dd->dd_dbuf) <= 2);
1304 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 +
1305 1311          if (ra->newparent != dd->dd_parent) {
1306 1312                  dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD,
1307 1313                      -dd->dd_phys->dd_used_bytes,
1308 1314                      -dd->dd_phys->dd_compressed_bytes,
1309 1315                      -dd->dd_phys->dd_uncompressed_bytes, tx);
1310 1316                  dsl_dir_diduse_space(ra->newparent, DD_USED_CHILD,
1311 1317                      dd->dd_phys->dd_used_bytes,
1312 1318                      dd->dd_phys->dd_compressed_bytes,
1313 1319                      dd->dd_phys->dd_uncompressed_bytes, tx);
1314 1320  
↓ open down ↓ 19 lines elided ↑ open up ↑
1334 1340          dsl_dir_close(dd->dd_parent, dd);
1335 1341          dd->dd_phys->dd_parent_obj = ra->newparent->dd_object;
1336 1342          VERIFY(0 == dsl_dir_open_obj(dd->dd_pool,
1337 1343              ra->newparent->dd_object, NULL, dd, &dd->dd_parent));
1338 1344  
1339 1345          /* add to new parent zapobj */
1340 1346          err = zap_add(mos, ra->newparent->dd_phys->dd_child_dir_zapobj,
1341 1347              dd->dd_myname, 8, 1, &dd->dd_object, tx);
1342 1348          ASSERT3U(err, ==, 0);
1343 1349  
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 1350  }
1347 1351  
1348 1352  int
1349 1353  dsl_dir_rename(dsl_dir_t *dd, const char *newname)
1350 1354  {
1351 1355          struct renamearg ra;
1352 1356          int err;
1353 1357  
1354 1358          /* new parent should exist */
1355 1359          err = dsl_dir_open(newname, FTAG, &ra.newparent, &ra.mynewname);
↓ open down ↓ 61 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX