From: Jeff King <peff@peff.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org, Michael Haggerty <mhagger@alum.mit.edu>
Subject: Re: [PATCH v3 2/2] lock_ref_sha1_basic: handle REF_NODEREF with invalid refs
Date: Tue, 12 Jan 2016 15:22:52 -0500 [thread overview]
Message-ID: <20160112202251.GA10843@sigill.intra.peff.net> (raw)
In-Reply-To: <xmqqlh7utwki.fsf@gitster.mtv.corp.google.com>
On Tue, Jan 12, 2016 at 11:41:17AM -0800, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
>
> > I also notice that if we are deleting, we _do_ set
> > RESOLVE_REF_NO_RECURSE from the very beginning, which means we would
> > generally not get a valid lock->old_oid.hash for a symref. But I'm not
> > sure what it would mean to delete a symref while asking for its current
> > value (it cannot have one!). So I don't think it is a bug.
>
> I started scratching my head after noticing that the NO_RECURSE bit
> set in the DELETING codepath before reading the above, and I am
> still doing so.
>
> A transaction that attempts to delete an existing symref presumably
> wants to make sure that the "old" value it read hasn't changed, but
> ensuring the object name (obtained by reading the ref that is
> pointed by the symref by dereferencing) are the same is not the
> right way to ensure nobody raced with us in the meantime anyway (we
> should rather be making sure that the symref is still pointing at
> the same ref), so in that sense, in the context of acquiring the
> lock, old oid value is meaningless for symrefs.
Right, that's the point I was trying to make. Though I think there is
something even more subtle going in (see the end of this message).
In theory you might want the old sha1 for logging purposes, but since we
delete the reflog along with the symref, I don't think it matters there,
either.
I'm not sure we actually delete symrefs very often, though. Grepping for
delete_ref and REF_NODEREF shows the callers expecting symrefs to mostly
be "git remote", which never passes in an old_sha1.
The only caller which does so is "branch -d", but I think it doesn't
affect symrefs. It gets the "old" sha1 by calling resolve_ref_unsafe()
itself with RESOLVE_REF_NO_RECURSE, so it will unconditionally remove a
symref you ask it to, even if somebody else raced and put something in
it.
You can also call "update-ref --no-ref -d" with an "old" sha1, but I
doubt anyone ever does so.
> This patch is a strict improvement as the behaviour for REF_DELETING
> case is unchanged by it (an idempotent resolve-ref-unsafe may be
> called one more time in some cases), and other cases are better, I
> think.
Yeah. My gut feeling is that the REF_DELETING special-handling of
REF_NODEREF could just be folded into what I've added in this series.
But absent a case that is demonstrably broken, I'm inclined not to muck
with it too much.
I had thought that this:
git init
git commit --allow-empty -m foo
git symbolic-ref refs/foo refs/heads/master
old=$(git rev-parse foo)
git update-ref --no-deref -d refs/foo $old
might trigger a problem (because reading refs/foo with NODEREF will give
us a blank sha1 to compare against). But of course that is nonsense. The
actual lock verification is not done by this initial resolve_ref. It
happens _after_ we take the lock (as it must to avoid races), when
verify_lock() calls read_ref_full().
But now I'm doubly confused. When we call read_ref_full(), it is _also_
into lock->old_oid.hash. Which should be overwriting what the earlier
resolve_ref_unsafe() wrote into it. Which would mean my whole commit is
wrong; we can just unconditionally do a non-recursive resolution in the
first place. But when I did so, I ended up with funny reflog values
(which is why I wrote the patch as I did).
Let me try to dig a little further into that case and see what is going
on.
-Peff
next prev parent reply other threads:[~2016-01-12 20:23 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-11 15:46 [PATCH 0/2] fix corner case with lock_ref_sha1_basic and REF_NODEREF Jeff King
2016-01-11 15:49 ` [PATCH 1/2] checkout,clone: check return value of create_symref Jeff King
2016-01-12 4:09 ` Michael Haggerty
2016-01-12 9:49 ` Jeff King
2016-01-11 15:52 ` [PATCH 2/2] lock_ref_sha1_basic: handle REF_NODEREF with invalid refs Jeff King
2016-01-11 18:28 ` Junio C Hamano
2016-01-12 4:55 ` Michael Haggerty
2016-01-12 9:52 ` Jeff King
2016-01-12 18:11 ` Junio C Hamano
2016-01-12 9:56 ` [PATCH v2 0/2] fix corner case with lock_ref_sha1_basic and REF_NODEREF Jeff King
2016-01-12 9:57 ` [PATCH v2 1/2] checkout,clone: check return value of create_symref Jeff King
2016-01-12 9:58 ` [PATCH v2 2/2] lock_ref_sha1_basic: handle REF_NODEREF with invalid refs Jeff King
2016-01-12 13:26 ` Jeff King
2016-01-12 13:55 ` [PATCH v3 " Jeff King
2016-01-12 19:41 ` Junio C Hamano
2016-01-12 20:22 ` Jeff King [this message]
2016-01-12 20:42 ` Jeff King
2016-01-12 21:43 ` [PATCH v4 0/3] fix corner cases with lock_ref_sha1_basic Jeff King
2016-01-12 21:44 ` [PATCH 1/3] checkout,clone: check return value of create_symref Jeff King
2016-01-12 21:44 ` [PATCH 2/3] lock_ref_sha1_basic: always fill old_oid while holding lock Jeff King
2016-01-13 1:25 ` Eric Sunshine
2016-01-13 11:38 ` Jeff King
2016-01-12 21:45 ` [PATCH 3/3] lock_ref_sha1_basic: handle REF_NODEREF with invalid refs Jeff King
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160112202251.GA10843@sigill.intra.peff.net \
--to=peff@peff.net \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=mhagger@alum.mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).