* Complete the removal of a toplevel vdev. This is called in open * context by the removal thread after we have copied all vdev's data. */
| 1177 | * context by the removal thread after we have copied all vdev's data. |
| 1178 | */ |
| 1179 | static void |
| 1180 | vdev_remove_complete(spa_t *spa) |
| 1181 | { |
| 1182 | uint64_t txg; |
| 1183 | |
| 1184 | /* |
| 1185 | * Wait for any deferred frees to be synced before we call |
| 1186 | * vdev_metaslab_fini() |
| 1187 | */ |
| 1188 | txg_wait_synced(spa->spa_dsl_pool, 0); |
| 1189 | txg = spa_vdev_enter(spa); |
| 1190 | vdev_t *vd = vdev_lookup_top(spa, spa->spa_vdev_removal->svr_vdev_id); |
| 1191 | ASSERT3P(vd->vdev_initialize_thread, ==, NULL); |
| 1192 | ASSERT3P(vd->vdev_trim_thread, ==, NULL); |
| 1193 | ASSERT3P(vd->vdev_autotrim_thread, ==, NULL); |
| 1194 | |
| 1195 | sysevent_t *ev = spa_event_create(spa, vd, NULL, |
| 1196 | ESC_ZFS_VDEV_REMOVE_DEV); |
| 1197 | |
| 1198 | zfs_dbgmsg("finishing device removal for vdev %llu in txg %llu", |
| 1199 | vd->vdev_id, txg); |
| 1200 | |
| 1201 | /* |
| 1202 | * Discard allocation state. |
| 1203 | */ |
| 1204 | if (vd->vdev_mg != NULL) { |
| 1205 | vdev_metaslab_fini(vd); |
| 1206 | metaslab_group_destroy(vd->vdev_mg); |
| 1207 | vd->vdev_mg = NULL; |
| 1208 | spa_log_sm_set_blocklimit(spa); |
| 1209 | } |
| 1210 | ASSERT0(vd->vdev_stat.vs_space); |
| 1211 | ASSERT0(vd->vdev_stat.vs_dspace); |
| 1212 | |
| 1213 | vdev_remove_replace_with_indirect(vd, txg); |
| 1214 | |
| 1215 | /* |
| 1216 | * We now release the locks, allowing spa_sync to run and finish the |
| 1217 | * removal via vdev_remove_complete_sync in syncing context. |
| 1218 | * |
| 1219 | * Note that we hold on to the vdev_t that has been replaced. Since |
| 1220 | * it isn't part of the vdev tree any longer, it can't be concurrently |
| 1221 | * manipulated, even while we don't have the config lock. |
| 1222 | */ |
| 1223 | (void) spa_vdev_exit(spa, NULL, txg, 0); |
| 1224 | |
| 1225 | /* |
| 1226 | * Top ZAP should have been transferred to the indirect vdev in |
| 1227 | * vdev_remove_replace_with_indirect. |
| 1228 | */ |
| 1229 | ASSERT0(vd->vdev_top_zap); |
| 1230 | |
| 1231 | /* |
| 1232 | * Leaf ZAP should have been moved in vdev_remove_replace_with_indirect. |
| 1233 | */ |
| 1234 | ASSERT0(vd->vdev_leaf_zap); |
| 1235 | |
| 1236 | txg = spa_vdev_enter(spa); |
no test coverage detected