diff options
Diffstat (limited to 'module/zfs/zfs_ioctl.c')
-rw-r--r-- | module/zfs/zfs_ioctl.c | 95 |
1 files changed, 93 insertions, 2 deletions
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 047193c61..debe733da 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -204,6 +204,7 @@ #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)); } @@ -3958,6 +3959,91 @@ zfs_ioc_pool_initialize(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl) } /* + * 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) * * innvl may contain name of expected target 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, |