aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--midx.c12
-rw-r--r--packfile.c11
2 files changed, 21 insertions, 2 deletions
diff --git a/midx.c b/midx.c
index 3d0015f782..cd6e766ce2 100644
--- a/midx.c
+++ b/midx.c
@@ -13,6 +13,8 @@
#include "pack-bitmap.h"
#include "pack-revindex.h"
+#define MIDX_PACK_ERROR ((void *)(intptr_t)-1)
+
int midx_checksum_valid(struct multi_pack_index *m);
void clear_midx_files_ext(const char *object_dir, const char *ext,
const char *keep_hash);
@@ -405,7 +407,7 @@ void close_midx(struct multi_pack_index *m)
munmap((unsigned char *)m->data, m->data_len);
for (i = 0; i < m->num_packs; i++) {
- if (m->packs[i])
+ if (m->packs[i] && m->packs[i] != MIDX_PACK_ERROR)
m->packs[i]->multi_pack_index = 0;
}
FREE_AND_NULL(m->packs);
@@ -458,6 +460,8 @@ int prepare_midx_pack(struct repository *r, struct multi_pack_index *m,
pack_int_id = midx_for_pack(&m, pack_int_id);
+ if (m->packs[pack_int_id] == MIDX_PACK_ERROR)
+ return 1;
if (m->packs[pack_int_id])
return 0;
@@ -482,8 +486,10 @@ int prepare_midx_pack(struct repository *r, struct multi_pack_index *m,
strbuf_release(&pack_name);
strbuf_release(&key);
- if (!p)
+ if (!p) {
+ m->packs[pack_int_id] = MIDX_PACK_ERROR;
return 1;
+ }
p->multi_pack_index = 1;
m->packs[pack_int_id] = p;
@@ -495,6 +501,8 @@ struct packed_git *nth_midxed_pack(struct multi_pack_index *m,
uint32_t pack_int_id)
{
uint32_t local_pack_int_id = midx_for_pack(&m, pack_int_id);
+ if (m->packs[local_pack_int_id] == MIDX_PACK_ERROR)
+ return NULL;
return m->packs[local_pack_int_id];
}
diff --git a/packfile.c b/packfile.c
index 80e35f1032..70c7208f02 100644
--- a/packfile.c
+++ b/packfile.c
@@ -737,6 +737,17 @@ struct packed_git *add_packed_git(struct repository *r, const char *path,
p = alloc_packed_git(r, alloc);
memcpy(p->pack_name, path, path_len);
+ /*
+ * Note that we have to check auxiliary data structures before we check
+ * for the ".pack" file to exist to avoid races with a packfile that is
+ * in the process of being deleted. The ".pack" file is unlinked before
+ * its auxiliary data structures, so we know that we either get a
+ * consistent snapshot of all data structures or that we'll fail to
+ * stat(3p) the packfile itself and thus return `NULL`.
+ *
+ * As such, we cannot bail out before the access(3p) calls in case the
+ * packfile doesn't exist without doing two stat(3p) calls for it.
+ */
xsnprintf(p->pack_name + path_len, alloc - path_len, ".keep");
if (!access(p->pack_name, F_OK))
p->pack_keep = 1;