Partial fix for #130007.
The catalog tree mutex would be set in `catalog_tree()` and
`invalidate_catalog_tree()`. The former could end up adding catalogs and thus
calling `invalidate_catalog_tree()`, which would attempt to set a mutex that the
caller set already. This seems like a good use-case for `std::recursive_mutex`.
would make sure there's a catalog for each catalog path by calling
`create_missing_catalogs()`