hammer2 - Correct allocator race and related corruption
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 12 Apr 2019 02:04:56 +0000 (19:04 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 12 Apr 2019 02:04:56 +0000 (19:04 -0700)
commit83815ec6515002d007c3800cb9fd83c9451852f7
tree53b5daf0eb0c7c374eb91062bac076c043e1b19a
parenta9924455589c1d8637b153d2585287798cd75cfd
hammer2 - Correct allocator race and related corruption

* When allocating fragments (below 16KB), for example 1K directory
  entries, 1K inodes, compressed file blocks that happen to be
  fragments, or end-of-file fragments, the allocator must ensure
  that any partially freed block is set back to fully allocated.

* In this specific case the allocator was not setting the
  correct bits in the freemap.  The situation never occurs
  on a block boundary (different code is executed which does
  the correct calculation), so the related block will always
  be in a minimally allocated state (either partially allocated
  or fully allocated).

  This means that the corruption can only happen under the specific
  circumstance where a fragment is allocated out of a block that
  the bulkfree code is simultaneously trying to free (marking it
  partially-allocated).  Because the wrong bits are set, the NEXT
  bulkfree pass can also miss the fact that the fragment is
  allocated and finish transitioning the block from partially-
  allocated to fully-free.

  A later allocation then corrupts the block, resulting in CHECK
  errors on the console.

* Because the bulkfree code always comes in and in ALL SITUATIONS OTHER
  THAN THIS SPECIFIC RACE will re-mark the blocks fully-allocated,
  the corruption can ONLY occur during heavy write activity during
  a bulkfree operation, typically when heavy manipulation of directory
  entries or inodes occurs.

* Correct the fragmentary bitmap calculation to set the proper
  bits.
sys/vfs/hammer2/hammer2_bulkfree.c
sys/vfs/hammer2/hammer2_freemap.c