| 928 | } |
| 929 | |
| 930 | void |
| 931 | vdev_free(vdev_t *vd) |
| 932 | { |
| 933 | spa_t *spa = vd->vdev_spa; |
| 934 | |
| 935 | ASSERT3P(vd->vdev_initialize_thread, ==, NULL); |
| 936 | ASSERT3P(vd->vdev_trim_thread, ==, NULL); |
| 937 | ASSERT3P(vd->vdev_autotrim_thread, ==, NULL); |
| 938 | ASSERT3P(vd->vdev_rebuild_thread, ==, NULL); |
| 939 | |
| 940 | /* |
| 941 | * Scan queues are normally destroyed at the end of a scan. If the |
| 942 | * queue exists here, that implies the vdev is being removed while |
| 943 | * the scan is still running. |
| 944 | */ |
| 945 | if (vd->vdev_scan_io_queue != NULL) { |
| 946 | mutex_enter(&vd->vdev_scan_io_queue_lock); |
| 947 | dsl_scan_io_queue_destroy(vd->vdev_scan_io_queue); |
| 948 | vd->vdev_scan_io_queue = NULL; |
| 949 | mutex_exit(&vd->vdev_scan_io_queue_lock); |
| 950 | } |
| 951 | |
| 952 | /* |
| 953 | * vdev_free() implies closing the vdev first. This is simpler than |
| 954 | * trying to ensure complicated semantics for all callers. |
| 955 | */ |
| 956 | vdev_close(vd); |
| 957 | |
| 958 | ASSERT(!list_link_active(&vd->vdev_config_dirty_node)); |
| 959 | ASSERT(!list_link_active(&vd->vdev_state_dirty_node)); |
| 960 | |
| 961 | /* |
| 962 | * Free all children. |
| 963 | */ |
| 964 | for (int c = 0; c < vd->vdev_children; c++) |
| 965 | vdev_free(vd->vdev_child[c]); |
| 966 | |
| 967 | ASSERT(vd->vdev_child == NULL); |
| 968 | ASSERT(vd->vdev_guid_sum == vd->vdev_guid); |
| 969 | |
| 970 | if (vd->vdev_ops->vdev_op_fini != NULL) |
| 971 | vd->vdev_ops->vdev_op_fini(vd); |
| 972 | |
| 973 | /* |
| 974 | * Discard allocation state. |
| 975 | */ |
| 976 | if (vd->vdev_mg != NULL) { |
| 977 | vdev_metaslab_fini(vd); |
| 978 | metaslab_group_destroy(vd->vdev_mg); |
| 979 | vd->vdev_mg = NULL; |
| 980 | } |
| 981 | |
| 982 | ASSERT0(vd->vdev_stat.vs_space); |
| 983 | ASSERT0(vd->vdev_stat.vs_dspace); |
| 984 | ASSERT0(vd->vdev_stat.vs_alloc); |
| 985 | |
| 986 | /* |
| 987 | * Remove this vdev from its parent's child list. |
no test coverage detected