Correct, good catch.
> The current limit_deferred_allocs calls flush_deferred_allocs that
> does not set barrier in the commit block. This does not look right.
> As I understand, we should always call commit_transaction(sb, 1)
> after flush_deferred_allocs. I.e., why not merge flush_deferred_allocs
> and commit_deferred_allocs() into one function?
You are right, this was fuzzy thinking on my part. I think the
limit_deferred_allocs logic needs to move into commit_transaction.
I will apply your version of the patch tomorrow, fix that and post
it.
> The commit_deferred_allocs() function writes all of chunks recorded
> in the deferred_alloc to disk. It then sets sb->deferred_allocs to zero
> and then calls commit_transaction with barrier parameter set to 1. The
> problem is that in this case, sb->defer.count can be non-zero. So the
> commit_deferred_allocs() function does not flush all of the deferred
> allocated chunks to disk. This can cause problems in journal replay.
> I guess one way to fix the problem is to add a commit_transactions(sb, 0)
> at the beginning of commit_deferred_allocs() so that there is no pending
> deferred alloc during the flush.
That was intentional: the transaction that flushes deferred allocs
can itself defer a new allocation. I saw no reason not to allow this.
But the logic is subtle indeed and I could easily have made a mistake
in the implementation. It seems ok, but let me fix up the other thing
first so we can discuss this additional "feature" in isolation.
(Once again, good spotting.)
> Another problem is that we clear SB_BUSY at the beginning of cleanup()
> without flushing dirty buffers and deferred allocs to disk. We will NOT call
> replay_journal if the server dies right after this. I think we should add
> commit_deferred_allocs before clearing the SB_BUSY flag in cleanup().
That was all messed up as we discussed earlier today. In fact,
flush_buffers should never be used any more, it is always wrong. So we
need a cleanup patch to remove and remaining uses and delete it.
Daniel
It is not the most obscure code I have seen, or even the most
obscure code in that file (find_victim might qualify for that).
One excessively obscure bit:
"for (length -= n; ..."
I decremented length there just because n will be destroyed by the
loop. A little too terse.
One boneheaded thing I did was, I should not have called _from_range
twice, I should have had just one allocation function that wraps back
to the beginning of the bitmap when necessary. I don't know what I
was thinking when I did that, but of course it is easiest to leave it
as is for now. Maybe add a FIXME.
Daniel