Browse Source

Merge branch 'mh/ref-lock-entry'

The code to acquire a lock on a reference (e.g. while accepting a
push from a client) used to immediately fail when the reference is
already locked---now it waits for a very short while and retries,
which can make it succeed if the lock holder was holding it during
a read-only operation.

* mh/ref-lock-entry:
  refs: retry acquiring reference locks for 100ms
maint
Junio C Hamano 8 years ago
parent
commit
f2dd90fc1c
  1. 6
      Documentation/config.txt
  2. 24
      refs.c
  3. 8
      refs/files-backend.c
  4. 6
      refs/refs-internal.h

6
Documentation/config.txt

@ -776,6 +776,12 @@ core.commentChar:: @@ -776,6 +776,12 @@ core.commentChar::
If set to "auto", `git-commit` would select a character that is not
the beginning character of any line in existing commit messages.

core.filesRefLockTimeout::
The length of time, in milliseconds, to retry when trying to
lock an individual reference. Value 0 means not to retry at
all; -1 means to try indefinitely. Default is 100 (i.e.,
retry for 100ms).

core.packedRefsTimeout::
The length of time, in milliseconds, to retry when trying to
lock the `packed-refs` file. Value 0 means not to retry at

24
refs.c

@ -579,6 +579,21 @@ enum ref_type ref_type(const char *refname) @@ -579,6 +579,21 @@ enum ref_type ref_type(const char *refname)
return REF_TYPE_NORMAL;
}

long get_files_ref_lock_timeout_ms(void)
{
static int configured = 0;

/* The default timeout is 100 ms: */
static int timeout_ms = 100;

if (!configured) {
git_config_get_int("core.filesreflocktimeout", &timeout_ms);
configured = 1;
}

return timeout_ms;
}

static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
const unsigned char *old_sha1, struct strbuf *err)
{
@ -591,7 +606,9 @@ static int write_pseudoref(const char *pseudoref, const unsigned char *sha1, @@ -591,7 +606,9 @@ static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));

filename = git_path("%s", pseudoref);
fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
fd = hold_lock_file_for_update_timeout(&lock, filename,
LOCK_DIE_ON_ERROR,
get_files_ref_lock_timeout_ms());
if (fd < 0) {
strbuf_addf(err, "could not open '%s' for writing: %s",
filename, strerror(errno));
@ -634,8 +651,9 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1 @@ -634,8 +651,9 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1
int fd;
unsigned char actual_old_sha1[20];

fd = hold_lock_file_for_update(&lock, filename,
LOCK_DIE_ON_ERROR);
fd = hold_lock_file_for_update_timeout(
&lock, filename, LOCK_DIE_ON_ERROR,
get_files_ref_lock_timeout_ms());
if (fd < 0)
die_errno(_("Could not open '%s' for writing"), filename);
if (read_ref(pseudoref, actual_old_sha1))

8
refs/files-backend.c

@ -537,7 +537,9 @@ retry: @@ -537,7 +537,9 @@ retry:
if (!lock->lk)
lock->lk = xcalloc(1, sizeof(struct lock_file));

if (hold_lock_file_for_update(lock->lk, ref_file.buf, LOCK_NO_DEREF) < 0) {
if (hold_lock_file_for_update_timeout(
lock->lk, ref_file.buf, LOCK_NO_DEREF,
get_files_ref_lock_timeout_ms()) < 0) {
if (errno == ENOENT && --attempts_remaining > 0) {
/*
* Maybe somebody just deleted one of the
@ -865,7 +867,9 @@ static int create_reflock(const char *path, void *cb) @@ -865,7 +867,9 @@ static int create_reflock(const char *path, void *cb)
{
struct lock_file *lk = cb;

return hold_lock_file_for_update(lk, path, LOCK_NO_DEREF) < 0 ? -1 : 0;
return hold_lock_file_for_update_timeout(
lk, path, LOCK_NO_DEREF,
get_files_ref_lock_timeout_ms()) < 0 ? -1 : 0;
}

/*

6
refs/refs-internal.h

@ -61,6 +61,12 @@ @@ -61,6 +61,12 @@
*/
#define REF_DELETED_LOOSE 0x200

/*
* Return the length of time to retry acquiring a loose reference lock
* before giving up, in milliseconds:
*/
long get_files_ref_lock_timeout_ms(void);

/*
* Return true iff refname is minimally safe. "Safe" here means that
* deleting a loose reference by this name will not do any damage, for

Loading…
Cancel
Save