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

[PATCH v2 0/9] packfile: avoid .idx rename races

From
Taylor Blau <me@ttaylorr.com>
Date
Sep 9, 2021, 23:24 UTC
Message-ID
<cover.1631228928.git.me@ttaylorr.com>
In-Reply-To
<cover.1631157880.git.me@ttaylorr.com>

Here is a relatively small reroll of mine and Ævar's series to prevent packfile-related races when moving the `.idx` into place before other auxiliary files are renamed.

All changes are cosmetic, but all of the feedback on the previous round was a strict improvement in the overall quality, so it seemed pertinent to send an improved version. Range-diff is below, and thanks in advance for your review.

Taylor Blau (4):
  bulk-checkin.c: store checksum directly
  pack-write.c: rename `.idx` files after `*.rev`
  builtin/repack.c: move `.idx` files into place last
  builtin/index-pack.c: move `.idx` files into place last
Ævar Arnfjörð Bjarmason (5):
  pack.h: line-wrap the definition of finish_tmp_packfile()
  pack-write: refactor renaming in finish_tmp_packfile()
  index-pack: refactor renaming in final()
  pack-write: split up finish_tmp_packfile() function
  pack-objects: rename .idx files into place after .bitmap files
 builtin/index-pack.c   | 48 +++++++++++++++++------------------
 builtin/pack-objects.c | 15 ++++++++---
 builtin/repack.c       |  2 +-
 bulk-checkin.c         | 31 +++++++++++++++++------
 pack-write.c           | 57 +++++++++++++++++++++---------------------
 pack.h                 | 10 +++++++-
 6 files changed, 96 insertions(+), 67 deletions(-)
