neo4j/neo4j — pull request #3271 by chrisvest (2014-10-13 11:08:10+00:00)
Title: [2.2] Fix a page cache bug that can lead to lost updates

The problem was in the MuninnPageCache#evictPages method, in that we released the write lock on the newly evicted page before we attempted to grab the write lock on the translation table, for removing the evicted page. This left open a window where another thread can do a look-up in the translation table, observe the page that we have just evicted, complete a page fault, and then the eviction thread would get the lock on the translation table and remove the page that was just faulted in. This is the bug.

Later, another thread would find that the translation table does not have an entry for the page it wants, so it faults it in. Now we have two cache pages that are bound to the same file pages. If both are written two, then one will overwrite the other when they are evicted. This is the symptom we observed in our tests.

This PR furthermore increases the potential parallelism of page faulting by releasing the write lock on the translation table sooner. This way, other page faults to the same stripe can proceed, while page faults and lookups for the specific page will wait like they've always done. Except now they're waiting on the lock on the page itself, instead of waiting on the lock for the translation table. We ensure this by grabbing the write lock on the page we are faulting into, before we add it to the translation table and release the lock on the translation table.