]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/zfs_ioctl.c
OpenZFS 7614, 9064 - zfs device evacuation/removal
[mirror_zfs.git] / module / zfs / zfs_ioctl.c
index 1e987dc885c494aaab42ad6676d2dfe206a945ca..b1ac149b38af200071f6e9663fc6c31921cf76ec 100644 (file)
 #include <sys/zfeature.h>
 #include <sys/zcp.h>
 #include <sys/zio_checksum.h>
+#include <sys/vdev_removal.h>
 
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
@@ -1048,6 +1049,14 @@ zfs_secpolicy_bookmark(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
        return (error);
 }
 
+/* ARGSUSED */
+static int
+zfs_secpolicy_remap(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
+{
+       return (zfs_secpolicy_write_perms(zc->zc_name,
+           ZFS_DELEG_PERM_REMAP, cr));
+}
+
 /* ARGSUSED */
 static int
 zfs_secpolicy_destroy_bookmarks(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
@@ -1920,8 +1929,8 @@ zfs_ioc_vdev_add(zfs_cmd_t *zc)
 /*
  * inputs:
  * zc_name             name of the pool
- * zc_nvlist_conf      nvlist of devices to remove
- * zc_cookie           to stop the remove?
+ * zc_guid             guid of vdev to remove
+ * zc_cookie           cancel removal
  */
 static int
 zfs_ioc_vdev_remove(zfs_cmd_t *zc)
@@ -1932,7 +1941,11 @@ zfs_ioc_vdev_remove(zfs_cmd_t *zc)
        error = spa_open(zc->zc_name, &spa, FTAG);
        if (error != 0)
                return (error);
-       error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE);
+       if (zc->zc_cookie != 0) {
+               error = spa_vdev_remove_cancel(spa);
+       } else {
+               error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE);
+       }
        spa_close(spa, FTAG);
        return (error);
 }
@@ -2920,7 +2933,7 @@ zfs_ioc_pool_set_props(zfs_cmd_t *zc)
                mutex_enter(&spa_namespace_lock);
                if ((spa = spa_lookup(zc->zc_name)) != NULL) {
                        spa_configfile_set(spa, props, B_FALSE);
-                       spa_config_sync(spa, B_FALSE, B_TRUE);
+                       spa_write_cachefile(spa, B_FALSE, B_TRUE);
                }
                mutex_exit(&spa_namespace_lock);
                if (spa != NULL) {
@@ -3395,6 +3408,17 @@ zfs_ioc_clone(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
        return (error);
 }
 
+/* ARGSUSED */
+static int
+zfs_ioc_remap(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
+{
+       if (strchr(fsname, '@') ||
+           strchr(fsname, '%'))
+               return (SET_ERROR(EINVAL));
+
+       return (dmu_objset_remap_indirects(fsname));
+}
+
 /*
  * innvl: {
  *     "snaps" -> { snapshot1, snapshot2 }
@@ -6339,6 +6363,10 @@ zfs_ioctl_init(void)
            zfs_ioc_clone, zfs_secpolicy_create_clone, DATASET_NAME,
            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
 
+       zfs_ioctl_register("remap", ZFS_IOC_REMAP,
+           zfs_ioc_remap, zfs_secpolicy_remap, DATASET_NAME,
+           POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_TRUE);
+
        zfs_ioctl_register("destroy_snaps", ZFS_IOC_DESTROY_SNAPS,
            zfs_ioc_destroy_snaps, zfs_secpolicy_destroy_snaps, POOL_NAME,
            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);