Print this page
8520 lzc_rollback_to should support rolling back to origin
7198 libzfs should gracefully handle EINVAL from lzc_rollback
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Dan McDonald <danmcd@joyent.com>
NEX-9673 Add capability to replicate cloned datasets relative to origin
Reviewed by: Alex Deiter <alex.deiter@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-13340 Continuous replication service may fail if a user removes nested datasets
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-3562 filename normalization doesn't work for removes (sync with upstream)
NEX-9406 Add a property to show that a dataset has been modified since a snapshot
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Revert "NEX-7251 Resume_token is not cleared right after finishing receive"
This reverts commit 9e97a45e8cf6ca59307a39e2d3c11c6e845e4187.
NEX-7251 Resume_token is not cleared right after finishing receive
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
NEX-6815 KRRP: 'sess-send-stop' hangs forever if the sources pool does not have free space
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-5366 Race between unique_insert() and unique_remove() causes ZFS fsid change
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Dan Vatca <dan.vatca@gmail.com>
NEX-5795 Rename 'wrc' as 'wbc' in the source and in the tech docs
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5272 KRRP: replicate snapshot properties
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
6328 Fix cstyle errors in zfs codebase (fix studio)
6328 Fix cstyle errors in zfs codebase
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Jorgen Lundman <lundman@lundman.net>
Approved by: Robert Mustacchi <rm@joyent.com>
2605 want to resume interrupted zfs send
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Xin Li <delphij@freebsd.org>
Reviewed by: Arne Jansen <sensille@gmx.net>
Approved by: Dan McDonald <danmcd@omniti.com>
6160 /usr/lib/fs/zfs/bootinstall should use bootadm
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Reviewed by: Adam Števko <adam.stevko@gmail.com>
Reviewed by: Josef Sipek <jeffpc@josefsipek.net>
Approved by: Richard Lowe <richlowe@richlowe.net>
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R (NULL is not an int)
6171 dsl_prop_unregister() slows down dataset eviction.
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R (fix studio build)
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Garrett D'Amore <garrett@damore.org>
6047 SPARC boot should support feature@embedded_data
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Approved by: Dan McDonald <danmcd@omniti.com>
5959 clean up per-dataset feature count code
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
NEX-4582 update wrc test cases for allow to use write back cache per tree of datasets
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
5960 zfs recv should prefetch indirect blocks
5925 zfs receive -o origin=
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
5909 ensure that shared snap names don't become too long after promotion
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
5393 spurious failures from dsl_dataset_hold_obj()
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Will Andrews <willa@spectralogic.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Steven Hartland <killing@multiplay.co.uk>
Approved by: Dan McDonald <danmcd@omniti.com>
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Revert "NEX-4476 WRC: Allow to use write back cache per tree of datasets"
This reverts commit fe97b74444278a6f36fec93179133641296312da.
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-3964 It should not be allowed to rename a snapshot that its new name is matched to the prefix of in-kernel autosnapshots
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3669 Faults for fans that don't exist
Reviewed by: Jeffry Molanus <jeffry.molanus@nexenta.com>
NEX-3891 Hide the snapshots that belong to in-kernel autosnap-service
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Alek Pinchuk <alek@nexenta.com>
NEX-3329 libnsl: set_up_connection() over TCP does not adhere the specified timeout
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-3521 CLONE - Port NEX-3209 normalization=formD and casesensitivity=mixed behaves improperly, squashing case
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-3558 KRRP Integration
4370 avoid transmitting holes during zfs send
4371 DMU code clean up
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
Approved by: Garrett D'Amore <garrett@damore.org>
re #13318 rb4428 kernel panic during failover with autosync running on the active node
re #12619 rb4429 More dp->dp_config_rwlock holds
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (fix lint -courtesy of Yuri Pankov)
re #12584 rb4049 zfsxx latest code merge (fix lint - courtesy of Yuri Pankov)
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
re 12063 rb 3793 Panic on zpool destroy
Bug 11205: add missing libzfs_closed_stubs.c to fix opensource-only build.
ZFS plus work: special vdevs, cos, cos/vdev properties

