9dbd8ee116
Before this change in vdev_insert() we would avoid inserting a duplicate vdev to the list of children, however this duplicate being unlinked from the parent is still stored on the global list with initialized v_guid. Such leaked duplicate can later be returned by vdev_find(). After6dd0803ffdsuch leaked vdev may be freed or pointing to a freed parent, which leads to a loader crash. Note that the leak problem was there before6dd0803ffd. First, in vdev_insert() free conflicting vdev and return the existing one. Update callers accordingly. There is only one caller that actually may encounter this condition. Second, eliminate global list of vdevs and make vdev_find() to work recursively on the tree that a caller must provide. Of course, a chance of GUID collision between members of different pools is extremely low. The main motivation here is just to increase code robustness and fully isolate the data structures of different pools being tasted by the loader, and make easier debugging of bugs like the one being fixed. Reviewed by: mav, imp Differential Revision: https://reviews.freebsd.org/D51912 Fixes:6dd0803ffd