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_dataset.c
          +++ new/usr/src/uts/common/fs/zfs/dsl_dataset.c
↓ open down ↓ 906 lines elided ↑ open up ↑
 907  907                  dsl_dataset_rele(ds, FTAG);
 908  908          }
 909  909  
 910  910          return (dsobj);
 911  911  }
 912  912  
 913  913  /*
 914  914   * The snapshots must all be in the same pool.
 915  915   */
 916  916  int
 917      -dmu_snapshots_destroy_nvl(nvlist_t *snaps, boolean_t defer, char *failed)
      917 +dmu_snapshots_destroy_nvl(nvlist_t *snaps, boolean_t defer,
      918 +    nvlist_t *errlist)
 918  919  {
 919  920          int err;
 920  921          dsl_sync_task_t *dst;
 921  922          spa_t *spa;
 922  923          nvpair_t *pair;
 923  924          dsl_sync_task_group_t *dstg;
 924  925  
 925  926          pair = nvlist_next_nvpair(snaps, NULL);
 926  927          if (pair == NULL)
 927  928                  return (0);
↓ open down ↓ 14 lines elided ↑ open up ↑
 942  943                          dsl_dataset_make_exclusive(ds, dstg);
 943  944                          dsda = kmem_zalloc(sizeof (struct dsl_ds_destroyarg),
 944  945                              KM_SLEEP);
 945  946                          dsda->ds = ds;
 946  947                          dsda->defer = defer;
 947  948                          dsl_sync_task_create(dstg, dsl_dataset_destroy_check,
 948  949                              dsl_dataset_destroy_sync, dsda, dstg, 0);
 949  950                  } else if (err == ENOENT) {
 950  951                          err = 0;
 951  952                  } else {
 952      -                        (void) strcpy(failed, nvpair_name(pair));
      953 +                        fnvlist_add_int32(errlist, nvpair_name(pair), err);
 953  954                          break;
 954  955                  }
 955  956          }
 956  957  
 957  958          if (err == 0)
 958  959                  err = dsl_sync_task_group_wait(dstg);
 959  960  
 960  961          for (dst = list_head(&dstg->dstg_tasks); dst;
 961  962              dst = list_next(&dstg->dstg_tasks, dst)) {
 962  963                  struct dsl_ds_destroyarg *dsda = dst->dst_arg1;
 963  964                  dsl_dataset_t *ds = dsda->ds;
 964  965  
 965  966                  /*
 966      -                 * Return the file system name that triggered the error
      967 +                 * Return the snapshots that triggered the error.
 967  968                   */
 968      -                if (dst->dst_err) {
 969      -                        dsl_dataset_name(ds, failed);
      969 +                if (dst->dst_err != 0) {
      970 +                        char name[ZFS_MAXNAMELEN];
      971 +                        dsl_dataset_name(ds, name);
      972 +                        fnvlist_add_int32(errlist, name, dst->dst_err);
 970  973                  }
 971  974                  ASSERT3P(dsda->rm_origin, ==, NULL);
 972  975                  dsl_dataset_disown(ds, dstg);
 973  976                  kmem_free(dsda, sizeof (struct dsl_ds_destroyarg));
 974  977          }
 975  978  
 976  979          dsl_sync_task_group_destroy(dstg);
 977  980          spa_close(spa, FTAG);
 978  981          return (err);
 979  982  
↓ open down ↓ 58 lines elided ↑ open up ↑
1038 1041   */
1039 1042  int
1040 1043  dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer)
1041 1044  {
1042 1045          int err;
1043 1046          dsl_sync_task_group_t *dstg;
1044 1047          objset_t *os;
1045 1048          dsl_dir_t *dd;
1046 1049          uint64_t obj;
1047 1050          struct dsl_ds_destroyarg dsda = { 0 };
1048      -        dsl_dataset_t dummy_ds = { 0 };
1049 1051  
1050 1052          dsda.ds = ds;
1051 1053  
1052 1054          if (dsl_dataset_is_snapshot(ds)) {
1053 1055                  /* Destroying a snapshot is simpler */
1054 1056                  dsl_dataset_make_exclusive(ds, tag);
1055 1057  
1056 1058                  dsda.defer = defer;
1057 1059                  err = dsl_sync_task_do(ds->ds_dir->dd_pool,
1058 1060                      dsl_dataset_destroy_check, dsl_dataset_destroy_sync,
1059 1061                      &dsda, tag, 0);
1060 1062                  ASSERT3P(dsda.rm_origin, ==, NULL);
1061 1063                  goto out;
1062 1064          } else if (defer) {
1063 1065                  err = EINVAL;
1064 1066                  goto out;
1065 1067          }
1066 1068  
1067 1069          dd = ds->ds_dir;
1068      -        dummy_ds.ds_dir = dd;
1069      -        dummy_ds.ds_object = ds->ds_object;
1070 1070  
1071 1071          /*
1072 1072           * Check for errors and mark this ds as inconsistent, in
1073 1073           * case we crash while freeing the objects.
1074 1074           */
1075 1075          err = dsl_sync_task_do(dd->dd_pool, dsl_dataset_destroy_begin_check,
1076 1076              dsl_dataset_destroy_begin_sync, ds, NULL, 0);
1077 1077          if (err)
1078 1078                  goto out;
1079 1079  
↓ open down ↓ 66 lines elided ↑ open up ↑
1146 1146                          if (err) {
1147 1147                                  dsl_dir_close(dd, FTAG);
1148 1148                                  goto out;
1149 1149                          }
1150 1150                  }
1151 1151  
1152 1152                  dstg = dsl_sync_task_group_create(ds->ds_dir->dd_pool);
1153 1153                  dsl_sync_task_create(dstg, dsl_dataset_destroy_check,
1154 1154                      dsl_dataset_destroy_sync, &dsda, tag, 0);
1155 1155                  dsl_sync_task_create(dstg, dsl_dir_destroy_check,
1156      -                    dsl_dir_destroy_sync, &dummy_ds, FTAG, 0);
     1156 +                    dsl_dir_destroy_sync, dd, FTAG, 0);
