For VMs a good way would be to use pg_visibility's pg_truncate_visibility_map(), but only for 9.6~.
Ah ok..
For FSM there is no real solution, and actually a pg_truncate_fsm would prove to be useful here.
Right, that's what I proposed as an alternate idea. I agree this is much cleaner and less error prone approach.
Actually, if we could add an API which can truncate FSM to the given heap block, then the user may not even need to run VACUUM, which could be costly for very large tables. Also, AFAICS we will need to backport pg_truncate_visibility_map() to older releases because unless the VM is truncated along with the FSM, VACUUM may not scan all pages and the FSM for those pages won't be recorded.