Thread (125 messages) flat view 125 messages, 6 authors, 2021-08-30

Re: [PATCH v4 27/28] reftable: fixup for new base topic 2/3

From: Ævar Arnfjörð Bjarmason <hidden>
Date: 2021-08-30 14:08:24

On Mon, Aug 30 2021, Han-Wen Nienhuys wrote:
On Mon, Aug 30, 2021 at 3:22 PM Ævar Arnfjörð Bjarmason
[off-list ref] wrote:
quoted
But we will need at least the optimistic locking of code like
builtin/reflog.c wanting to do an expiry, and deciding whether to do
that expiry based on a given state of the ref/reflog. I.e. we don't
want:

    1. Start reflog expiry
    2. Code in builtin/reflog.c looks up the OID
    3. Code in builtin/reflog.c decides whether expire the reflog
    4. Concurrent with #4, another writer updates the ref/reflog pair
    5. Code in builtin/reflog.c says "OK, expire it!"
    6. Reftable queues a delete/prune of the reflog per #5.

This would be a sequente of updates to the ref/reflog, none of whom were
racy as far as the reftable semantics itself are concerneb, but where
we'd do the wrong thing because the writer thought we had A when we
really had B. So we need the equivalent of an "git update-ref" with the
"<oldvalue>".

Is there a better way to do that in this case that I'm missing?
I spent some more time looking at builtin/reflog.c, but I am still not
100% sure what the locking is used for.

From a quick glance, the OID goes into tip_commit, and tip_commit goes
into a reachable list (?). The reachable list is then for something,
but I can't really tell what.

In your example with 1.-6., it's still not clear to me what the
undesired behavior is precisely. If the reflog is pruned in #6, is the
worry that the update in #4 is pruned immediately after being
effected?
Yes, I think so. But I'm not sure. I skimmed the code quickly today, and
when I wrote the referenced series didn't focus much on the nitty-gritty
of the builtin/reflog.c behavior other than assuring myself that I was
doing the exact same thing as before as far as its logic was concerned.

I.e. it always locked at a given OID. Before my in-flight "reflog
expire: don't lock reflogs using previously seen OI" it might not lock
but get this error:

    error: cannot lock ref '<refname>': ref '<refname>' is at <OID-A> but expected <OID-B>

But at least it wouldn't do anything, but the current code does require
the passed-in OID. See the code that needs "unreachable_expire_kind" and
"tip_commit".

Perhaps that whole thing can also be refactored somehow. If I change the
"commit = lookup_commit(the_repository, oid);" in
"reflog_expiry_prepare()" to just "commit = NULL" all tests pass, but
that might just be missing test coverage in the face of same race...
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help