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

Re: [PATCH 5/7] tmp-objdir: new API for creating and removing primary object dirs

From
Jeff King <peff@peff.net>
Date
Sep 28, 2021, 23:17 UTC
Message-ID
<YVOiggCWAdZcxAb6@coredump.intra.peff.net>
In-Reply-To
<67d3b2b09f9ddda616cdd0d1b12ab7afc73670ed.1630376800.git.gitgitgadget@gmail.com>
On Tue, Aug 31, 2021 at 02:26:38AM +0000, Elijah Newren via GitGitGadget wrote:
Show 14 quoted lines
> From: Elijah Newren <newren@gmail.com>
> 
> The tmp_objdir API provides the ability to create temporary object
> directories, but was designed with the goal of having subprocesses
> access these object stores, followed by the main process migrating
> objects from it to the main object store or just deleting it.  The
> subprocesses would view it as their primary datastore and write to it.
> 
> For the --remerge-diff option we want to add to show & log, we want all
> writes of intermediate merge results (both blobs and trees) to go to
> this alternate object store; since those writes will be done by the main
> process, we need this "alternate" object store to actually be the
> primary object store.  When show & log are done, they'll simply remove
> this temporary object store.

I think this is consistent with the original design of tmp_objdir. I just never needed to do anything in-process before, so overriding the environment of sub-processes was sufficient.

I do think these are dangerous and may cause bugs, though. Anything you write while the tmp_objdir is marked as "primary" is going to go away when you remove it. So any object names you reference outside of that, either:

  - by another object that you create after the tmp_objdir is removed;
    or
  - in a ref

are going to turn into repository corruption. Of course that's true for the existing sub-processes, too, but here we're touching a wider variety of code.

Obviously the objects we write as part of remerge-diff are meant to be temporary, and we'll never reference them in any other way. And usually we would not expect a diff to write any other objects. But one thing that comes to mind if textconv caching.

If you do a remerge diff on a blob that uses textconv, and the caching feature is turned on, then we'll write out a new blob with the cached value, and eventually a new tree and refs/notes/ pointer referencing it. I'm not sure of the timing of all of that, but it seems likely to me that at least some of that will end up in your tmp_objdir.

If you remove the tmp_objdir as the primary as soon as you're done with the merge, but before you run the diff, you might be OK, though.

If not, then I think the solution is probably not to install this as the "primary", but rather:

  - do the specific remerge-diff writes we want using a special "write
    to this object dir" variant of write_object_file()
  - install the tmp_objdir as an alternate, so the reading side (which
    is diff code that doesn't otherwise know about our remerge-diff
    trickery) can find them

And that lets other writers avoid writing into the temporary area accidentally.

In that sense this is kind of like the pretend_object_file() interface, except that it's storing the objects on disk instead of in memory. Of course another way of doing that would be to stuff the object data into tempfiles and just put pointers into the in-memory cached_objects array.

It's also not entirely foolproof (nor is the existing pretend_object_file()). Any operation which is fooled into thinking we have object X because it's in the fake-object list or the tmp_objdir may reference that object erroneously, creating a corruption. But it's still safer than allowing arbitrary writes into the tmp_objdir.

  Side note: The pretend_object_file() approach is actually even better,
  because we know the object is fake. So it does not confuse
  write_object_file()'s "do we already have this object" freshening
  check.
  I suspect it could even be made faster than the tmp_objdir approach.
  From our perspective, these objects really are tempfiles. So we could
  write them as such, not worrying about things like fsyncing them,
  naming them into place, etc. We could just write them out, then mmap
  the results, and put the pointers into cached_objects (currently it
  insists on malloc-ing a copy of the input buffer, but that seems like
  an easy extension to add).
  In fact, I think you could get away with just _one_ tempfile per
  merge. Open up one tempfile. Write out all of the objects you want to
  "store" into it in sequence, and record the lseek() offsets before and
  after for each object. Then mmap the whole result, and stuff the
  appropriate pointers (based on arithmetic with the offsets) into the
  cached_objects list.
  As a bonus, this tempfile can easily be in $TMPDIR, meaning
  remerge-diff could work on a read-only repository (and the OS can
  perhaps handle the data better, especially if $TMPDIR isn't a regular
  filesystem).
Show 5 quoted lines
> We also need one more thing -- `git log --remerge-diff` can cause the
> temporary object store to fill up with loose objects.  Rather than
> trying to gc that are known garbage anyway, we simply want to know the
> location of the temporary object store so we can purge the loose objects
> after each merge.