@@ -44,19 +44,20 @@
 #include <sys/zfeature.h>
 #include <sys/unique.h>
 #include <sys/zfs_context.h>
 #include <sys/zfs_ioctl.h>
 #include <sys/spa.h>
-#include <sys/vdev.h>
+#include <sys/spa_impl.h>
 #include <sys/zfs_znode.h>
 #include <sys/zfs_onexit.h>
 #include <sys/zvol.h>
 #include <sys/dsl_scan.h>
 #include <sys/dsl_deadlist.h>
 #include <sys/dsl_destroy.h>
 #include <sys/dsl_userhold.h>
 #include <sys/dsl_bookmark.h>
+#include <sys/autosnap.h>
 #include <sys/dmu_send.h>
 #include <sys/zio_checksum.h>
 #include <sys/zio_compress.h>
 #include <zfs_fletcher.h>
 

@@ -80,19 +81,28 @@
 
 #define DS_REF_MAX      (1ULL << 62)
 
 extern inline dsl_dataset_phys_t *dsl_dataset_phys(dsl_dataset_t *ds);
 
-static void dsl_dataset_set_remap_deadlist_object(dsl_dataset_t *ds,
-    uint64_t obj, dmu_tx_t *tx);
-static void dsl_dataset_unset_remap_deadlist_object(dsl_dataset_t *ds,
-    dmu_tx_t *tx);
-
 extern int spa_asize_inflation;
 
 static zil_header_t zero_zil;
 
+kmem_cache_t *zfs_ds_collector_cache = NULL;
+
+zfs_ds_collector_entry_t *
+dsl_dataset_collector_cache_alloc()
+{
+        return (kmem_cache_alloc(zfs_ds_collector_cache, KM_SLEEP));
+}
+
+void
+dsl_dataset_collector_cache_free(zfs_ds_collector_entry_t *entry)
+{
+        kmem_cache_free(zfs_ds_collector_cache, entry);
+}
+
 /*
  * Figure out how much of this delta should be propogated to the dsl_dir
  * layer.  If there's a refreservation, that space has already been
  * partially accounted for in our ancestors.
  */

@@ -158,58 +168,18 @@
             compressed, uncompressed, tx);
         dsl_dir_transfer_space(ds->ds_dir, used - delta,
             DD_USED_REFRSRV, DD_USED_HEAD, tx);
 }
 
