]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/zfs_ioctl.c
Fix typo/etc in module/zfs/zfs_ctldir.c
[mirror_zfs.git] / module / zfs / zfs_ioctl.c
index 047193c61412ef6678143f724cf83085f4c96384..debe733dab7ca672be1be721080d3d114455260e 100644 (file)
 #include <sys/zfs_sysfs.h>
 #include <sys/vdev_impl.h>
 #include <sys/vdev_initialize.h>
+#include <sys/vdev_trim.h>
 
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
@@ -3885,7 +3886,7 @@ zfs_ioc_destroy(zfs_cmd_t *zc)
 
 /*
  * innvl: {
- *     "initialize_command" -> POOL_INITIALIZE_{CANCEL|DO|SUSPEND} (uint64)
+ *     "initialize_command" -> POOL_INITIALIZE_{CANCEL|START|SUSPEND} (uint64)
  *     "initialize_vdevs": { -> guids to initialize (nvlist)
  *         "vdev_path_1": vdev_guid_1, (uint64),
  *         "vdev_path_2": vdev_guid_2, (uint64),
@@ -3919,7 +3920,7 @@ zfs_ioc_pool_initialize(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
        }
 
        if (!(cmd_type == POOL_INITIALIZE_CANCEL ||
-           cmd_type == POOL_INITIALIZE_DO ||
+           cmd_type == POOL_INITIALIZE_START ||
            cmd_type == POOL_INITIALIZE_SUSPEND)) {
                return (SET_ERROR(EINVAL));
        }
@@ -3957,6 +3958,91 @@ zfs_ioc_pool_initialize(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
        return (total_errors > 0 ? EINVAL : 0);
 }
 
+/*
+ * innvl: {
+ *     "trim_command" -> POOL_TRIM_{CANCEL|START|SUSPEND} (uint64)
+ *     "trim_vdevs": { -> guids to TRIM (nvlist)
+ *         "vdev_path_1": vdev_guid_1, (uint64),
+ *         "vdev_path_2": vdev_guid_2, (uint64),
+ *         ...
+ *     },
+ *     "trim_rate" -> Target TRIM rate in bytes/sec.
+ *     "trim_secure" -> Set to request a secure TRIM.
+ * }
+ *
+ * outnvl: {
+ *     "trim_vdevs": { -> TRIM errors (nvlist)
+ *         "vdev_path_1": errno, see function body for possible errnos (uint64)
+ *         "vdev_path_2": errno, ... (uint64)
+ *         ...
+ *     }
+ * }
+ *
+ * EINVAL is returned for an unknown commands or if any of the provided vdev
+ * guids have be specified with a type other than uint64.
+ */
+static const zfs_ioc_key_t zfs_keys_pool_trim[] = {
+       {ZPOOL_TRIM_COMMAND,    DATA_TYPE_UINT64,               0},
+       {ZPOOL_TRIM_VDEVS,      DATA_TYPE_NVLIST,               0},
+       {ZPOOL_TRIM_RATE,       DATA_TYPE_UINT64,               ZK_OPTIONAL},
+       {ZPOOL_TRIM_SECURE,     DATA_TYPE_BOOLEAN_VALUE,        ZK_OPTIONAL},
+};
+
+static int
+zfs_ioc_pool_trim(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
+{
+       uint64_t cmd_type;
+       if (nvlist_lookup_uint64(innvl, ZPOOL_TRIM_COMMAND, &cmd_type) != 0)
+               return (SET_ERROR(EINVAL));
+
+       if (!(cmd_type == POOL_TRIM_CANCEL ||
+           cmd_type == POOL_TRIM_START ||
+           cmd_type == POOL_TRIM_SUSPEND)) {
+               return (SET_ERROR(EINVAL));
+       }
+
+       nvlist_t *vdev_guids;
+       if (nvlist_lookup_nvlist(innvl, ZPOOL_TRIM_VDEVS, &vdev_guids) != 0)
+               return (SET_ERROR(EINVAL));
+
+       for (nvpair_t *pair = nvlist_next_nvpair(vdev_guids, NULL);
+           pair != NULL; pair = nvlist_next_nvpair(vdev_guids, pair)) {
+               uint64_t vdev_guid;
+               if (nvpair_value_uint64(pair, &vdev_guid) != 0) {
+                       return (SET_ERROR(EINVAL));
+               }
+       }
+
+       /* Optional, defaults to maximum rate when not provided */
+       uint64_t rate;
+       if (nvlist_lookup_uint64(innvl, ZPOOL_TRIM_RATE, &rate) != 0)
+               rate = 0;
+
+       /* Optional, defaults to standard TRIM when not provided */
+       boolean_t secure;
+       if (nvlist_lookup_boolean_value(innvl, ZPOOL_TRIM_SECURE,
+           &secure) != 0) {
+               secure = B_FALSE;
+       }
+
+       spa_t *spa;
+       int error = spa_open(poolname, &spa, FTAG);
+       if (error != 0)
+               return (error);
+
+       nvlist_t *vdev_errlist = fnvlist_alloc();
+       int total_errors = spa_vdev_trim(spa, vdev_guids, cmd_type,
+           rate, !!zfs_trim_metaslab_skip, secure, vdev_errlist);
+
+       if (fnvlist_size(vdev_errlist) > 0)
+               fnvlist_add_nvlist(outnvl, ZPOOL_TRIM_VDEVS, vdev_errlist);
+
+       fnvlist_free(vdev_errlist);
+
+       spa_close(spa, FTAG);
+       return (total_errors > 0 ? EINVAL : 0);
+}
+
 /*
  * fsname is name of dataset to rollback (to most recent snapshot)
  *
@@ -6580,6 +6666,11 @@ zfs_ioctl_init(void)
            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE,
            zfs_keys_pool_initialize, ARRAY_SIZE(zfs_keys_pool_initialize));
 
+       zfs_ioctl_register("trim", ZFS_IOC_POOL_TRIM,
+           zfs_ioc_pool_trim, zfs_secpolicy_config, POOL_NAME,
+           POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE,
+           zfs_keys_pool_trim, ARRAY_SIZE(zfs_keys_pool_trim));
+
        /* IOCTLS that use the legacy function signature */
 
        zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,