git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v5 1/4] hashfile: allow skipping the hash function

From
Derrick Stolee via GitGitGadget <gitgitgadget@gmail.com>
Date
Jan 6, 2023, 16:31 UTC
Message-ID
<c99470d46763cdfbde01629888c379c448b3579d.1673022717.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1439.v5.git.1673022717.gitgitgadget@gmail.com>
From: Derrick Stolee <derrickstolee@github.com>

The hashfile API is useful for generating files that include a trailing hash of the file's contents up to that point. Using such a hash is helpful for verifying the file for corruption-at-rest, such as a faulty drive causing flipped bits.

Git's index file includes this trailing hash, so it uses a 'struct hashfile' to handle the I/O to the file. This was very convenient to allow using the hashfile methods during these operations.

However, hashing the file contents during write comes at a performance penalty. It's slower to hash the bytes on their way to the disk than without that step. This problem is made worse by the replacement of hardware-accelerated SHA1 computations with the software-based sha1dc computation.

This write cost is significant, and the checksum capability is likely not worth that cost for such a short-lived file. The index is rewritten frequently and the only time the checksum is checked is during 'git fsck'. Thus, it would be helpful to allow a user to opt-out of the hash computation.

We first need to allow Git to opt-out of the hash computation in the hashfile API. The buffered writes of the API are still helpful, so it makes sense to make the change here.

Introduce a new 'skip_hash' option to 'struct hashfile'. When set, the update_fn and final_fn members of the_hash_algo are skipped. When finalizing the hashfile, the trailing hash is replaced with the null hash.

This use of a trailing null hash would be desireable in either case, since we do not want to special case a file format to have a different length depending on whether it was hashed or not. When the final bytes of a file are all zero, we can infer that it was written without hashing, and thus that verification is not available as a check for file consistency. This also means that we could easily toggle hashing for any file format we desire.

A version of this patch has existed in the microsoft/git fork since 2017 [1] (the linked commit was rebased in 2018, but the original dates back to January 2017). Here, the change to make the index use this fast path is delayed until a later change.

[1] https://github.com/microsoft/git/commit/21fed2d91410f45d85279467f21d717a2db45201
Co-authored-by: Kevin Willford <kewillf@microsoft.com>
Signed-off-by: Kevin Willford <kewillf@microsoft.com>
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
---
 csum-file.c | 14 +++++++++++---
 csum-file.h |  7 +++++++
 2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/csum-file.c b/csum-file.c
index 59ef3398ca2..cce13c0f047 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -45,7 +45,8 @@ void hashflush(struct hashfile *f)
 	unsigned offset = f->offset;
 
 	if (offset) {
-		the_hash_algo->update_fn(&f->ctx, f->buffer, offset);
+		if (!f->skip_hash)
+			the_hash_algo->update_fn(&f->ctx, f->buffer, offset);
 		flush(f, f->buffer, offset);
 		f->offset = 0;
 	}
@@ -64,7 +65,12 @@ int finalize_hashfile(struct hashfile *f, unsigned char *result,
 	int fd;
 
 	hashflush(f);
-	the_hash_algo->final_fn(f->buffer, &f->ctx);
+
+	if (f->skip_hash)
+		hashclr(f->buffer);
+	else
+		the_hash_algo->final_fn(f->buffer, &f->ctx);
+
 	if (result)
 		hashcpy(result, f->buffer);
 	if (flags & CSUM_HASH_IN_STREAM)
@@ -108,7 +114,8 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count)
 			 * the hashfile's buffer. In this block,
 			 * f->offset is necessarily zero.
 			 */
-			the_hash_algo->update_fn(&f->ctx, buf, nr);
+			if (!f->skip_hash)
+				the_hash_algo->update_fn(&f->ctx, buf, nr);
 			flush(f, buf, nr);
 		} else {
 			/*
@@ -153,6 +160,7 @@ static struct hashfile *hashfd_internal(int fd, const char *name,
 	f->tp = tp;
 	f->name = name;
 	f->do_crc = 0;
+	f->skip_hash = 0;
 	the_hash_algo->init_fn(&f->ctx);
 
 	f->buffer_len = buffer_len;
diff --git a/csum-file.h b/csum-file.h
index 0d29f528fbc..793a59da12b 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -20,6 +20,13 @@ struct hashfile {
 	size_t buffer_len;
 	unsigned char *buffer;
 	unsigned char *check_buffer;
+
+	/**
+	 * If non-zero, skip_hash indicates that we should
+	 * not actually compute the hash for this hashfile and
+	 * instead only use it as a buffered write.
+	 */
+	int skip_hash;
 };
 
 /* Checkpoint */