1157 1157                  err = dsl_sync_task_group_wait(dstg);
1158 1158                  dsl_sync_task_group_destroy(dstg);
1159 1159  
1160 1160                  /*
1161 1161                   * We could be racing against 'zfs release' or 'zfs destroy -d'
1162 1162                   * on the origin snap, in which case we can get EBUSY if we
1163 1163                   * needed to destroy the origin snap but were not ready to
1164 1164                   * do so.
1165 1165                   */
1166 1166                  if (dsda.need_prep) {
↓ open down ↓ 154 lines elided ↑ open up ↑
1321 1321                  return (EEXIST);
1322 1322  
1323 1323          return (0);
1324 1324  }
1325 1325  
1326 1326  /* ARGSUSED */
1327 1327  static void
1328 1328  dsl_dataset_destroy_begin_sync(void *arg1, void *arg2, dmu_tx_t *tx)
1329 1329  {
1330 1330          dsl_dataset_t *ds = arg1;
1331      -        dsl_pool_t *dp = ds->ds_dir->dd_pool;
1332 1331  
1333 1332          /* Mark it as inconsistent on-disk, in case we crash */
1334 1333          dmu_buf_will_dirty(ds->ds_dbuf, tx);
1335 1334          ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
1336 1335  
1337      -        spa_history_log_internal(LOG_DS_DESTROY_BEGIN, dp->dp_spa, tx,
1338      -            "dataset = %llu", ds->ds_object);
     1336 +        spa_history_log_internal_ds(ds, "destroy begin", tx, "");
1339 1337  }
1340 1338  
1341 1339  static int
1342 1340  dsl_dataset_origin_check(struct dsl_ds_destroyarg *dsda, void *tag,
1343 1341      dmu_tx_t *tx)
1344 1342  {
1345 1343          dsl_dataset_t *ds = dsda->ds;
1346 1344          dsl_dataset_t *ds_prev = ds->ds_prev;
1347 1345  
1348 1346          if (dsl_dataset_might_destroy_origin(ds_prev)) {
↓ open down ↓ 304 lines elided ↑ open up ↑
1653 1651          ASSERT(ds->ds_owner || wont_destroy);
1654 1652          ASSERT(dsda->defer || ds->ds_phys->ds_num_children <= 1);
1655 1653          ASSERT(ds->ds_prev == NULL ||
1656 1654              ds->ds_prev->ds_phys->ds_next_snap_obj != ds->ds_object);
1657 1655          ASSERT3U(ds->ds_phys->ds_bp.blk_birth, <=, tx->tx_txg);
1658 1656  
1659 1657          if (wont_destroy) {
1660 1658                  ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
1661 1659                  dmu_buf_will_dirty(ds->ds_dbuf, tx);
1662 1660                  ds->ds_phys->ds_flags |= DS_FLAG_DEFER_DESTROY;
     1661 +                spa_history_log_internal_ds(ds, "defer_destroy", tx, "");
1663 1662                  return;
1664 1663          }
1665 1664  
     1665 +        /* We need to log before removing it from the namespace. */
     1666 +        spa_history_log_internal_ds(ds, "destroy", tx, "");
     1667 +
1666 1668          /* signal any waiters that this dataset is going away */
1667 1669          mutex_enter(&ds->ds_lock);
1668 1670          ds->ds_owner = dsl_reaper;
1669 1671          cv_broadcast(&ds->ds_exclusive_cv);
1670 1672          mutex_exit(&ds->ds_lock);
1671 1673  
1672 1674          /* Remove our reservation */
1673 1675          if (ds->ds_reserved != 0) {
1674 1676                  dsl_prop_setarg_t psa;
1675 1677                  uint64_t value = 0;
↓ open down ↓ 274 lines elided ↑ open up ↑
1950 1952  #endif
1951 1953                  err = dsl_dataset_snap_remove(ds_head, ds->ds_snapname, tx);
1952 1954                  ASSERT(err == 0);
1953 1955                  dsl_dataset_rele(ds_head, FTAG);
1954 1956          }
1955 1957  
1956 1958          if (ds_prev && ds->ds_prev != ds_prev)
1957 1959                  dsl_dataset_rele(ds_prev, FTAG);
1958 1960  
1959 1961          spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
1960      -        spa_history_log_internal(LOG_DS_DESTROY, dp->dp_spa, tx,
1961      -            "dataset = %llu", ds->ds_object);
1962 1962  
1963 1963          if (ds->ds_phys->ds_next_clones_obj != 0) {
1964 1964                  uint64_t count;
1965 1965                  ASSERT(0 == zap_count(mos,
1966 1966                      ds->ds_phys->ds_next_clones_obj, &count) && count == 0);
1967 1967                  VERIFY(0 == dmu_object_free(mos,
1968 1968                      ds->ds_phys->ds_next_clones_obj, tx));
1969 1969          }
1970 1970          if (ds->ds_phys->ds_props_obj != 0)
1971 1971                  VERIFY(0 == zap_destroy(mos, ds->ds_phys->ds_props_obj, tx));
↓ open down ↓ 27 lines elided ↑ open up ↑
1999 1999           * If there's an fs-only reservation, any blocks that might become
2000 2000           * owned by the snapshot dataset must be accommodated by space
2001 2001           * outside of the reservation.
2002 2002           */
2003 2003          ASSERT(ds->ds_reserved == 0 || DS_UNIQUE_IS_ACCURATE(ds));
2004 2004          asize = MIN(ds->ds_phys->ds_unique_bytes, ds->ds_reserved);
2005 2005          if (asize > dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE))
2006 2006                  return (ENOSPC);
2007 2007  
2008 2008          /*
2009      -         * Propogate any reserved space for this snapshot to other
     2009 +         * Propagate any reserved space for this snapshot to other
2010 2010           * snapshot checks in this sync group.
2011 2011           */
2012 2012          if (asize > 0)
2013 2013                  dsl_dir_willuse_space(ds->ds_dir, asize, tx);
2014 2014  
2015 2015          return (0);
2016 2016  }
2017 2017  
2018 2018  int
2019      -dsl_dataset_snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
     2019 +dsl_dataset_snapshot_check(dsl_dataset_t *ds, const char *snapname,
     2020 +    dmu_tx_t *tx)
