* Remove a device from the pool. * * Removing a device from the vdev namespace requires several steps * and can take a significant amount of time. As a result we use * the spa_vdev_config_[enter/exit] functions which allow us to * grab and release the spa_config_lock while still holding the namespace * lock. During each step the configuration is synced out. */
| 2185 | * lock. During each step the configuration is synced out. |
| 2186 | */ |
| 2187 | int |
| 2188 | spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare) |
| 2189 | { |
| 2190 | vdev_t *vd; |
| 2191 | nvlist_t **spares, **l2cache, *nv; |
| 2192 | uint64_t txg = 0; |
| 2193 | uint_t nspares, nl2cache; |
| 2194 | int error = 0, error_log; |
| 2195 | boolean_t locked = MUTEX_HELD(&spa_namespace_lock); |
| 2196 | sysevent_t *ev = NULL; |
| 2197 | char *vd_type = NULL, *vd_path = NULL; |
| 2198 | |
| 2199 | ASSERT(spa_writeable(spa)); |
| 2200 | |
| 2201 | if (!locked) |
| 2202 | txg = spa_vdev_enter(spa); |
| 2203 | |
| 2204 | ASSERT(MUTEX_HELD(&spa_namespace_lock)); |
| 2205 | if (spa_feature_is_active(spa, SPA_FEATURE_POOL_CHECKPOINT)) { |
| 2206 | error = (spa_has_checkpoint(spa)) ? |
| 2207 | ZFS_ERR_CHECKPOINT_EXISTS : ZFS_ERR_DISCARDING_CHECKPOINT; |
| 2208 | |
| 2209 | if (!locked) |
| 2210 | return (spa_vdev_exit(spa, NULL, txg, error)); |
| 2211 | |
| 2212 | return (error); |
| 2213 | } |
| 2214 | |
| 2215 | vd = spa_lookup_by_guid(spa, guid, B_FALSE); |
| 2216 | |
| 2217 | if (spa->spa_spares.sav_vdevs != NULL && |
| 2218 | nvlist_lookup_nvlist_array(spa->spa_spares.sav_config, |
| 2219 | ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0 && |
| 2220 | (nv = spa_nvlist_lookup_by_guid(spares, nspares, guid)) != NULL) { |
| 2221 | /* |
| 2222 | * Only remove the hot spare if it's not currently in use |
| 2223 | * in this pool. |
| 2224 | */ |
| 2225 | if (vd == NULL || unspare) { |
| 2226 | char *type; |
| 2227 | boolean_t draid_spare = B_FALSE; |
| 2228 | |
| 2229 | if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) |
| 2230 | == 0 && strcmp(type, VDEV_TYPE_DRAID_SPARE) == 0) |
| 2231 | draid_spare = B_TRUE; |
| 2232 | |
| 2233 | if (vd == NULL && draid_spare) { |
| 2234 | error = SET_ERROR(ENOTSUP); |
| 2235 | } else { |
| 2236 | if (vd == NULL) |
| 2237 | vd = spa_lookup_by_guid(spa, |
| 2238 | guid, B_TRUE); |
| 2239 | ev = spa_event_create(spa, vd, NULL, |
| 2240 | ESC_ZFS_VDEV_REMOVE_AUX); |
| 2241 | |
| 2242 | vd_type = VDEV_TYPE_SPARE; |
| 2243 | vd_path = spa_strdup(fnvlist_lookup_string( |
| 2244 | nv, ZPOOL_CONFIG_PATH)); |