I also just want to understand how the oops can happen :).
The trick is, there are in fact two revoke tables. So the commit code
does the following:
1) It waits until all handles of the running transaction are released
(this is the while loop waiting checking t_updates).
2) It does some cleanup of unused buffers.
3) Switches revoke tables - i.e. journal->j_revoke now points to a
freshly initialized table, the table of the committing transaction is kept
hidden.
4) Transaction state is changed to FLUSH, journal->j_running_transaction
is set to NULL, etc.
5) Data writeout is performed.
6) Saved revoke hash table is written.
After 3), journal_revoke() and journal_revoke_cancel() access the new
hash table and thus have no influence on journal_write_revoke_records(). It
could possibly be that the pointer to the old hash table would be stored in
some local variable - but all the places where we store a pointer to the
hash table seem to be contained inside journal_start(), journal_stop()
pairs (all functions working with hash tables take a transaction handle
as an argument) and because all handles were released at some point in time,
we know that this should not happen either.
I hope it is clearer now. If you still have any questions, please ask.
Honza
--
Jan Kara <jack@suse.cz>
SuSE CR Labs
-