2020 2021  {
2021      -        dsl_dataset_t *ds = arg1;
2022      -        const char *snapname = arg2;
2023 2022          int err;
2024 2023          uint64_t value;
2025 2024  
2026 2025          /*
2027 2026           * We don't allow multiple snapshots of the same txg.  If there
2028 2027           * is already one, try again.
2029 2028           */
2030 2029          if (ds->ds_phys->ds_prev_snap_txg >= tx->tx_txg)
2031 2030                  return (EAGAIN);
2032 2031  
2033 2032          /*
2034      -         * Check for conflicting name snapshot name.
     2033 +         * Check for conflicting snapshot name.
2035 2034           */
2036 2035          err = dsl_dataset_snap_lookup(ds, snapname, &value);
2037 2036          if (err == 0)
2038 2037                  return (EEXIST);
2039 2038          if (err != ENOENT)
2040 2039                  return (err);
2041 2040  
2042 2041          /*
2043 2042           * Check that the dataset's name is not too long.  Name consists
2044 2043           * of the dataset's length + 1 for the @-sign + snapshot name's length
↓ open down ↓ 3 lines elided ↑ open up ↑
2048 2047  
2049 2048          err = dsl_dataset_snapshot_reserve_space(ds, tx);
2050 2049          if (err)
2051 2050                  return (err);
2052 2051  
2053 2052          ds->ds_trysnap_txg = tx->tx_txg;
2054 2053          return (0);
2055 2054  }
2056 2055  
2057 2056  void
2058      -dsl_dataset_snapshot_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     2057 +dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *snapname,
     2058 +    dmu_tx_t *tx)
2059 2059  {
2060      -        dsl_dataset_t *ds = arg1;
2061      -        const char *snapname = arg2;
2062 2060          dsl_pool_t *dp = ds->ds_dir->dd_pool;
2063 2061          dmu_buf_t *dbuf;
2064 2062          dsl_dataset_phys_t *dsphys;
2065 2063          uint64_t dsobj, crtxg;
2066 2064          objset_t *mos = dp->dp_meta_objset;
2067 2065          int err;
2068 2066  
2069 2067          ASSERT(RW_WRITE_HELD(&dp->dp_config_rwlock));
2070 2068  
2071 2069          /*
↓ open down ↓ 85 lines elided ↑ open up ↑
2157 2155  
2158 2156          if (ds->ds_prev)
2159 2157                  dsl_dataset_drop_ref(ds->ds_prev, ds);
2160 2158          VERIFY(0 == dsl_dataset_get_ref(dp,
2161 2159              ds->ds_phys->ds_prev_snap_obj, ds, &ds->ds_prev));
2162 2160  
2163 2161          dsl_scan_ds_snapshotted(ds, tx);
2164 2162  
2165 2163          dsl_dir_snap_cmtime_update(ds->ds_dir);
2166 2164  
2167      -        spa_history_log_internal(LOG_DS_SNAPSHOT, dp->dp_spa, tx,
2168      -            "dataset = %llu", dsobj);
     2165 +        spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, "");
2169 2166  }
2170 2167  
2171 2168  void
2172 2169  dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx)
2173 2170  {
2174 2171          ASSERT(dmu_tx_is_syncing(tx));
2175 2172          ASSERT(ds->ds_objset != NULL);
2176 2173          ASSERT(ds->ds_phys->ds_next_snap_obj == 0);
2177 2174  
2178 2175          /*
↓ open down ↓ 66 lines elided ↑ open up ↑
2245 2242          nvlist_free(val);
2246 2243          nvlist_free(propval);
2247 2244          rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
2248 2245  }
2249 2246  
2250 2247  void
2251 2248  dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
2252 2249  {
2253 2250          uint64_t refd, avail, uobjs, aobjs, ratio;
2254 2251  
2255      -        dsl_dir_stats(ds->ds_dir, nv);
     2252 +        ratio = ds->ds_phys->ds_compressed_bytes == 0 ? 100 :
     2253 +            (ds->ds_phys->ds_uncompressed_bytes * 100 /
     2254 +            ds->ds_phys->ds_compressed_bytes);
     2255 +
     2256 +        dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio);
     2257 +
     2258 +        if (dsl_dataset_is_snapshot(ds)) {
     2259 +                dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio);
     2260 +                dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
     2261 +                    ds->ds_phys->ds_unique_bytes);
     2262 +                get_clones_stat(ds, nv);
     2263 +        } else {
     2264 +                dsl_dir_stats(ds->ds_dir, nv);
     2265 +        }
2256 2266  
2257 2267          dsl_dataset_space(ds, &refd, &avail, &uobjs, &aobjs);
2258 2268          dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_AVAILABLE, avail);
2259 2269          dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFERENCED, refd);
2260 2270  
2261 2271          dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_CREATION,
2262 2272              ds->ds_phys->ds_creation_time);
2263 2273          dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_CREATETXG,
2264 2274              ds->ds_phys->ds_creation_txg);
2265 2275          dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFQUOTA,
↓ open down ↓ 24 lines elided ↑ open up ↑
2290 2300                          err = dsl_dataset_space_written(prev, ds, &written,
2291 2301                              &comp, &uncomp);
2292 2302                          dsl_dataset_rele(prev, FTAG);
2293 2303                          if (err == 0) {
2294 2304                                  dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_WRITTEN,
2295 2305                                      written);
2296 2306                          }
2297 2307                  }
2298 2308          }
2299 2309  
2300      -        ratio = ds->ds_phys->ds_compressed_bytes == 0 ? 100 :
2301      -            (ds->ds_phys->ds_uncompressed_bytes * 100 /
2302      -            ds->ds_phys->ds_compressed_bytes);
2303      -        dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio);
2304      -
2305      -        if (ds->ds_phys->ds_next_snap_obj) {
2306      -                /*
2307      -                 * This is a snapshot; override the dd's space used with
2308      -                 * our unique space and compression ratio.
2309      -                 */
2310      -                dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
2311      -                    ds->ds_phys->ds_unique_bytes);
2312      -                dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio);
2313      -
2314      -                get_clones_stat(ds, nv);
2315      -        }
2316 2310  }
2317 2311  
2318 2312  void
2319 2313  dsl_dataset_fast_stat(dsl_dataset_t *ds, dmu_objset_stats_t *stat)
2320 2314  {
2321 2315          stat->dds_creation_txg = ds->ds_phys->ds_creation_txg;
2322 2316          stat->dds_inconsistent = ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT;
2323 2317          stat->dds_guid = ds->ds_phys->ds_guid;
2324      -        if (ds->ds_phys->ds_next_snap_obj) {
     2318 +        stat->dds_origin[0] = '\0';
     2319 +        if (dsl_dataset_is_snapshot(ds)) {
2325 2320                  stat->dds_is_snapshot = B_TRUE;
2326 2321                  stat->dds_num_clones = ds->ds_phys->ds_num_children - 1;
2327 2322          } else {
2328 2323                  stat->dds_is_snapshot = B_FALSE;
2329 2324                  stat->dds_num_clones = 0;
2330      -        }
2331      -
2332      -        /* clone origin is really a dsl_dir thing... */
2333      -        rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
2334      -        if (dsl_dir_is_clone(ds->ds_dir)) {
2335      -                dsl_dataset_t *ods;
2336 2325  
2337      -                VERIFY(0 == dsl_dataset_get_ref(ds->ds_dir->dd_pool,
2338      -                    ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &ods));
2339      -                dsl_dataset_name(ods, stat->dds_origin);
2340      -                dsl_dataset_drop_ref(ods, FTAG);
2341      -        } else {
2342      -                stat->dds_origin[0] = '\0';
     2326 +                rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
     2327 +                if (dsl_dir_is_clone(ds->ds_dir)) {
     2328 +                        dsl_dataset_t *ods;
     2329 +
     2330 +                        VERIFY(0 == dsl_dataset_get_ref(ds->ds_dir->dd_pool,
     2331 +                            ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &ods));
     2332 +                        dsl_dataset_name(ods, stat->dds_origin);
     2333 +                        dsl_dataset_drop_ref(ods, FTAG);
     2334 +                }
     2335 +                rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
2343 2336          }
2344      -        rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
2345 2337  }
2346 2338  
2347 2339  uint64_t
2348 2340  dsl_dataset_fsid_guid(dsl_dataset_t *ds)
2349 2341  {
2350 2342          return (ds->ds_fsid_guid);
2351 2343  }
2352 2344  
2353 2345  void
2354 2346  dsl_dataset_space(dsl_dataset_t *ds,
↓ open down ↓ 96 lines elided ↑ open up ↑
2451 2443          VERIFY(0 == dsl_dataset_get_snapname(ds));
2452 2444          err = dsl_dataset_snap_remove(hds, ds->ds_snapname, tx);
2453 2445          ASSERT3U(err, ==, 0);
2454 2446          mutex_enter(&ds->ds_lock);
2455 2447          (void) strcpy(ds->ds_snapname, newsnapname);
2456 2448          mutex_exit(&ds->ds_lock);
2457 2449          err = zap_add(mos, hds->ds_phys->ds_snapnames_zapobj,
2458 2450              ds->ds_snapname, 8, 1, &ds->ds_object, tx);
2459 2451          ASSERT3U(err, ==, 0);
2460 2452  
2461      -        spa_history_log_internal(LOG_DS_RENAME, dd->dd_pool->dp_spa, tx,
2462      -            "dataset = %llu", ds->ds_object);
     2453 +        spa_history_log_internal_ds(ds, "rename", tx,
     2454 +            "-> @%s", newsnapname);
2463 2455          dsl_dataset_rele(hds, FTAG);
2464 2456  }
2465 2457  
2466 2458  struct renamesnaparg {
2467 2459          dsl_sync_task_group_t *dstg;
2468 2460          char failed[MAXPATHLEN];
2469 2461          char *oldsnap;
2470 2462          char *newsnap;
2471 2463  };
2472 2464  
↓ open down ↓ 459 lines elided ↑ open up ↑
2932 2924              odd->dd_phys->dd_used_breakdown[DD_USED_SNAP];
2933 2925          ASSERT3S(delta, <=, 0);
2934 2926          ASSERT3U(pa->used, >=, -delta);
2935 2927          dsl_dir_diduse_space(odd, DD_USED_SNAP, delta, 0, 0, tx);
2936 2928          dsl_dir_diduse_space(odd, DD_USED_HEAD,
2937 2929              -pa->used - delta, -pa->comp, -pa->uncomp, tx);
2938 2930  
2939 2931          origin_ds->ds_phys->ds_unique_bytes = pa->unique;
2940 2932  
2941 2933          /* log history record */
2942      -        spa_history_log_internal(LOG_DS_PROMOTE, dd->dd_pool->dp_spa, tx,
2943      -            "dataset = %llu", hds->ds_object);
     2934 +        spa_history_log_internal_ds(hds, "promote", tx, "");
2944 2935  
2945 2936          dsl_dir_close(odd, FTAG);
2946 2937  }
2947 2938  
2948 2939  static char *snaplist_tag = "snaplist";
2949 2940  /*
2950 2941   * Make a list of dsl_dataset_t's for the snapshots between first_obj
2951 2942   * (exclusive) and last_obj (inclusive).  The list will be in reverse
2952 2943   * order (last_obj will be the list_head()).  If first_obj == 0, do all
2953 2944   * snapshots back to this dataset's origin.
↓ open down ↓ 337 lines elided ↑ open up ↑
3291 3282          dsl_deadlist_close(&csa->cds->ds_deadlist);
3292 3283          dsl_deadlist_close(&csa->ohds->ds_deadlist);
3293 3284          SWITCH64(csa->ohds->ds_phys->ds_deadlist_obj,
3294 3285              csa->cds->ds_phys->ds_deadlist_obj);
3295 3286          dsl_deadlist_open(&csa->cds->ds_deadlist, dp->dp_meta_objset,
3296 3287              csa->cds->ds_phys->ds_deadlist_obj);
3297 3288          dsl_deadlist_open(&csa->ohds->ds_deadlist, dp->dp_meta_objset,
3298 3289              csa->ohds->ds_phys->ds_deadlist_obj);
3299 3290  
3300 3291          dsl_scan_ds_clone_swapped(csa->ohds, csa->cds, tx);
     3292 +
     3293 +        spa_history_log_internal_ds(csa->cds, "clone swap", tx,
     3294 +            "parent=%s", csa->ohds->ds_dir->dd_myname);
3301 3295  }
3302 3296  
3303 3297  /*
3304 3298   * Swap 'clone' with its origin head datasets.  Used at the end of "zfs
3305 3299   * recv" into an existing fs to swizzle the file system to the new
3306 3300   * version, and by "zfs rollback".  Can also be used to swap two
3307 3301   * independent head datasets if neither has any snapshots.
3308 3302   */
3309 3303  int
3310 3304  dsl_dataset_clone_swap(dsl_dataset_t *clone, dsl_dataset_t *origin_head,
↓ open down ↓ 136 lines elided ↑ open up ↑
3447 3441          dsl_prop_setarg_t *psa = arg2;
3448 3442          uint64_t effective_value = psa->psa_effective_value;
3449 3443  
3450 3444          dsl_prop_set_sync(ds, psa, tx);
3451 3445          DSL_PROP_CHECK_PREDICTION(ds->ds_dir, psa);
3452 3446  
3453 3447          if (ds->ds_quota != effective_value) {
3454 3448                  dmu_buf_will_dirty(ds->ds_dbuf, tx);
3455 3449                  ds->ds_quota = effective_value;
3456 3450  
3457      -                spa_history_log_internal(LOG_DS_REFQUOTA,
3458      -                    ds->ds_dir->dd_pool->dp_spa, tx, "%lld dataset = %llu ",
3459      -                    (longlong_t)ds->ds_quota, ds->ds_object);
     3451 +                spa_history_log_internal_ds(ds, "set refquota", tx,
     3452 +                    "refquota=%lld", (longlong_t)ds->ds_quota);
3460 3453          }
3461 3454  }
3462 3455  
3463 3456  int
3464 3457  dsl_dataset_set_quota(const char *dsname, zprop_source_t source, uint64_t quota)
3465 3458  {
3466 3459          dsl_dataset_t *ds;
3467 3460          dsl_prop_setarg_t psa;
3468 3461          int err;
3469 3462  
↓ open down ↓ 84 lines elided ↑ open up ↑
3554 3547          ASSERT(DS_UNIQUE_IS_ACCURATE(ds));
3555 3548          unique = ds->ds_phys->ds_unique_bytes;
3556 3549          delta = MAX(0, (int64_t)(effective_value - unique)) -
3557 3550              MAX(0, (int64_t)(ds->ds_reserved - unique));
3558 3551          ds->ds_reserved = effective_value;
3559 3552          mutex_exit(&ds->ds_lock);
3560 3553  
3561 3554          dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV, delta, 0, 0, tx);
3562 3555          mutex_exit(&ds->ds_dir->dd_lock);
3563 3556  
3564      -        spa_history_log_internal(LOG_DS_REFRESERV,
3565      -            ds->ds_dir->dd_pool->dp_spa, tx, "%lld dataset = %llu",
3566      -            (longlong_t)effective_value, ds->ds_object);
     3557 +        spa_history_log_internal_ds(ds, "set refreservation", tx,
     3558 +            "refreservation=%lld", (longlong_t)effective_value);
