| 7236 | } |
| 7237 | |
| 7238 | static int |
| 7239 | spa_vdev_trim_impl(spa_t *spa, uint64_t guid, uint64_t cmd_type, |
| 7240 | uint64_t rate, boolean_t partial, boolean_t secure, list_t *vd_list) |
| 7241 | { |
| 7242 | ASSERT(MUTEX_HELD(&spa_namespace_lock)); |
| 7243 | |
| 7244 | spa_config_enter(spa, SCL_CONFIG | SCL_STATE, FTAG, RW_READER); |
| 7245 | |
| 7246 | /* Look up vdev and ensure it's a leaf. */ |
| 7247 | vdev_t *vd = spa_lookup_by_guid(spa, guid, B_FALSE); |
| 7248 | if (vd == NULL || vd->vdev_detached) { |
| 7249 | spa_config_exit(spa, SCL_CONFIG | SCL_STATE, FTAG); |
| 7250 | return (SET_ERROR(ENODEV)); |
| 7251 | } else if (!vd->vdev_ops->vdev_op_leaf || !vdev_is_concrete(vd)) { |
| 7252 | spa_config_exit(spa, SCL_CONFIG | SCL_STATE, FTAG); |
| 7253 | return (SET_ERROR(EINVAL)); |
| 7254 | } else if (!vdev_writeable(vd)) { |
| 7255 | spa_config_exit(spa, SCL_CONFIG | SCL_STATE, FTAG); |
| 7256 | return (SET_ERROR(EROFS)); |
| 7257 | } else if (!vd->vdev_has_trim) { |
| 7258 | spa_config_exit(spa, SCL_CONFIG | SCL_STATE, FTAG); |
| 7259 | return (SET_ERROR(EOPNOTSUPP)); |
| 7260 | } else if (secure && !vd->vdev_has_securetrim) { |
| 7261 | spa_config_exit(spa, SCL_CONFIG | SCL_STATE, FTAG); |
| 7262 | return (SET_ERROR(EOPNOTSUPP)); |
| 7263 | } |
| 7264 | mutex_enter(&vd->vdev_trim_lock); |
| 7265 | spa_config_exit(spa, SCL_CONFIG | SCL_STATE, FTAG); |
| 7266 | |
| 7267 | /* |
| 7268 | * When we activate a TRIM action we check to see if the |
| 7269 | * vdev_trim_thread is NULL. We do this instead of using the |
| 7270 | * vdev_trim_state since there might be a previous TRIM process |
| 7271 | * which has completed but the thread is not exited. |
| 7272 | */ |
| 7273 | if (cmd_type == POOL_TRIM_START && |
| 7274 | (vd->vdev_trim_thread != NULL || vd->vdev_top->vdev_removing)) { |
| 7275 | mutex_exit(&vd->vdev_trim_lock); |
| 7276 | return (SET_ERROR(EBUSY)); |
| 7277 | } else if (cmd_type == POOL_TRIM_CANCEL && |
| 7278 | (vd->vdev_trim_state != VDEV_TRIM_ACTIVE && |
| 7279 | vd->vdev_trim_state != VDEV_TRIM_SUSPENDED)) { |
| 7280 | mutex_exit(&vd->vdev_trim_lock); |
| 7281 | return (SET_ERROR(ESRCH)); |
| 7282 | } else if (cmd_type == POOL_TRIM_SUSPEND && |
| 7283 | vd->vdev_trim_state != VDEV_TRIM_ACTIVE) { |
| 7284 | mutex_exit(&vd->vdev_trim_lock); |
| 7285 | return (SET_ERROR(ESRCH)); |
| 7286 | } |
| 7287 | |
| 7288 | switch (cmd_type) { |
| 7289 | case POOL_TRIM_START: |
| 7290 | vdev_trim(vd, rate, partial, secure); |
| 7291 | break; |
| 7292 | case POOL_TRIM_CANCEL: |
| 7293 | vdev_trim_stop(vd, VDEV_TRIM_CANCELED, vd_list); |
| 7294 | break; |
| 7295 | case POOL_TRIM_SUSPEND: |
no test coverage detected