-- 
gitgitgadget
Previous: Derrick Stolee via GitGitGadgetNext: Derrick Stolee via GitGitGadget
Message 54 of 59 in “Optionally skip hashing index on write”
  1. 0/4 Optionally skip hashing index on writeDerrick Stolee via GitGitGadget, Dec 7, 2022
  2. 2/4 read-cache: add index.skipHash config optionDerrick Stolee via GitGitGadget, Dec 7, 2022
  3. Eric SunshineDec 7, 2022
  4. Derrick StoleeDec 12, 2022
  5. Eric SunshineDec 12, 2022
  6. Ævar Arnfjörð BjarmasonDec 7, 2022
  7. Ævar Arnfjörð BjarmasonDec 7, 2022
  8. Junio C HamanoDec 8, 2022
  9. Derrick StoleeDec 12, 2022
  10. Ævar Arnfjörð BjarmasonDec 12, 2022
  11. 1/4 hashfile: allow skipping the hash functionDerrick Stolee via GitGitGadget, Dec 7, 2022
  12. Ævar Arnfjörð BjarmasonDec 7, 2022
  13. Jeff KingDec 8, 2022
  14. 3/4 test-lib-functions: add helper for trailing hashDerrick Stolee via GitGitGadget, Dec 7, 2022
  15. Ævar Arnfjörð BjarmasonDec 7, 2022
  16. Derrick StoleeDec 12, 2022
  17. 4/4 features: feature.manyFiles implies fast index writesDerrick Stolee via GitGitGadget, Dec 7, 2022
  18. Ævar Arnfjörð BjarmasonDec 7, 2022
  19. Derrick StoleeDec 12, 2022
  20. Ævar Arnfjörð BjarmasonDec 12, 2022
  21. Junio C HamanoDec 7, 2022
  22. Ævar Arnfjörð BjarmasonDec 7, 2022
  23. Derrick StoleeDec 8, 2022
  24. Jacob KellerDec 12, 2022
  25. 0/4 Optionally skip hashing index on writeDerrick Stolee via GitGitGadget, Dec 12, 2022
  26. 1/4 hashfile: allow skipping the hash functionDerrick Stolee via GitGitGadget, Dec 12, 2022
  27. 4/4 features: feature.manyFiles implies fast index writesDerrick Stolee via GitGitGadget, Dec 12, 2022
  28. 2/4 read-cache: add index.skipHash config optionDerrick Stolee via GitGitGadget, Dec 12, 2022
  29. 3/4 test-lib-functions: add helper for trailing hashDerrick Stolee via GitGitGadget, Dec 12, 2022
  30. SZEDER GáborDec 12, 2022
  31. Junio C HamanoDec 13, 2022
  32. SZEDER GáborDec 17, 2022
  33. 0/4 Optionally skip hashing index on writeDerrick Stolee via GitGitGadget, Dec 15, 2022
  34. 1/4 hashfile: allow skipping the hash functionDerrick Stolee via GitGitGadget, Dec 15, 2022
  35. 2/4 read-cache: add index.skipHash config optionDerrick Stolee via GitGitGadget, Dec 15, 2022
  36. Ævar Arnfjörð BjarmasonDec 15, 2022
  37. 3/4 test-lib-functions: add helper for trailing hashDerrick Stolee via GitGitGadget, Dec 15, 2022
  38. 4/4 features: feature.manyFiles implies fast index writesDerrick Stolee via GitGitGadget, Dec 15, 2022
  39. Ævar Arnfjörð BjarmasonDec 15, 2022
  40. Derrick StoleeDec 16, 2022
  41. 0/4 Optionally skip hashing index on writeDerrick Stolee via GitGitGadget, Dec 16, 2022
  42. 1/4 hashfile: allow skipping the hash functionDerrick Stolee via GitGitGadget, Dec 16, 2022
  43. 2/4 read-cache: add index.skipHash config optionDerrick Stolee via GitGitGadget, Dec 16, 2022
  44. 3/4 test-lib-functions: add helper for trailing hashDerrick Stolee via GitGitGadget, Dec 16, 2022
  45. 4/4 features: feature.manyFiles implies fast index writesDerrick Stolee via GitGitGadget, Dec 16, 2022
  46. Ævar Arnfjörð BjarmasonDec 16, 2022
  47. Derrick StoleeJan 6, 2023
  48. Junio C HamanoJan 6, 2023
  49. Derrick StoleeJan 6, 2023
  50. Ævar Arnfjörð BjarmasonJan 9, 2023
  51. Derrick StoleeJan 9, 2023
  52. Ævar Arnfjörð BjarmasonJan 9, 2023
  53. 0/4 Optionally skip hashing index on writeDerrick Stolee via GitGitGadget, Jan 6, 2023
  54. 1/4 hashfile: allow skipping the hash functionDerrick Stolee via GitGitGadget, Jan 6, 2023
  55. 2/4 read-cache: add index.skipHash config optionDerrick Stolee via GitGitGadget, Jan 6, 2023
  56. 3/4 test-lib-functions: add helper for trailing hashDerrick Stolee via GitGitGadget, Jan 6, 2023
  57. 4/4 features: feature.manyFiles implies fast index writesDerrick Stolee via GitGitGadget, Jan 6, 2023
  58. Junio C HamanoJan 15, 2023
  59. Derrick StoleeJan 17, 2023

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.