3567 3559  }
3568 3560  
3569 3561  int
3570 3562  dsl_dataset_set_reservation(const char *dsname, zprop_source_t source,
3571 3563      uint64_t reservation)
3572 3564  {
3573 3565          dsl_dataset_t *ds;
3574 3566          dsl_prop_setarg_t psa;
3575 3567          int err;
3576 3568  
↓ open down ↓ 45 lines elided ↑ open up ↑
3622 3614  /*
3623 3615   * If you add new checks here, you may need to add
3624 3616   * additional checks to the "temporary" case in
3625 3617   * snapshot_check() in dmu_objset.c.
3626 3618   */
3627 3619  static int
3628 3620  dsl_dataset_user_hold_check(void *arg1, void *arg2, dmu_tx_t *tx)
3629 3621  {
3630 3622          dsl_dataset_t *ds = arg1;
3631 3623          struct dsl_ds_holdarg *ha = arg2;
3632      -        char *htag = ha->htag;
     3624 +        const char *htag = ha->htag;
3633 3625          objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
3634 3626          int error = 0;
3635 3627  
3636 3628          if (spa_version(ds->ds_dir->dd_pool->dp_spa) < SPA_VERSION_USERREFS)
3637 3629                  return (ENOTSUP);
3638 3630  
3639 3631          if (!dsl_dataset_is_snapshot(ds))
3640 3632                  return (EINVAL);
3641 3633  
3642 3634          /* tags must be unique */
↓ open down ↓ 13 lines elided ↑ open up ↑
3656 3648                  error = E2BIG;
3657 3649  
3658 3650          return (error);
3659 3651  }
3660 3652  
3661 3653  void
3662 3654  dsl_dataset_user_hold_sync(void *arg1, void *arg2, dmu_tx_t *tx)
3663 3655  {
3664 3656          dsl_dataset_t *ds = arg1;
3665 3657          struct dsl_ds_holdarg *ha = arg2;
3666      -        char *htag = ha->htag;
     3658 +        const char *htag = ha->htag;
3667 3659          dsl_pool_t *dp = ds->ds_dir->dd_pool;
3668 3660          objset_t *mos = dp->dp_meta_objset;
3669 3661          uint64_t now = gethrestime_sec();
3670 3662          uint64_t zapobj;
3671 3663  
3672 3664          mutex_enter(&ds->ds_lock);
3673 3665          if (ds->ds_phys->ds_userrefs_obj == 0) {
3674 3666                  /*
3675 3667                   * This is the first user hold for this dataset.  Create
3676 3668                   * the userrefs zap object.
↓ open down ↓ 7 lines elided ↑ open up ↑
3684 3676          ds->ds_userrefs++;
3685 3677          mutex_exit(&ds->ds_lock);
3686 3678  
3687 3679          VERIFY(0 == zap_add(mos, zapobj, htag, 8, 1, &now, tx));
3688 3680  
3689 3681          if (ha->temphold) {
3690 3682                  VERIFY(0 == dsl_pool_user_hold(dp, ds->ds_object,
3691 3683                      htag, &now, tx));
3692 3684          }
3693 3685  
3694      -        spa_history_log_internal(LOG_DS_USER_HOLD,
3695      -            dp->dp_spa, tx, "<%s> temp = %d dataset = %llu", htag,
3696      -            (int)ha->temphold, ds->ds_object);
     3686 +        spa_history_log_internal_ds(ds, "hold", tx,
     3687 +            "tag = %s temp = %d holds now = %llu",
     3688 +            htag, (int)ha->temphold, ds->ds_userrefs);
3697 3689  }
3698 3690  
3699 3691  static int
3700 3692  dsl_dataset_user_hold_one(const char *dsname, void *arg)
3701 3693  {
3702 3694          struct dsl_ds_holdarg *ha = arg;
3703 3695          dsl_dataset_t *ds;
3704 3696          int error;
3705 3697          char *name;
3706 3698  
↓ open down ↓ 186 lines elided ↑ open up ↑
3893 3885  }
3894 3886  
3895 3887  static void
3896 3888  dsl_dataset_user_release_sync(void *arg1, void *tag, dmu_tx_t *tx)
3897 3889  {
3898 3890          struct dsl_ds_releasearg *ra = arg1;
3899 3891          dsl_dataset_t *ds = ra->ds;
3900 3892          dsl_pool_t *dp = ds->ds_dir->dd_pool;
3901 3893          objset_t *mos = dp->dp_meta_objset;
3902 3894          uint64_t zapobj;
3903      -        uint64_t dsobj = ds->ds_object;
3904 3895          uint64_t refs;
3905 3896          int error;
3906 3897  
3907 3898          mutex_enter(&ds->ds_lock);
3908 3899          ds->ds_userrefs--;
3909 3900          refs = ds->ds_userrefs;
3910 3901          mutex_exit(&ds->ds_lock);
3911 3902          error = dsl_pool_user_release(dp, ds->ds_object, ra->htag, tx);
3912 3903          VERIFY(error == 0 || error == ENOENT);
3913 3904          zapobj = ds->ds_phys->ds_userrefs_obj;
↓ open down ↓ 2 lines elided ↑ open up ↑
3916 3907              DS_IS_DEFER_DESTROY(ds)) {
3917 3908                  struct dsl_ds_destroyarg dsda = {0};
3918 3909  
3919 3910                  ASSERT(ra->own);
3920 3911                  dsda.ds = ds;
3921 3912                  dsda.releasing = B_TRUE;
3922 3913                  /* We already did the destroy_check */
3923 3914                  dsl_dataset_destroy_sync(&dsda, tag, tx);
3924 3915          }
3925 3916  
3926      -        spa_history_log_internal(LOG_DS_USER_RELEASE,
3927      -            dp->dp_spa, tx, "<%s> %lld dataset = %llu",
3928      -            ra->htag, (longlong_t)refs, dsobj);
     3917 +        spa_history_log_internal_ds(ds, "release", tx,
     3918 +            "tag = %s refs now = %lld", ra->htag, (longlong_t)refs);
3929 3919  }
3930 3920  
3931 3921  static int
3932 3922  dsl_dataset_user_release_one(const char *dsname, void *arg)
3933 3923  {
3934 3924          struct dsl_ds_holdarg *ha = arg;
3935 3925          struct dsl_ds_releasearg *ra;
3936 3926          dsl_dataset_t *ds;
3937 3927          int error;
3938 3928          void *dtag = ha->dstg;
↓ open down ↓ 375 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX