Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
71c76d4
hashfile: allow skipping the hash function
derrickstolee Oct 21, 2022
030d76f
read-cache: add index.computeHash config option
derrickstolee Oct 24, 2022
4013f99
extensions: add refFormat extension
derrickstolee Oct 10, 2022
0cf6549
config: fix multi-level bulleted list
derrickstolee Nov 3, 2022
3121334
repository: wire ref extensions to ref backends
derrickstolee Oct 24, 2022
531bf1b
refs: allow loose files without packed-refs
derrickstolee Oct 24, 2022
4fcbfed
chunk-format: number of chunks is optional
derrickstolee Nov 1, 2022
a7bf8cb
chunk-format: document trailing table of contents
derrickstolee Nov 1, 2022
ff176b5
chunk-format: store chunk offset during write
derrickstolee Oct 5, 2022
78e585c
chunk-format: allow trailing table of contents
derrickstolee Oct 5, 2022
ebc719f
chunk-format: parse trailing table of contents
derrickstolee Oct 5, 2022
a171a84
refs: extract packfile format to new file
derrickstolee Oct 25, 2022
f141d85
packed-backend: extract add_write_error()
derrickstolee Oct 25, 2022
cca445c
packed-backend: extract iterator/updates merge
derrickstolee Oct 25, 2022
a3819f6
packed-backend: create abstraction for writing refs
derrickstolee Oct 25, 2022
7c1f6a1
config: add config values for packed-refs v2
derrickstolee Oct 25, 2022
eb6152f
packed-backend: create shell of v2 writes
derrickstolee Oct 25, 2022
740c2f6
packed-refs: write file format version 2
derrickstolee Oct 25, 2022
701c5ad
packed-refs: read file format v2
derrickstolee Oct 25, 2022
9b3bd93
packed-refs: read optional prefix chunks
derrickstolee Oct 25, 2022
36f9aa0
packed-refs: write prefix chunks
derrickstolee Oct 25, 2022
6fe60ef
packed-backend: create GIT_TEST_PACKED_REFS_VERSION
derrickstolee Oct 26, 2022
188a55d
t1409: test with packed-refs v2
derrickstolee Oct 26, 2022
191ad7f
t5312: allow packed-refs v2 format
derrickstolee Oct 26, 2022
f8b9f35
t5502: add PACKED_REFS_V1 prerequisite
derrickstolee Oct 26, 2022
e6ed6e7
t3210: require packed-refs v1 for some tests
derrickstolee Oct 26, 2022
5aa0d40
t*: skip packed-refs v2 over http tests
derrickstolee Oct 26, 2022
9d261a5
ci: run GIT_TEST_PACKED_REFS_VERSION=2 in some builds
derrickstolee Oct 26, 2022
a4a69d8
p1401: create performance test for ref operations
derrickstolee Nov 3, 2022
37fb4e7
refs: skip hashing when writing packed-refs v2
derrickstolee Nov 3, 2022
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
read-cache: add index.computeHash config option
The previous change allowed skipping the hashing portion of the hashwrite API, using it instead as a buffered write API. Disabling the hashwrite can be particularly helpful when the write operation is in a critical path. One such critical path is the writing of the index. This operation is so critical that the sparse index was created specifically to reduce the size of the index to make these writes (and reads) faster. Following a similar approach to one used in the microsoft/git fork [1], add a new config option that allows disabling this hashing during the index write. The cost is that we can no longer validate the contents for corruption-at-rest using the trailing hash. [1] microsoft@21fed2d While older Git versions will not recognize the null hash as a special case, the file format itself is still being met in terms of its structure. Using this null hash will still allow Git operations to function across older versions. The one exception is 'git fsck' which checks the hash of the index file. Here, we disable this check if the trailing hash is all zeroes. We add a warning to the config option that this may cause undesirable behavior with older Git versions. As a quick comparison, I tested 'git update-index --force-write' with and without index.computHash=false on a copy of the Linux kernel repository. Benchmark 1: with hash Time (mean ± σ): 46.3 ms ± 13.8 ms [User: 34.3 ms, System: 11.9 ms] Range (min … max): 34.3 ms … 79.1 ms 82 runs Benchmark 2: without hash Time (mean ± σ): 26.0 ms ± 7.9 ms [User: 11.8 ms, System: 14.2 ms] Range (min … max): 16.3 ms … 42.0 ms 69 runs Summary 'without hash' ran 1.78 ± 0.76 times faster than 'with hash' These performance benefits are substantial enough to allow users the ability to opt-in to this feature, even with the potential confusion with older 'git fsck' versions. Signed-off-by: Derrick Stolee <derrickstolee@github.com>
  • Loading branch information
derrickstolee committed Nov 3, 2022
commit 030d76f52af654470026b0c4b1dfba2b6c996885
8 changes: 8 additions & 0 deletions Documentation/config/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,11 @@ index.version::
Specify the version with which new index files should be
initialized. This does not affect existing repositories.
If `feature.manyFiles` is enabled, then the default is 4.

index.computeHash::
When enabled, compute the hash of the index file as it is written
and store the hash at the end of the content. This is enabled by
default.
+
If you disable `index.computHash`, then older Git clients may report that
your index is corrupt during `git fsck`.
22 changes: 21 additions & 1 deletion read-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1817,6 +1817,8 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)
git_hash_ctx c;
unsigned char hash[GIT_MAX_RAWSZ];
int hdr_version;
int all_zeroes = 1;
unsigned char *start, *end;

if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
return error(_("bad signature 0x%08x"), hdr->hdr_signature);
Expand All @@ -1827,10 +1829,23 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)
if (!verify_index_checksum)
return 0;

end = (unsigned char *)hdr + size;
start = end - the_hash_algo->rawsz;
while (start < end) {
if (*start != 0) {
all_zeroes = 0;
break;
}
start++;
}

if (all_zeroes)
return 0;

the_hash_algo->init_fn(&c);
the_hash_algo->update_fn(&c, hdr, size - the_hash_algo->rawsz);
the_hash_algo->final_fn(hash, &c);
if (!hasheq(hash, (unsigned char *)hdr + size - the_hash_algo->rawsz))
if (!hasheq(hash, end - the_hash_algo->rawsz))
return error(_("bad index file sha1 signature"));
return 0;
}
Expand Down Expand Up @@ -2917,9 +2932,14 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
int ieot_entries = 1;
struct index_entry_offset_table *ieot = NULL;
int nr, nr_threads;
int compute_hash;

f = hashfd(tempfile->fd, tempfile->filename.buf);

if (!git_config_get_maybe_bool("index.computehash", &compute_hash) &&
!compute_hash)
f->skip_hash = 1;

for (i = removed = extended = 0; i < entries; i++) {
if (cache[i]->ce_flags & CE_REMOVE)
removed++;
Expand Down
8 changes: 8 additions & 0 deletions t/t1600-index.sh
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,12 @@ test_expect_success 'index version config precedence' '
test_index_version 0 true 2 2
'

test_expect_success 'index.computeHash config option' '
(
rm -f .git/index &&
git -c index.computeHash=false add a &&
git fsck
)
'

test_done