The cs_LastBlockFile mutex is redundant: all critical sections are already covered by cs_main. This is demonstrated in this patch by replacing all instances of locking cs_LastBlockFile with pairs of AssertLockHeld(::cs_main) and EXCLUSIVE_LOCKS_REQUIRED(::cs_main) annotations. No additional ::cs_main LOCK(...)s are introduced (besides for test-only code).
It is also not clear for which sections cs_LastBlockFile is responsible for. It is annotated for m_blockfile_cursors, but sporadically and inconsistently also covers m_blockfile_info (e.g. in LoadBlockIndexDB).
Since it has no semantic meaning, and seems confusing to developers, remove it.
An alternative to this patch would be expanding the scope of what cs_LastBlockFile covers and turning it into a non-recursive mutex. I prepared such a patch some time ago, but found it unsatisfactory. It was not clear to me if the lock was now covering too much or too little, and its purpose remained unclear. If this patch is accepted, I would expect the project to eventually implement a separate, narrowly-scoped block storage lock to allow for a more parallelizable block processing routine.