This paragraph confused me. At first I thought you were talking about how to avoid calling "gc --auto" because we don't want to waste time thinking all those loose objects were worth gc-ing. But we wouldn't do that anyway (git-log does not expect to make objects so doesn't call it at all, and anyway you'd expect it to happen at the end of a process, after we've already removed the tmp_objdir).

But I think you just mean: we can build up a bunch of loose objects, which is inefficient. We don't want to gc them, because that's even less efficient. So we want to clean them out between merges.

But I don't see any code to do that here. I guess that's maybe why you've added tmp_objdir_path(), to find them later. But IMHO this would be much better encapsulated as tmp_objdir_clear_objects() or something.

But simpler still: is there any reason not to just drop and re-create the tmp-objdir for each merge? It's not very expensive to do so (and certainly not compared to the cost of actually writing out the objects).

-Peff
Previous: Elijah NewrenNext: Junio C Hamano
Message 30 of 64 in “Add a new --remerge-diff capability to show & log”
  1. 0/7 Add a new --remerge-diff capability to show & logElijah Newren via GitGitGadget, Aug 31, 2021
  2. 1/7 merge-ort: mark a few more conflict messages as omittableElijah Newren via GitGitGadget, Aug 31, 2021
  3. Junio C HamanoAug 31, 2021
  4. Elijah NewrenSep 1, 2021
  5. Junio C HamanoSep 1, 2021
  6. 2/7 merge-ort: add ability to record conflict messages in a fileElijah Newren via GitGitGadget, Aug 31, 2021
  7. Jeff KingSep 28, 2021
  8. Elijah NewrenSep 29, 2021
  9. Junio C HamanoSep 29, 2021
  10. Elijah NewrenSep 29, 2021
  11. Jeff KingSep 30, 2021
  12. Ævar Arnfjörð BjarmasonSep 30, 2021
  13. Elijah NewrenOct 1, 2021
  14. Jeff KingOct 1, 2021
  15. 3/7 ll-merge: add API for capturing warnings in a strbuf instead of stderrElijah Newren via GitGitGadget, Aug 31, 2021
  16. Jeff KingSep 28, 2021
  17. Junio C HamanoSep 28, 2021
  18. Elijah NewrenSep 29, 2021
  19. 4/7 merge-ort: capture and print ll-merge warnings in our preferred fashionElijah Newren via GitGitGadget, Aug 31, 2021
  20. Jeff KingSep 28, 2021
  21. Ævar Arnfjörð BjarmasonSep 30, 2021
  22. Elijah NewrenOct 1, 2021
  23. Ævar Arnfjörð BjarmasonOct 1, 2021
  24. 5/7 tmp-objdir: new API for creating and removing primary object dirsElijah Newren via GitGitGadget, Aug 31, 2021
  25. Ævar Arnfjörð BjarmasonSep 28, 2021
  26. Elijah NewrenSep 29, 2021
  27. Jeff KingSep 30, 2021
  28. Ævar Arnfjörð BjarmasonSep 30, 2021
  29. Elijah NewrenOct 1, 2021
  30. Jeff KingSep 28, 2021
  31. Junio C HamanoSep 29, 2021
  32. Jeff KingSep 30, 2021
  33. Ævar Arnfjörð BjarmasonSep 30, 2021
  34. Jeff KingSep 30, 2021
  35. Elijah NewrenOct 1, 2021
  36. Ævar Arnfjörð BjarmasonOct 1, 2021
  37. Elijah NewrenOct 1, 2021
  38. Elijah NewrenOct 1, 2021
  39. Jeff KingOct 1, 2021
  40. Ævar Arnfjörð BjarmasonOct 1, 2021
  41. Elijah NewrenSep 29, 2021
  42. Jeff KingSep 30, 2021
  43. Jeff KingSep 30, 2021
  44. Junio C HamanoSep 30, 2021
  45. Elijah NewrenOct 1, 2021
  46. Junio C HamanoOct 1, 2021
  47. Elijah NewrenOct 1, 2021
  48. Jeff KingOct 1, 2021
  49. Neeraj SinghSep 30, 2021
  50. Junio C HamanoSep 30, 2021
  51. Junio C HamanoSep 30, 2021
  52. Elijah NewrenOct 1, 2021
  53. 7/7 doc/diff-options: explain the new --remerge-diff optionElijah Newren via GitGitGadget, Aug 31, 2021
  54. 6/7 show, log: provide a --remerge-diff capabilityElijah Newren via GitGitGadget, Aug 31, 2021
  55. Sergey OrganovAug 31, 2021
  56. Ævar Arnfjörð BjarmasonSep 28, 2021
  57. Elijah NewrenSep 29, 2021
  58. Bagas SanjayaAug 31, 2021
  59. Elijah NewrenAug 31, 2021
  60. Junio C HamanoAug 31, 2021
  61. Elijah NewrenAug 31, 2021
  62. Junio C HamanoSep 1, 2021
  63. Elijah NewrenSep 1, 2021
  64. Junio C HamanoSep 1, 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.