-/*
- * Called when the specified segment has been remapped, and is thus no
- * longer referenced in the head dataset.  The vdev must be indirect.
- *
- * If the segment is referenced by a snapshot, put it on the remap deadlist.
- * Otherwise, add this segment to the obsolete spacemap.
- */
-void
-dsl_dataset_block_remapped(dsl_dataset_t *ds, uint64_t vdev, uint64_t offset,
-    uint64_t size, uint64_t birth, dmu_tx_t *tx)
-{
-        spa_t *spa = ds->ds_dir->dd_pool->dp_spa;
-
-        ASSERT(dmu_tx_is_syncing(tx));
-        ASSERT(birth <= tx->tx_txg);
-        ASSERT(!ds->ds_is_snapshot);
-
-        if (birth > dsl_dataset_phys(ds)->ds_prev_snap_txg) {
-                spa_vdev_indirect_mark_obsolete(spa, vdev, offset, size, tx);
-        } else {
-                blkptr_t fakebp;
-                dva_t *dva = &fakebp.blk_dva[0];
-
-                ASSERT(ds != NULL);
-
-                mutex_enter(&ds->ds_remap_deadlist_lock);
-                if (!dsl_dataset_remap_deadlist_exists(ds)) {
-                        dsl_dataset_create_remap_deadlist(ds, tx);
-                }
-                mutex_exit(&ds->ds_remap_deadlist_lock);
-
-                BP_ZERO(&fakebp);
-                fakebp.blk_birth = birth;
-                DVA_SET_VDEV(dva, vdev);
-                DVA_SET_OFFSET(dva, offset);
-                DVA_SET_ASIZE(dva, size);
-
-                dsl_deadlist_insert(&ds->ds_remap_deadlist, &fakebp, tx);
-        }
-}
-
 int
 dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
     boolean_t async)
 {
         int used = bp_get_dsize_sync(tx->tx_pool->dp_spa, bp);
         int compressed = BP_GET_PSIZE(bp);
         int uncompressed = BP_GET_UCSIZE(bp);
+        wbc_data_t *wbc_data = spa_get_wbc_data(tx->tx_pool->dp_spa);
 
         if (BP_IS_HOLE(bp))
                 return (0);
 
         ASSERT(dmu_tx_is_syncing(tx));

@@ -230,10 +200,27 @@
                 int64_t delta;
 
                 dprintf_bp(bp, "freeing ds=%llu", ds->ds_object);
                 dsl_free(tx->tx_pool, tx->tx_txg, bp);
 
+                /* update amount of data which is changed in the window */
+                mutex_enter(&wbc_data->wbc_lock);
+                if (wbc_data->wbc_isvalid &&
+                    bp->blk_birth && wbc_data->wbc_finish_txg &&
+                    bp->blk_birth <= wbc_data->wbc_finish_txg &&
+                    bp->blk_birth >= wbc_data->wbc_start_txg &&
+                    !wbc_data->wbc_purge) {
+
+                        wbc_data->wbc_altered_bytes += used;
+                        if (wbc_data->wbc_altered_limit &&
+                            wbc_data->wbc_altered_bytes >
+                            wbc_data->wbc_altered_limit) {
+                                wbc_purge_window(tx->tx_pool->dp_spa, tx);
+                        }
+                }
+                mutex_exit(&wbc_data->wbc_lock);
+
                 mutex_enter(&ds->ds_lock);
                 ASSERT(dsl_dataset_phys(ds)->ds_unique_bytes >= used ||
                     !DS_UNIQUE_IS_ACCURATE(ds));
                 delta = parent_delta(ds, -used);
                 dsl_dataset_phys(ds)->ds_unique_bytes -= used;

@@ -317,24 +304,21 @@
                 dsl_dataset_rele(ds->ds_prev, ds);
                 ds->ds_prev = NULL;
         }
 
         bplist_destroy(&ds->ds_pending_deadlist);
-        if (dsl_deadlist_is_open(&ds->ds_deadlist))
+        if (ds->ds_deadlist.dl_os != NULL)
                 dsl_deadlist_close(&ds->ds_deadlist);
-        if (dsl_deadlist_is_open(&ds->ds_remap_deadlist))
-                dsl_deadlist_close(&ds->ds_remap_deadlist);
         if (ds->ds_dir)
                 dsl_dir_async_rele(ds->ds_dir, ds);
 
         ASSERT(!list_link_active(&ds->ds_synced_link));
 
         list_destroy(&ds->ds_prop_cbs);
         mutex_destroy(&ds->ds_lock);
         mutex_destroy(&ds->ds_opening_lock);
         mutex_destroy(&ds->ds_sendstream_lock);
-        mutex_destroy(&ds->ds_remap_deadlist_lock);
         refcount_destroy(&ds->ds_longholds);
         rrw_destroy(&ds->ds_bp_rwlock);
 
         kmem_free(ds, sizeof (dsl_dataset_t));
 }

@@ -455,27 +439,19 @@
                 ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
                 ds->ds_dbuf = dbuf;
                 ds->ds_object = dsobj;
                 ds->ds_is_snapshot = dsl_dataset_phys(ds)->ds_num_children != 0;
 
-                err = dsl_dir_hold_obj(dp, dsl_dataset_phys(ds)->ds_dir_obj,
-                    NULL, ds, &ds->ds_dir);
-                if (err != 0) {
-                        kmem_free(ds, sizeof (dsl_dataset_t));
-                        dmu_buf_rele(dbuf, tag);
-                        return (err);
-                }
-
                 mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
                 mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
                 mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
