lock_ref_sha1_basic(): use raceproof_create_file()
Instead of coding the retry loop inline, use raceproof_create_file() to make lock acquisition safe against directory creation/deletion races. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Michael Haggerty committed
Jan 6, 2017 at 17:22 UTC
3b5d3c9848aaa6e15d814730cfac0efe3257eb46
1 file changed
+9
-26
refs/files-backend.c
+9
-26
@@ -1985,6 +1985,13 @@ static int remove_empty_directories(struct strbuf *path)
1985
return remove_dir_recursively(path, REMOVE_DIR_EMPTY_ONLY);
1986
}
1987
1988
+static int create_reflock(const char *path, void *cb)
1989
+{
1990
+ struct lock_file *lk = cb;
1991
+
1992
+ return hold_lock_file_for_update(lk, path, LOCK_NO_DEREF) < 0 ? -1 : 0;
1993
+}
1994
+
1995
/*
1996
* Locks a ref returning the lock on success and NULL on failure.
1997
* On failure errno is set to something meaningful.
@@ -2002,7 +2009,6 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
2009
int last_errno = 0;
2010
int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
2011
int resolve_flags = RESOLVE_REF_NO_RECURSE;
2005
- int attempts_remaining = 3;
2012
int resolved;
2013
2014
assert_main_repository(&refs->base, "lock_ref_sha1_basic");
@@ -2067,35 +2073,12 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
2073
2074
lock->ref_name = xstrdup(refname);
2075
2070
- retry:
2071
- switch (safe_create_leading_directories_const(ref_file.buf)) {
2072
- case SCLD_OK:
2073
- break; /* success */
2074
- case SCLD_VANISHED:
2075
- if (--attempts_remaining > 0)
2076
- goto retry;
2077
- /* fall through */
2078
- default:
2076
+ if (raceproof_create_file(ref_file.buf, create_reflock, lock->lk)) {
2077
last_errno = errno;
2080
- strbuf_addf(err, "unable to create directory for '%s'",
2081
- ref_file.buf);
2078
+ unable_to_lock_message(ref_file.buf, errno, err);
2079
goto error_return;
2080
}
2081
2085
- if (hold_lock_file_for_update(lock->lk, ref_file.buf, LOCK_NO_DEREF) < 0) {
2086
- last_errno = errno;
2087
- if (errno == ENOENT && --attempts_remaining > 0)
2088
- /*
2089
- * Maybe somebody just deleted one of the
2090
- * directories leading to ref_file. Try
2091
- * again:
2092
- */
2093
- goto retry;
2094
- else {
2095
- unable_to_lock_message(ref_file.buf, errno, err);
2096
- goto error_return;
2097
- }
2098
- }
2082
if (verify_lock(lock, old_sha1, mustexist, err)) {
2083
last_errno = errno;
2084
goto error_return;