]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/dsl_dir.c
OpenZFS 7614, 9064 - zfs device evacuation/removal
[mirror_zfs.git] / module / zfs / dsl_dir.c
index bf130eb990ae9aa59550e6ea9df08fd0608577d0..a866c3074d3c5c83632aaeb1f133dbbfb4b37a01 100644 (file)
@@ -129,6 +129,11 @@ extern inline dsl_dir_phys_t *dsl_dir_phys(dsl_dir_t *dd);
 
 static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
 
+typedef struct ddulrt_arg {
+       dsl_dir_t       *ddulrta_dd;
+       uint64_t        ddlrta_txg;
+} ddulrt_arg_t;
+
 static void
 dsl_dir_evict_async(void *dbu)
 {
@@ -750,6 +755,35 @@ dsl_enforce_ds_ss_limits(dsl_dir_t *dd, zfs_prop_t prop, cred_t *cr)
        return (enforce);
 }
 
+static void
+dsl_dir_update_last_remap_txg_sync(void *varg, dmu_tx_t *tx)
+{
+       ddulrt_arg_t *arg = varg;
+       uint64_t last_remap_txg;
+       dsl_dir_t *dd = arg->ddulrta_dd;
+       objset_t *mos = dd->dd_pool->dp_meta_objset;
+
+       dsl_dir_zapify(dd, tx);
+       if (zap_lookup(mos, dd->dd_object, DD_FIELD_LAST_REMAP_TXG,
+           sizeof (last_remap_txg), 1, &last_remap_txg) != 0 ||
+           last_remap_txg < arg->ddlrta_txg) {
+               VERIFY0(zap_update(mos, dd->dd_object, DD_FIELD_LAST_REMAP_TXG,
+                   sizeof (arg->ddlrta_txg), 1, &arg->ddlrta_txg, tx));
+       }
+}
+
+int
+dsl_dir_update_last_remap_txg(dsl_dir_t *dd, uint64_t txg)
+{
+       ddulrt_arg_t arg;
+       arg.ddulrta_dd = dd;
+       arg.ddlrta_txg = txg;
+
+       return (dsl_sync_task(spa_name(dd->dd_pool->dp_spa),
+           NULL, dsl_dir_update_last_remap_txg_sync, &arg,
+           1, ZFS_SPACE_CHECK_RESERVED));
+}
+
 /*
  * Check if adding additional child filesystem(s) would exceed any filesystem
  * limits or adding additional snapshot(s) would exceed any snapshot limits.
@@ -947,7 +981,6 @@ dsl_dir_is_clone(dsl_dir_t *dd)
            dd->dd_pool->dp_origin_snap->ds_object));
 }
 
-
 uint64_t
 dsl_dir_get_used(dsl_dir_t *dd)
 {
@@ -1042,6 +1075,19 @@ dsl_dir_get_snapshot_count(dsl_dir_t *dd, uint64_t *count)
        }
 }
 
+int
+dsl_dir_get_remaptxg(dsl_dir_t *dd, uint64_t *count)
+{
+       if (dsl_dir_is_zapified(dd)) {
+               objset_t *os = dd->dd_pool->dp_meta_objset;
+               return (zap_lookup(os, dd->dd_object, DD_FIELD_LAST_REMAP_TXG,
+                   sizeof (*count), 1, count));
+       } else {
+               return (ENOENT);
+       }
+
+}
+
 void
 dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv)
 {
@@ -1073,6 +1119,10 @@ dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv)
                dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_SNAPSHOT_COUNT,
                    count);
        }
+       if (dsl_dir_get_remaptxg(dd, &count) == 0) {
+               dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REMAPTXG,
+                   count);
+       }
 
        if (dsl_dir_is_clone(dd)) {
                char buf[ZFS_MAX_DATASET_NAME_LEN];