-                mutex_init(&ds->ds_remap_deadlist_lock,
-                    NULL, MUTEX_DEFAULT, NULL);
                 rrw_init(&ds->ds_bp_rwlock, B_FALSE);
                 refcount_create(&ds->ds_longholds);
 
                 bplist_create(&ds->ds_pending_deadlist);
+                dsl_deadlist_open(&ds->ds_deadlist,
+                    mos, dsl_dataset_phys(ds)->ds_deadlist_obj);
 
                 list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t),
                     offsetof(dmu_sendarg_t, dsa_link));
 
                 list_create(&ds->ds_prop_cbs, sizeof (dsl_prop_cb_record_t),

@@ -495,10 +471,24 @@
                                         err = 0;
                                 }
                         }
                 }
 
+                err = dsl_dir_hold_obj(dp,
+                    dsl_dataset_phys(ds)->ds_dir_obj, NULL, ds, &ds->ds_dir);
+                if (err != 0) {
+                        mutex_destroy(&ds->ds_lock);
+                        mutex_destroy(&ds->ds_opening_lock);
+                        mutex_destroy(&ds->ds_sendstream_lock);
+                        refcount_destroy(&ds->ds_longholds);
+                        bplist_destroy(&ds->ds_pending_deadlist);
+                        dsl_deadlist_close(&ds->ds_deadlist);
+                        kmem_free(ds, sizeof (dsl_dataset_t));
+                        dmu_buf_rele(dbuf, tag);
+                        return (err);
+                }
+
                 if (!ds->ds_is_snapshot) {
                         ds->ds_snapname[0] = '\0';
                         if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
                                 err = dsl_dataset_hold_obj(dp,
                                     dsl_dataset_phys(ds)->ds_prev_snap_obj,

@@ -535,29 +525,18 @@
                         }
                 } else {
                         ds->ds_reserved = ds->ds_quota = 0;
                 }
 
-                dsl_deadlist_open(&ds->ds_deadlist,
-                    mos, dsl_dataset_phys(ds)->ds_deadlist_obj);
-                uint64_t remap_deadlist_obj =
-                    dsl_dataset_get_remap_deadlist_object(ds);
-                if (remap_deadlist_obj != 0) {
-                        dsl_deadlist_open(&ds->ds_remap_deadlist, mos,
-                            remap_deadlist_obj);
-                }
-
                 dmu_buf_init_user(&ds->ds_dbu, dsl_dataset_evict_sync,
                     dsl_dataset_evict_async, &ds->ds_dbuf);
                 if (err == 0)
                         winner = dmu_buf_set_user_ie(dbuf, &ds->ds_dbu);
 
                 if (err != 0 || winner != NULL) {
                         bplist_destroy(&ds->ds_pending_deadlist);
                         dsl_deadlist_close(&ds->ds_deadlist);
-                        if (dsl_deadlist_is_open(&ds->ds_remap_deadlist))
-                                dsl_deadlist_close(&ds->ds_remap_deadlist);
                         if (ds->ds_prev)
                                 dsl_dataset_rele(ds->ds_prev, ds);
                         dsl_dir_rele(ds->ds_dir, ds);
                         mutex_destroy(&ds->ds_lock);
                         mutex_destroy(&ds->ds_opening_lock);

@@ -1201,10 +1180,13 @@
         dsl_dataset_snapshot_arg_t *ddsa = arg;
         dsl_pool_t *dp = dmu_tx_pool(tx);
         nvpair_t *pair;
         int rv = 0;
 
+        if (ddsa->ddsa_autosnap && dmu_tx_is_syncing(tx))
+                autosnap_invalidate_list(dp, ddsa->ddsa_snaps);
+
         /*
          * Pre-compute how many total new snapshots will be created for each
          * level in the tree and below. This is needed for validating the
          * snapshot limit when either taking a recursive snapshot or when
          * taking multiple snapshots.

@@ -1341,11 +1323,12 @@
         dsl_pool_t *dp = ds->ds_dir->dd_pool;
         dmu_buf_t *dbuf;
         dsl_dataset_phys_t *dsphys;
         uint64_t dsobj, crtxg;
         objset_t *mos = dp->dp_meta_objset;
-        objset_t *os;
+        objset_t *os = NULL;
+        uint64_t unique_bytes = 0;
 
         ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
 
         /*
          * If we are on an old pool, the zil must not be active, in which

@@ -1446,31 +1429,15 @@
         dsl_deadlist_open(&ds->ds_deadlist, mos,
             dsl_dataset_phys(ds)->ds_deadlist_obj);
         dsl_deadlist_add_key(&ds->ds_deadlist,
             dsl_dataset_phys(ds)->ds_prev_snap_txg, tx);
 
-        if (dsl_dataset_remap_deadlist_exists(ds)) {
-                uint64_t remap_deadlist_obj =
-                    dsl_dataset_get_remap_deadlist_object(ds);
-                /*
-                 * Move the remap_deadlist to the snapshot.  The head
-                 * will create a new remap deadlist on demand, from
-                 * dsl_dataset_block_remapped().
-                 */
-                dsl_dataset_unset_remap_deadlist_object(ds, tx);
-                dsl_deadlist_close(&ds->ds_remap_deadlist);
-
-                dmu_object_zapify(mos, dsobj, DMU_OT_DSL_DATASET, tx);
-                VERIFY0(zap_add(mos, dsobj, DS_FIELD_REMAP_DEADLIST,
-                    sizeof (remap_deadlist_obj), 1, &remap_deadlist_obj, tx));
-        }
-
         ASSERT3U(dsl_dataset_phys(ds)->ds_prev_snap_txg, <, tx->tx_txg);
         dsl_dataset_phys(ds)->ds_prev_snap_obj = dsobj;
         dsl_dataset_phys(ds)->ds_prev_snap_txg = crtxg;
