I tested your patch on the current master and confirmed the WAL reduction during HASH index build.
While testing, I noticed a possible small follow-up improvement in HASH overflow handling. Currently, any free overflow page may be reused, which can scatter overflow chains and hurt cache locality. Reusing recently freed overflow pages first could help, without changing WAL behavior or on-disk format.
I would like to work on this as a follow-up enhancement and would welcome any suggestions.
There exists an optimization to index creation process, when we omit to write any WAL for index build. It is currently supported in B Tree, GIN, GiST, spg indexes. It works because we do not need to recover anything if index creation fails, because if was not used by any query. So, the index can be built on-disk, and then, just before making the index alive, we can simply log all pages to WAL.
Hash index currently lacks this optimization. PFA implementation.
During my testing, I checked the amount of WAL generated by index build before and after patch applied. My script was something like:
select pg_current_wal_insert_lsn();
create index on t using hash (i);
select pg_current_wal_insert_lsn();
select pg_lsn_wal_diff(lsn1, lsn2);
Resulting numbers depend on index size, but I got 2.5-3.5 times less WAL with this patch and 8 times less WAL with this patch + wal_compression=on. Index creation time, however, did not change much...
About implementation: These are many types of record that can be generated during index build. I know for sure these are possible (double-checked using pg_waldump):