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

Re: [PATCH 2/2] dir.c: add retry logic to relocate_gitdir

From
Stefan Beller <sbeller@google.com>
Date
Dec 19, 2016, 23:19 UTC
Message-ID
<CAGZ79kZoiFfi9+-yqHZmF3Ofp3X-CV6s0qg1bm2CRpN-ETbDLw@mail.gmail.com>
In-Reply-To
<20161219222551.GA41080@google.com>
On Mon, Dec 19, 2016 at 2:25 PM, Brandon Williams <bmwill@google.com> wrote:
Show 77 quoted lines
> On 12/19, Stefan Beller wrote:
>> Relocating a git directory consists of 3 steps:
>> 1) Move the directory.
>> 2) Update the gitlink file.
>> 3) Set core.worktree correctly.
>>
>> In an ideal world all three steps would be part of one transaction, such
>> that either all of them happen correctly or none of them.
>> However currently we just execute these three steps sequentially and die
>> in case of an error in any of these 3 steps.
>>
>> Dying is ok in 1) as the transaction hasn't started and the state is
>> recoverable.
>>
>> When dying in 2), this is a problem as the repo state is left in an
>> inconsistent state, e.g. the git link file of a submodule could be
>> empty and hence even the superproject appears to be broken as basic
>> commands such as git-status would die as there is it cannot tell the
>> state of the submodule.
>> So in that case try to undo 1) to be in a less sufferable state.
>
> I now see why an atomic filesystem swap operation would be useful :)
>
>>
>> 3) is less of an issue as experiments with submodules show. When
>> core.worktree is unset or set incorrectly, git-status still works
>> both in the superproject as well as the working tree of the submodule.
>>
>> Signed-off-by: Stefan Beller <sbeller@google.com>
>> ---
>>  dir.c       | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------
>>  dir.h       |  6 ++--
>>  submodule.c |  3 +-
>>  3 files changed, 91 insertions(+), 12 deletions(-)
>>
>> diff --git a/dir.c b/dir.c
>> index b2cb23fe88..e4e3f69869 100644
>> --- a/dir.c
>> +++ b/dir.c
>> @@ -2749,30 +2749,66 @@ void untracked_cache_add_to_index(struct index_state *istate,
>>       untracked_cache_invalidate_path(istate, path);
>>  }
>>
>> -static void point_gitlink_file_to(const char *work_tree, const char *git_dir)
>> +/*
>> + * Just like write_file, we try hard to write the full content to the file.
>> + * If there is suspicion the write did not work correctly, make sure the file
>> + * is removed again.
>> + * Return 0 if the write succeeded, -1 if the file was removed,
>> + * -2 if the (partial) file is still there.
>> + */
>> +static int write_file_or_remove(const char *path, const char *buf, size_t len)
>> +{
>> +     int retries = 3;
>> +     int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
>> +     if (write_in_full(fd, buf, len) != len) {
>> +             warning_errno(_("could not write '%s'"), path);
>> +             goto err;
>> +     }
>> +     if (close(fd)) {
>> +             warning_errno(_("could not close '%s'"), path);
>> +             goto err;
>> +     }
>> +     return 0;
>> +err:
>> +     while (retries-- > 0) {
>> +             if (file_exists(path))
>> +                     unlink_or_warn(path);
>> +             else
>> +                     return -1;
>> +     }
>> +     return -2;
>> +}
>
> Any reason why on attempt 2 or 3 this would succeed if it failed on try
> 1?
>

This code is heavily inspired by refs/files-backend.c which upon closer inspection only retries directory things within the git directory (which is assumed to be accessed in parallel by different invocations of Git)

So I think we could drop the retry logic.
Show 7 quoted lines
>>  {
>> +     char *git_dir = xstrdup(real_path(new_git_dir));
>> +     char *work_tree = xstrdup(real_path(path));
>> +     int c;
>
> I guess in a later patch we could clean up these calls to real_path to
> use real_pathdup from bw/realpath-wo-chdir.
good point.
Previous: Brandon WilliamsNext: Duy Nguyen
Message 4 of 9 in “improve relocate_git_dir to fail into a sane state.”
  1. 0/2 improve relocate_git_dir to fail into a sane state.Stefan Beller, Dec 19, 2016
  2. 2/2 dir.c: add retry logic to relocate_gitdirStefan Beller, Dec 19, 2016
  3. Brandon WilliamsDec 19, 2016
  4. Stefan BellerDec 19, 2016
  5. Duy NguyenJan 4, 2017
  6. 1/2 dir.c: split up connect_work_tree_and_git_dirStefan Beller, Dec 19, 2016
  7. Junio C HamanoDec 19, 2016
  8. Stefan BellerDec 19, 2016
  9. Junio C HamanoDec 19, 2016

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.