+        unique_bytes = dsl_dataset_phys(ds)->ds_unique_bytes;
         dsl_dataset_phys(ds)->ds_unique_bytes = 0;
-
         if (spa_version(dp->dp_spa) >= SPA_VERSION_UNIQUE_ACCURATE)
                 dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
 
         VERIFY0(zap_add(mos, dsl_dataset_phys(ds)->ds_snapnames_zapobj,
             snapname, 8, 1, &dsobj, tx));

@@ -1483,10 +1450,21 @@
         dsl_scan_ds_snapshotted(ds, tx);
 
         dsl_dir_snap_cmtime_update(ds->ds_dir);
 
         spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, "");
+
+        if (autosnap_check_name(snapname)) {
+                autosnap_create_cb(spa_get_autosnap(dp->dp_spa),
+                    ds, snapname, tx->tx_txg);
+        }
+
+        if (os == NULL)
+                VERIFY0(dmu_objset_from_ds(ds, &os));
+
+        if (os->os_wbc_mode != ZFS_WBC_MODE_OFF)
+                wbc_add_bytes(dp->dp_spa, tx->tx_txg, unique_bytes);
 }
 
 void
 dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx)
 {

@@ -1499,10 +1477,11 @@
                 dsl_dataset_t *ds;
                 char *name, *atp;
                 char dsname[ZFS_MAX_DATASET_NAME_LEN];
 
                 name = nvpair_name(pair);
+
                 atp = strchr(name, '@');
                 (void) strlcpy(dsname, name, atp - name + 1);
                 VERIFY0(dsl_dataset_hold(dp, dsname, FTAG, &ds));
 
                 dsl_dataset_snapshot_sync_impl(ds, atp + 1, tx);

@@ -1566,10 +1545,11 @@
 
         ddsa.ddsa_snaps = snaps;
         ddsa.ddsa_props = props;
         ddsa.ddsa_errors = errors;
         ddsa.ddsa_cr = CRED();
+        ddsa.ddsa_autosnap = B_FALSE;
 
         if (error == 0) {
                 error = dsl_sync_task(firstname, dsl_dataset_snapshot_check,
                     dsl_dataset_snapshot_sync, &ddsa,
                     fnvlist_num_pairs(snaps) * 3, ZFS_SPACE_CHECK_NORMAL);

@@ -2200,10 +2180,23 @@
             dsl_get_compressratio(ds));
         dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
             dsl_get_used(ds));
 
         if (ds->ds_is_snapshot) {
+                dsl_dataset_t *hds = NULL;
+                boolean_t modified = B_FALSE;
+
+                if (dsl_dataset_hold_obj(dp,
+                    dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj,
+                    FTAG, &hds) == 0) {
+                        modified = dsl_dataset_modified_since_snap(hds, ds);
+                        dsl_dataset_rele(hds, FTAG);
+                }
+
+                dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_MODIFIED,
+                    modified ? 1 : 0);
+
                 get_clones_stat(ds, nv);
         } else {
                 char buf[ZFS_MAX_DATASET_NAME_LEN];
                 if (dsl_get_prev_snap(ds, buf) == 0)
                         dsl_prop_nvlist_add_string(nv, ZFS_PROP_PREV_SNAP,

@@ -2277,15 +2270,20 @@
 
         stat->dds_creation_txg = dsl_get_creationtxg(ds);
         stat->dds_inconsistent = dsl_get_inconsistent(ds);
         stat->dds_guid = dsl_get_guid(ds);
         stat->dds_origin[0] = '\0';
+        stat->dds_is_snapshot = B_FALSE;
+        stat->dds_is_autosnapshot = B_FALSE;
         if (ds->ds_is_snapshot) {
+                if (autosnap_is_autosnap(ds))
+                        stat->dds_is_autosnapshot = B_TRUE;
+                else
                 stat->dds_is_snapshot = B_TRUE;
+
                 stat->dds_num_clones = dsl_get_numclones(ds);
         } else {
-                stat->dds_is_snapshot = B_FALSE;
                 stat->dds_num_clones = 0;
 
                 if (dsl_dir_is_clone(ds->ds_dir)) {
                         dsl_dir_get_origin(ds->ds_dir, stat->dds_origin);
                 }

@@ -2398,10 +2396,18 @@
         dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
         dsl_pool_t *dp = dmu_tx_pool(tx);
         dsl_dataset_t *hds;
         int error;
 
+        /* You cannot rename an autosnapshot */
+        if (autosnap_check_name(ddrsa->ddrsa_oldsnapname))
+                return (SET_ERROR(EPERM));
+
+        /* New name cannot match the AUTOSNAP prefix */
+        if (autosnap_check_name(ddrsa->ddrsa_newsnapname))
+                return (SET_ERROR(EPERM));
+
         error = dsl_dataset_hold(dp, ddrsa->ddrsa_fsname, FTAG, &hds);
         if (error != 0)
                 return (error);
 
         if (ddrsa->ddrsa_recursive) {

@@ -3340,45 +3346,10 @@
                 return (SET_ERROR(EDQUOT));
 
         return (0);
 }
 
-static void
-dsl_dataset_swap_remap_deadlists(dsl_dataset_t *clone,
-    dsl_dataset_t *origin, dmu_tx_t *tx)
-{
-        uint64_t clone_remap_dl_obj, origin_remap_dl_obj;
-        dsl_pool_t *dp = dmu_tx_pool(tx);
-
-        ASSERT(dsl_pool_sync_context(dp));
-
-        clone_remap_dl_obj = dsl_dataset_get_remap_deadlist_object(clone);
-        origin_remap_dl_obj = dsl_dataset_get_remap_deadlist_object(origin);
-
-        if (clone_remap_dl_obj != 0) {
-                dsl_deadlist_close(&clone->ds_remap_deadlist);
-                dsl_dataset_unset_remap_deadlist_object(clone, tx);
-        }
-        if (origin_remap_dl_obj != 0) {
-                dsl_deadlist_close(&origin->ds_remap_deadlist);
-                dsl_dataset_unset_remap_deadlist_object(origin, tx);
-        }
-
-        if (clone_remap_dl_obj != 0) {
-                dsl_dataset_set_remap_deadlist_object(origin,
-                    clone_remap_dl_obj, tx);
-                dsl_deadlist_open(&origin->ds_remap_deadlist,
-                    dp->dp_meta_objset, clone_remap_dl_obj);
-        }
-        if (origin_remap_dl_obj != 0) {
-                dsl_dataset_set_remap_deadlist_object(clone,
-                    origin_remap_dl_obj, tx);
-                dsl_deadlist_open(&clone->ds_remap_deadlist,
-                    dp->dp_meta_objset, origin_remap_dl_obj);
-        }
-}
-
 void
 dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
     dsl_dataset_t *origin_head, dmu_tx_t *tx)
 {
         dsl_pool_t *dp = dmu_tx_pool(tx);

@@ -3544,11 +3515,10 @@
             dsl_dataset_phys(clone)->ds_deadlist_obj);
         dsl_deadlist_open(&clone->ds_deadlist, dp->dp_meta_objset,
             dsl_dataset_phys(clone)->ds_deadlist_obj);
         dsl_deadlist_open(&origin_head->ds_deadlist, dp->dp_meta_objset,
             dsl_dataset_phys(origin_head)->ds_deadlist_obj);
-        dsl_dataset_swap_remap_deadlists(clone, origin_head, tx);
 
         dsl_scan_ds_clone_swapped(origin_head, clone, tx);
 
         spa_history_log_internal_ds(clone, "clone swap", tx,
             "parent=%s", origin_head->ds_dir->dd_myname);

@@ -4037,107 +4007,57 @@
         objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
         dmu_object_zapify(mos, ds->ds_object, DMU_OT_DSL_DATASET, tx);
 }
 
 boolean_t
-dsl_dataset_is_zapified(dsl_dataset_t *ds)
+dataset_name_hidden(const char *name)
 {
-        dmu_object_info_t doi;
-
-        dmu_object_info_from_db(ds->ds_dbuf, &doi);
-        return (doi.doi_type == DMU_OTN_ZAP_METADATA);
+        if (strchr(name, '$') != NULL)
+                return (B_TRUE);
+        if (strchr(name, '%') != NULL)
+                return (B_TRUE);
+        if (!INGLOBALZONE(curproc) && !zone_dataset_visible(name, NULL))
+                return (B_TRUE);
+        return (B_FALSE);
 }
 
-boolean_t
-dsl_dataset_has_resume_receive_state(dsl_dataset_t *ds)
-{
-        return (dsl_dataset_is_zapified(ds) &&
-            zap_contains(ds->ds_dir->dd_pool->dp_meta_objset,
-            ds->ds_object, DS_FIELD_RESUME_TOGUID) == 0);
-}
-
 uint64_t
-dsl_dataset_get_remap_deadlist_object(dsl_dataset_t *ds)
+dsl_dataset_creation_txg(const char *name)
 {
-        uint64_t remap_deadlist_obj;
+        dsl_pool_t *dp;
+        dsl_dataset_t *ds;
         int err;
+        uint64_t ret = UINT64_MAX;
 
-        if (!dsl_dataset_is_zapified(ds))
-                return (0);
+        err = dsl_pool_hold(name, FTAG, &dp);
 
-        err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset, ds->ds_object,
-            DS_FIELD_REMAP_DEADLIST, sizeof (remap_deadlist_obj), 1,
-            &remap_deadlist_obj);
+        if (err)
+                return (ret);
 
-        if (err != 0) {
-                VERIFY3S(err, ==, ENOENT);
-                return (0);
+        err = dsl_dataset_hold(dp, name, FTAG, &ds);
+
+        if (!err) {
+                ret = dsl_dataset_phys(ds)->ds_creation_txg;
+                dsl_dataset_rele(ds, FTAG);
         }
 
-        ASSERT(remap_deadlist_obj != 0);
-        return (remap_deadlist_obj);
+        dsl_pool_rele(dp, FTAG);
+
+        return (ret);
 }
 
 boolean_t
-dsl_dataset_remap_deadlist_exists(dsl_dataset_t *ds)
+dsl_dataset_is_zapified(dsl_dataset_t *ds)
 {
-        EQUIV(dsl_deadlist_is_open(&ds->ds_remap_deadlist),
-            dsl_dataset_get_remap_deadlist_object(ds) != 0);
-        return (dsl_deadlist_is_open(&ds->ds_remap_deadlist));
-}
+        dmu_object_info_t doi;
 
-static void
-dsl_dataset_set_remap_deadlist_object(dsl_dataset_t *ds, uint64_t obj,
-    dmu_tx_t *tx)
-{
-        ASSERT(obj != 0);
-        dsl_dataset_zapify(ds, tx);
-        VERIFY0(zap_add(ds->ds_dir->dd_pool->dp_meta_objset, ds->ds_object,
-            DS_FIELD_REMAP_DEADLIST, sizeof (obj), 1, &obj, tx));
+        dmu_object_info_from_db(ds->ds_dbuf, &doi);
+        return (doi.doi_type == DMU_OTN_ZAP_METADATA);
 }
 
-static void
-dsl_dataset_unset_remap_deadlist_object(dsl_dataset_t *ds, dmu_tx_t *tx)
+boolean_t
+dsl_dataset_has_resume_receive_state(dsl_dataset_t *ds)
 {
-        VERIFY0(zap_remove(ds->ds_dir->dd_pool->dp_meta_objset,
-            ds->ds_object, DS_FIELD_REMAP_DEADLIST, tx));
-}
-
-void
-dsl_dataset_destroy_remap_deadlist(dsl_dataset_t *ds, dmu_tx_t *tx)
-{
-        uint64_t remap_deadlist_object;
-        spa_t *spa = ds->ds_dir->dd_pool->dp_spa;
-
-        ASSERT(dmu_tx_is_syncing(tx));
-        ASSERT(dsl_dataset_remap_deadlist_exists(ds));
-
-        remap_deadlist_object = ds->ds_remap_deadlist.dl_object;
-        dsl_deadlist_close(&ds->ds_remap_deadlist);
-        dsl_deadlist_free(spa_meta_objset(spa), remap_deadlist_object, tx);
-        dsl_dataset_unset_remap_deadlist_object(ds, tx);
-        spa_feature_decr(spa, SPA_FEATURE_OBSOLETE_COUNTS, tx);
-}
-
-void
-dsl_dataset_create_remap_deadlist(dsl_dataset_t *ds, dmu_tx_t *tx)
-{
-        uint64_t remap_deadlist_obj;
-        spa_t *spa = ds->ds_dir->dd_pool->dp_spa;
-
-        ASSERT(dmu_tx_is_syncing(tx));
-        ASSERT(MUTEX_HELD(&ds->ds_remap_deadlist_lock));
-        /*
-         * Currently we only create remap deadlists when there are indirect
-         * vdevs with referenced mappings.
-         */
-        ASSERT(spa_feature_is_active(spa, SPA_FEATURE_DEVICE_REMOVAL));
-
-        remap_deadlist_obj = dsl_deadlist_clone(
-            &ds->ds_deadlist, UINT64_MAX,
-            dsl_dataset_phys(ds)->ds_prev_snap_obj, tx);
-        dsl_dataset_set_remap_deadlist_object(ds,
-            remap_deadlist_obj, tx);
-        dsl_deadlist_open(&ds->ds_remap_deadlist, spa_meta_objset(spa),
-            remap_deadlist_obj);
-        spa_feature_incr(spa, SPA_FEATURE_OBSOLETE_COUNTS, tx);
+        return (dsl_dataset_is_zapified(ds) &&
+            zap_contains(ds->ds_dir->dd_pool->dp_meta_objset,
+            ds->ds_object, DS_FIELD_RESUME_TOGUID) == 0);
 }