]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/dsl_dataset.c
OpenZFS 7600 - zfs rollback should pass target snapshot to kernel
[mirror_zfs.git] / module / zfs / dsl_dataset.c
index 5fa04e7ba715e71bdaa5f6bb7e6800c4cb323f33..bd03b486858bd3ba039c957bc5f94839ef13a9a4 100644 (file)
@@ -2210,6 +2210,7 @@ dsl_dataset_handoff_check(dsl_dataset_t *ds, void *owner, dmu_tx_t *tx)
 
 typedef struct dsl_dataset_rollback_arg {
        const char *ddra_fsname;
+       const char *ddra_tosnap;
        void *ddra_owner;
        nvlist_t *ddra_result;
 } dsl_dataset_rollback_arg_t;
@@ -2253,6 +2254,18 @@ dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx)
                return (SET_ERROR(EAGAIN));
        }
 
+       /*
+        * If the expected target snapshot is specified, then check that
+        * the latest snapshot is it.
+        */
+       if (ddra->ddra_tosnap != NULL) {
+               char namebuf[ZFS_MAX_DATASET_NAME_LEN];
+
+               dsl_dataset_name(ds->ds_prev, namebuf);
+               if (strcmp(namebuf, ddra->ddra_tosnap) != 0)
+                       return (SET_ERROR(EXDEV));
+       }
+
        /* must not have any bookmarks after the most recent snapshot */
        proprequest = fnvlist_alloc();
        fnvlist_add_boolean(proprequest, zfs_prop_to_name(ZFS_PROP_CREATETXG));
@@ -2354,11 +2367,13 @@ dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx)
  * notes above zfs_suspend_fs() for further details.
  */
 int
-dsl_dataset_rollback(const char *fsname, void *owner, nvlist_t *result)
+dsl_dataset_rollback(const char *fsname, const char *tosnap, void *owner,
+    nvlist_t *result)
 {
        dsl_dataset_rollback_arg_t ddra;
 
        ddra.ddra_fsname = fsname;
+       ddra.ddra_tosnap = tosnap;
        ddra.ddra_owner = owner;
        ddra.ddra_result = result;