From: Patrick Steinhardt <ps@pks.im>
To: Christian Couder <christian.couder@gmail.com>
Cc: git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>
Subject: Re: [PATCH v2 6/6] odb/source-files: only reload alternates when the file has changed
Date: Tue, 27 Oct 2026 14:15:01 +0100 [thread overview]
Message-ID: <auCj1VesUFVBtT5P@pks.im> (raw)
In-Reply-To: <CAP8UFD3XSQXFAiqGEp++=Y_OmEhogDo77t-XRFYAu_1yOQc+Gw@mail.gmail.com>
On Tue, Oct 27, 2026 at 12:22:50PM +0100, Christian Couder wrote:
> On Fri, Oct 23, 2026 at 2:48 PM Patrick Steinhardt <ps@pks.im> wrote:
>
> > -static int read_alternates(const char *object_dir, struct strvec *out)
> > +static void read_alternates(const char *object_dir, struct strvec *out,
> > + struct stat_validity *validity)
> > {
> > struct strbuf buf = STRBUF_INIT;
> > char *path;
> >
> > path = xstrfmt("%s/info/alternates", object_dir);
> > - if (strbuf_read_file(&buf, path, 1024) < 0) {
> > - warn_on_fopen_errors(path);
> > - free(path);
> > - return 0;
> > + if (!validity || !stat_validity_check(validity, path)) {
> > + bool successful = false;
> > + int fd;
> > +
> > + fd = open(path, O_RDONLY);
> > + if (fd < 0) {
> > + warn_on_fopen_errors(path);
> > + } else if (strbuf_read(&buf, fd, 1024) < 0) {
>
> Here we start reading from the alternates file, but that file could
> start to be written to...
>
> > + warning_errno(_("unable to read alternates file '%s'"),
> > + path);
> > + } else {
> > + parse_alternates(buf.buf, '\n', object_dir, out);
>
> ...suppose we parse the old content of the file (which calls
> strbuf_realpath() for each entry and so does a few syscalls) while an
> in-place rewrite of the file, like the:
>
> `echo "$PWD/alternate/.git/objects" >repo/.git/objects/info/alternates`
>
> in the new t1006 test added by patch 3/6, happens...
>
> > + successful = true;
> > + }
> > +
> > + if (validity) {
> > + if (successful)
> > + stat_validity_update(validity, fd);
>
> ...then we would update the validity while the alternates file's
> content has changed (and we only parsed its old content).
>
> So, if the file content is not changed after that, we never parse the
> content of the file from the in-place rewrite.
>
> (If the rewrite is not an in-place one, but the file is for example
> replaced through a lock file and rename, the race doesn't happen.)
>
> It seems to me that if we want to avoid a race here, we should have
> the `stat_validity_update(..., fd);` call before reading from fd like
> in "refs/packed-backend.c" and "shallow.c".
>
> > + else
> > + stat_validity_clear(validity);
> > + }
> > +
> > + if (fd >= 0)
> > + close(fd);
>
> It looks like v1 didn't have this issue, as it called
> stat_validity_update() before reading. A concurrent rewrite then only
> caused a spurious re-read on the next check. So I wonder if we could
> keep that order, and just clear the validity when reading fails, which
> would also address Junio's point:
>
> fd = open(path, O_RDONLY);
> if (fd < 0) {
> warn_on_fopen_errors(path);
> } else {
> if (validity)
> stat_validity_update(validity, fd);
> if (strbuf_read(&buf, fd, 1024) < 0) {
> warning_errno(_("unable to read
> alternates file '%s'"),
> path);
> if (validity)
> stat_validity_clear(validity);
> } else {
> parse_alternates(buf.buf, '\n', object_dir, out);
> }
> close(fd);
> }
Hmm, that's fair. I don't think that we should worry too much about
in-place updates when concurrent processes are active as this is
inherently broken already. That process may see any in-between state,
and that may or may not result in something sensible. But fixing this is
easy enough.
Your proposed variant is subtly broken because you don't clear the stat
cache in the case where open(3p) itself fails. But I'll adapt that a bit
and then include this in the next version.
Thanks!
Patrick
next prev parent reply other threads:[~2026-10-27 13:15 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 8:54 [PATCH 0/4] odb/files: reload alternates on retry again Patrick Steinhardt
2026-10-20 8:54 ` [PATCH 1/4] odb/source-files: rename alternates-related functions Patrick Steinhardt
2026-10-20 8:54 ` [PATCH 2/4] odb/source-files: reload alternates on retry Patrick Steinhardt
2026-10-21 14:32 ` Christian Couder
2026-10-23 11:57 ` Patrick Steinhardt
2026-10-20 8:54 ` [PATCH 3/4] odb/source-files: avoid rechecking already-known alternates Patrick Steinhardt
2026-10-20 8:54 ` [PATCH 4/4] odb/source-files: only reload alternates when the file has changed Patrick Steinhardt
2026-10-20 19:59 ` Junio C Hamano
2026-10-21 10:17 ` Patrick Steinhardt
2026-10-23 12:47 ` [PATCH v2 0/6] odb/files: reload alternates on retry again Patrick Steinhardt
2026-10-23 12:48 ` [PATCH v2 1/6] odb/source-files: rename alternates-related functions Patrick Steinhardt
2026-10-23 12:48 ` [PATCH v2 2/6] odb/source-files: always load alternates via primary object directory Patrick Steinhardt
2026-10-27 12:20 ` Christian Couder
2026-10-23 12:48 ` [PATCH v2 3/6] odb/source-files: reload alternates on retry Patrick Steinhardt
2026-10-23 12:48 ` [PATCH v2 4/6] odb/source-files: simplify directory duplication detection Patrick Steinhardt
2026-10-27 12:13 ` Christian Couder
2026-10-27 13:14 ` Patrick Steinhardt
2026-10-23 12:48 ` [PATCH v2 5/6] odb/source-files: avoid stat'ing already-known alternates Patrick Steinhardt
2026-10-27 12:36 ` Christian Couder
2026-10-27 13:14 ` Patrick Steinhardt
2026-10-27 14:31 ` Christian Couder
2026-10-28 7:08 ` Patrick Steinhardt
2026-10-23 12:48 ` [PATCH v2 6/6] odb/source-files: only reload alternates when the file has changed Patrick Steinhardt
2026-10-27 11:22 ` Christian Couder
2026-10-27 13:15 ` Patrick Steinhardt [this message]
2026-10-27 12:43 ` [PATCH v2 0/6] odb/files: reload alternates on retry again Christian Couder
2026-10-28 7:11 ` [PATCH v3 " Patrick Steinhardt
2026-10-28 7:11 ` [PATCH v3 1/6] odb/source-files: rename alternates-related functions Patrick Steinhardt
2026-10-28 7:11 ` [PATCH v3 2/6] odb/source-files: always load alternates via primary object directory Patrick Steinhardt
2026-10-28 7:11 ` [PATCH v3 3/6] odb/source-files: reload alternates on retry Patrick Steinhardt
2026-10-28 7:11 ` [PATCH v3 4/6] odb/source-files: simplify directory duplication detection Patrick Steinhardt
2026-10-28 8:59 ` Christian Couder
2026-10-28 9:07 ` Patrick Steinhardt
2026-10-28 16:27 ` Junio C Hamano
2026-10-28 7:11 ` [PATCH v3 5/6] odb/source-files: avoid stat'ing already-known alternates Patrick Steinhardt
2026-10-28 7:11 ` [PATCH v3 6/6] odb/source-files: only reload alternates when the file has changed Patrick Steinhardt
2026-10-28 16:12 ` [PATCH v3 0/6] odb/files: reload alternates on retry again Junio C Hamano
2026-10-29 8:37 ` Patrick Steinhardt
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=auCj1VesUFVBtT5P@pks.im \
--to=ps@pks.im \
--cc=christian.couder@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.