diff mbox series

[1/2] pack-write.c: rename `.idx` file into place last

Message ID ea3b1a0d8edd7b6179f305349bb316be7ff92e18.1630461918.git.me@ttaylorr.com (mailing list archive)
State New, archived
Headers show
Series pack-write,repack: prevent opening packs too early | expand

Commit Message

Taylor Blau Sept. 1, 2021, 2:06 a.m. UTC
We treat the presence of an `.idx` file as the indicator of whether or
not it's safe to use a packfile. But `finish_tmp_packfile()` (which is
responsible for writing the pack and moving the temporary versions of
all of its auxiliary files into place) is inconsistent about the write
order.

But the `.rev` file is moved into place after the `.idx`, so it's
possible for a process to open a pack in between the two (i.e., while
the `.idx` file is in place but the `.rev` file is not) and mistakenly
fall back to generating the pack's reverse index in memory. Though racy,
this amounts to an unnecessary slow-down at worst, and doesn't affect
the correctness of the resulting reverse index.

Close this race by moving the .rev file into place before moving the
.idx file into place.

While we're here, only call strbuf_setlen() if we actually modified the
buffer by bringing it inside of the same if-statement that calls
rename().

Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
The diff is a little inscrutable here, since it shows the .idx hunk
moving below the .rev hunk (instead of the .rev hunk moving above the
.idx one), but the end-result is the same.

 pack-write.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

--
2.33.0.96.g73915697e6
diff mbox series

Patch

diff --git a/pack-write.c b/pack-write.c
index f1fc3ecafa..277c60165e 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -490,18 +490,18 @@  void finish_tmp_packfile(struct strbuf *name_buffer,

 	strbuf_setlen(name_buffer, basename_len);

-	strbuf_addf(name_buffer, "%s.idx", hash_to_hex(hash));
-	if (rename(idx_tmp_name, name_buffer->buf))
-		die_errno("unable to rename temporary index file");
-
-	strbuf_setlen(name_buffer, basename_len);
-
 	if (rev_tmp_name) {
 		strbuf_addf(name_buffer, "%s.rev", hash_to_hex(hash));
 		if (rename(rev_tmp_name, name_buffer->buf))
 			die_errno("unable to rename temporary reverse-index file");
+
+		strbuf_setlen(name_buffer, basename_len);
 	}

+	strbuf_addf(name_buffer, "%s.idx", hash_to_hex(hash));
+	if (rename(idx_tmp_name, name_buffer->buf))
+		die_errno("unable to rename temporary index file");
+
 	strbuf_setlen(name_buffer, basename_len);

 	free((void *)idx_tmp_name);