Range-diff against v1:
 -:  ---------- >  1:  0b07aa4947 pack.h: line-wrap the definition of finish_tmp_packfile()
 1:  20b35ce050 !  2:  c46d3c29b4 bulk-checkin.c: store checksum directly
    @@ Commit message
         Store the hash directly in an unsigned char array. This behaves the same
         as writing to the `hash` member, but makes the intent clearer (and
         avoids allocating an extra four bytes for the `algo` member of `struct
    -    object_id`).
    +    object_id`). It likewise prevents the possibility of a segfault when
    +    reading `algo` (e.g., by calling `oid_to_hex()`) if it is uninitialized.
     
         Signed-off-by: Taylor Blau <me@ttaylorr.com>
     
 2:  35052ef494 !  3:  2e907e309d pack-write: refactor renaming in finish_tmp_packfile()
    @@ pack-write.c: struct hashfile *create_tmp_packfile(char **pack_tmp_name)
      	return hashfd(fd, *pack_tmp_name);
      }
      
    -+static void rename_tmp_packfile(struct strbuf *nb, const char *source,
    ++static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,
     +				const char *ext)
     +{
    -+	size_t nb_len = nb->len;
    ++	size_t name_prefix_len = name_prefix->len;
     +
    -+	strbuf_addstr(nb, ext);
    -+	if (rename(source, nb->buf))
    -+		die_errno("unable to rename temporary '*.%s' file to '%s'",
    -+			  ext, nb->buf);
    -+	strbuf_setlen(nb, nb_len);
    ++	strbuf_addstr(name_prefix, ext);
    ++	if (rename(source, name_prefix->buf))
    ++		die_errno("unable to rename temporary file to '%s'",
    ++			  name_prefix->buf);
    ++	strbuf_setlen(name_prefix, name_prefix_len);
     +}
     +
      void finish_tmp_packfile(struct strbuf *name_buffer,
 3:  0fb2c25f5a =  4:  41d34b1f18 pack-write.c: rename `.idx` files after `*.rev`
 4:  3b10a97ec0 =  5:  6b340b7eba builtin/repack.c: move `.idx` files into place last
 5:  3c9b515907 !  6:  1e4d0ea0f3 index-pack: refactor renaming in final()
    @@ Commit message
         helper, this is both a net decrease in lines, and improves the
         readability, since we can easily see at a glance that the logic for
         writing these three types of files is exactly the same, aside from the
    -    obviously differing cases of "*final_xyz_name" being NULL, and
    -    "else_chmod_if" being different.
    +    obviously differing cases of "*final_name" being NULL, and
    +    "make_read_only_if_same" being different.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
         Signed-off-by: Taylor Blau <me@ttaylorr.com>
    @@ builtin/index-pack.c: static void write_special_file(const char *suffix, const c
      	strbuf_release(&name_buf);
      }
      
    -+static void rename_tmp_packfile(const char **final_xyz_name,
    -+				const char *curr_xyz_name,
    -+				struct strbuf *xyz_name, unsigned char *hash,
    -+				const char *ext, int else_chmod_if)
    ++static void rename_tmp_packfile(const char **final_name,
    ++				const char *curr_name,
    ++				struct strbuf *name, unsigned char *hash,
    ++				const char *ext, int make_read_only_if_same)
     +{
    -+	if (*final_xyz_name != curr_xyz_name) {
    -+		if (!*final_xyz_name)
    -+			*final_xyz_name = odb_pack_name(xyz_name, hash, ext);
    -+		if (finalize_object_file(curr_xyz_name, *final_xyz_name))
    ++	if (*final_name != curr_name) {
    ++		if (!*final_name)
    ++			*final_name = odb_pack_name(name, hash, ext);
    ++		if (finalize_object_file(curr_name, *final_name))
     +			die(_("unable to rename temporary '*.%s' file to '%s"),
    -+			    ext, *final_xyz_name);
    -+	} else if (else_chmod_if) {
    -+		chmod(*final_xyz_name, 0444);
    ++			    ext, *final_name);
    ++	} else if (make_read_only_if_same) {
    ++		chmod(*final_name, 0444);
     +	}
     +}
     +
 6:  8d67a71501 =  7:  906e75d707 builtin/index-pack.c: move `.idx` files into place last
 7:  5c553229b0 !  8:  90bebe4e51 pack-write: split up finish_tmp_packfile() function
    @@ bulk-checkin.c: static struct bulk_checkin_state {
      	unsigned char hash[GIT_MAX_RAWSZ];
     
      ## pack-write.c ##
    -@@ pack-write.c: static void rename_tmp_packfile(struct strbuf *nb, const char *source,
    - 	strbuf_setlen(nb, nb_len);
    +@@ pack-write.c: static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,
    + 	strbuf_setlen(name_prefix, name_prefix_len);
      }
      
     -void finish_tmp_packfile(struct strbuf *name_buffer,
 8:  d8286cf107 !  9:  1409725509 pack-objects: rename .idx files into place after .bitmap files
    @@ Commit message
         about filesystem races in the face of doing and not doing fsync() (and
         if doing fsync(), not doing it properly).
     
    -    In particular, in this case of writing to ".git/objects/pack" we only
    -    write and fsync() the individual files, but if we wanted to guarantee
    -    that the metadata update was seen in that way by concurrent processes
    -    we'd need to fsync() on the "fd" of the containing directory. That
    -    concern is probably more theoretical than not, modern OS's tend to be
    -    more on the forgiving side than the overly pedantic side of
    -    implementing POSIX FS semantics.
    +    We may want to fsync the containing directory once after renaming the
    +    *.idx file into place, but that is outside the scope of this series.
     
         1. https://lore.kernel.org/git/8735qgkvv1.fsf@evledraar.gmail.com/
     
-- 
2.33.0.96.g73915697e6
Previous: Junio C HamanoNext: Taylor Blau
Message 71 of 81 in “pack-write,repack: prevent opening packs too early”
  1. 0/2 pack-write,repack: prevent opening packs too earlyTaylor Blau, Sep 1, 2021
  2. 1/2 pack-write.c: rename `.idx` file into place lastTaylor Blau, Sep 1, 2021
  3. 2/2 builtin/repack.c: move `.idx` files into place lastTaylor Blau, Sep 1, 2021
  4. Jeff KingSep 1, 2021
  5. Taylor BlauSep 1, 2021
  6. Jeff KingSep 1, 2021
  7. Taylor BlauSep 1, 2021
  8. Jeff KingSep 1, 2021
  9. Taylor BlauSep 1, 2021
  10. Jeff KingSep 7, 2021
  11. 0/3 rename *.idx file into place last (also after *.bitmap)Ævar Arnfjörð Bjarmason, Sep 7, 2021
  12. 1/3 pack-write: use more idiomatic strbuf usage for packname constructionÆvar Arnfjörð Bjarmason, Sep 7, 2021
  13. Taylor BlauSep 7, 2021
  14. Ævar Arnfjörð BjarmasonSep 7, 2021
  15. 2/3 pack-write: split up finish_tmp_packfile() functionÆvar Arnfjörð Bjarmason, Sep 7, 2021
  16. Taylor BlauSep 7, 2021
  17. 3/3 pack-write: rename *.idx file into place last (really!)Ævar Arnfjörð Bjarmason, Sep 7, 2021
  18. Taylor BlauSep 7, 2021
  19. Taylor BlauSep 7, 2021
  20. Ævar Arnfjörð BjarmasonSep 7, 2021
  21. 0/4 rename *.idx file into place last (also after *.bitmap)Ævar Arnfjörð Bjarmason, Sep 8, 2021
  22. 1/4 pack.h: line-wrap the definition of finish_tmp_packfile()Ævar Arnfjörð Bjarmason, Sep 8, 2021
  23. 2/4 pack-write: refactor renaming in finish_tmp_packfile()Ævar Arnfjörð Bjarmason, Sep 8, 2021
  24. Taylor BlauSep 8, 2021
  25. 3/4 pack-write: split up finish_tmp_packfile() functionÆvar Arnfjörð Bjarmason, Sep 8, 2021
  26. 4/4 pack-write: rename *.idx file into place last (really!)Ævar Arnfjörð Bjarmason, Sep 8, 2021
  27. Ævar Arnfjörð BjarmasonSep 8, 2021
  28. Ævar Arnfjörð BjarmasonSep 8, 2021
  29. Taylor BlauSep 8, 2021
  30. 0/3 prevent opening packs too earlyTaylor Blau, Sep 8, 2021
  31. 1/3 pack-write.c: rename `.idx` files into place lastTaylor Blau, Sep 8, 2021
  32. 2/3 builtin/repack.c: move `.idx` files into place lastTaylor Blau, Sep 8, 2021
  33. 3/3 builtin/index-pack.c: move `.idx` files into place lastTaylor Blau, Sep 8, 2021
  34. Ævar Arnfjörð BjarmasonSep 8, 2021
  35. Ævar Arnfjörð BjarmasonSep 9, 2021
  36. Taylor BlauSep 9, 2021
  37. Ævar Arnfjörð BjarmasonSep 9, 2021
  38. Ævar Arnfjörð BjarmasonSep 9, 2021
  39. Taylor BlauSep 9, 2021
  40. 0/9 packfile: avoid .idx rename racesTaylor Blau, Sep 9, 2021
  41. 1/9 pack.h: line-wrap the definition of finish_tmp_packfile()Taylor Blau, Sep 9, 2021
  42. 2/9 bulk-checkin.c: store checksum directlyTaylor Blau, Sep 9, 2021
  43. Ævar Arnfjörð BjarmasonSep 9, 2021
  44. 3/9 pack-write: refactor renaming in finish_tmp_packfile()Taylor Blau, Sep 9, 2021
  45. Junio C HamanoSep 9, 2021
  46. Taylor BlauSep 9, 2021
  47. Junio C HamanoSep 9, 2021
  48. Taylor BlauSep 9, 2021
  49. Junio C HamanoSep 10, 2021
  50. 4/9 pack-write.c: rename `.idx` files after `*.rev`Taylor Blau, Sep 9, 2021
  51. Ævar Arnfjörð BjarmasonSep 9, 2021
  52. Taylor BlauSep 9, 2021
  53. Junio C HamanoSep 9, 2021
  54. 5/9 builtin/repack.c: move `.idx` files into place lastTaylor Blau, Sep 9, 2021
  55. Junio C HamanoSep 9, 2021
  56. Taylor BlauSep 9, 2021
  57. 6/9 index-pack: refactor renaming in final()Taylor Blau, Sep 9, 2021
  58. Junio C HamanoSep 9, 2021
  59. Taylor BlauSep 9, 2021
  60. 8/9 pack-write: split up finish_tmp_packfile() functionTaylor Blau, Sep 9, 2021
  61. 7/9 builtin/index-pack.c: move `.idx` files into place lastTaylor Blau, Sep 9, 2021
  62. Ævar Arnfjörð BjarmasonSep 9, 2021
  63. Junio C HamanoSep 9, 2021
  64. 9/9 pack-objects: rename .idx files into place after .bitmap filesTaylor Blau, Sep 9, 2021
  65. Ævar Arnfjörð BjarmasonSep 9, 2021
  66. Junio C HamanoSep 9, 2021
  67. Taylor BlauSep 9, 2021
  68. Ævar Arnfjörð BjarmasonSep 9, 2021
  69. Taylor BlauSep 9, 2021
  70. Junio C HamanoSep 9, 2021
  71. 0/9 packfile: avoid .idx rename racesTaylor Blau, Sep 9, 2021
  72. 1/9 pack.h: line-wrap the definition of finish_tmp_packfile()Taylor Blau, Sep 9, 2021
  73. 2/9 bulk-checkin.c: store checksum directlyTaylor Blau, Sep 9, 2021
  74. 3/9 pack-write: refactor renaming in finish_tmp_packfile()Taylor Blau, Sep 9, 2021
  75. 4/9 pack-write.c: rename `.idx` files after `*.rev`Taylor Blau, Sep 9, 2021
  76. 5/9 builtin/repack.c: move `.idx` files into place lastTaylor Blau, Sep 9, 2021
  77. 6/9 index-pack: refactor renaming in final()Taylor Blau, Sep 9, 2021
  78. 8/9 pack-write: split up finish_tmp_packfile() functionTaylor Blau, Sep 9, 2021
  79. 7/9 builtin/index-pack.c: move `.idx` files into place lastTaylor Blau, Sep 9, 2021
  80. 9/9 pack-objects: rename .idx files into place after .bitmap filesTaylor Blau, Sep 9, 2021
  81. Junio C HamanoSep 10, 2021

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.