All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stefan Beller <sbeller@google.com>
To: Jonathan Nieder <jrnieder@gmail.com>
Cc: Michael Haggerty <mhagger@alum.mit.edu>,
	Junio C Hamano <gitster@pobox.com>,
	Ronnie Sahlberg <ronniesahlberg@gmail.com>,
	git@vger.kernel.org
Subject: Re: [PATCH 07/23] expire_reflog(): use a lock_file for rewriting the reflog file
Date: Fri, 5 Dec 2014 11:18:29 -0800	[thread overview]
Message-ID: <20141205191829.GB16682@google.com> (raw)
In-Reply-To: <20141205002331.GJ16345@google.com>

On Thu, Dec 04, 2014 at 04:23:31PM -0800, Jonathan Nieder wrote:
> Michael Haggerty wrote:
> 
> > We don't actually need the locking functionality, because we already
> > hold the lock on the reference itself, which is how the reflog file is
> > locked. But the lock_file code still does some of the bookkeeping for
> > us and is more careful than the old code here was.
> 
> As you say, the ref lock takes care of mutual exclusion, so we do not
> have to be too careful about compatibility with other tools that might
> not know to lock the reflog.  And this is not tying our hands for a
> future when I might want to lock logs/refs/heads/topic/1 while
> logs/refs/heads/topic still exists as part of the implementation of
> "git mv topic/1 topic".
> 
> Stefan and I had forgotten about that guarantee when looking at that
> kind of operation --- thanks for the reminder.
> 
> Should updates to the HEAD reflog acquire HEAD.lock?  (They don't
> currently.)
> 
> [...]
> > --- a/builtin/reflog.c
> > +++ b/builtin/reflog.c
> > @@ -349,12 +349,14 @@ static int push_tip_to_list(const char *refname, const unsigned char *sha1, int
> >  	return 0;
> >  }
> >  
> > +static struct lock_file reflog_lock;
> 
> If this lockfile is only used in that one function, it can be declared
> inside the function.
> 
> If it is meant to be used throughout the 'git reflog' command, then it
> can go near the top of the file.
> 

After the series completes, this lock is only used in reflog_expire.
So I'd rather move it inside the function? Then we could run the reflog_expire
function in parallel for different locks in theory?

> > +
> >  static int expire_reflog(const char *refname, const unsigned char *sha1, void *cb_data)
> >  {
> >  	struct cmd_reflog_expire_cb *cmd = cb_data;
> >  	struct expire_reflog_cb cb;
> >  	struct ref_lock *lock;
> > -	char *log_file, *newlog_path = NULL;
> > +	char *log_file;
> >  	struct commit *tip_commit;
> >  	struct commit_list *tips;
> >  	int status = 0;
> > @@ -372,10 +374,14 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, void *c
> >  		unlock_ref(lock);
> >  		return 0;
> >  	}
> > +
> >  	log_file = git_pathdup("logs/%s", refname);
> >  	if (!cmd->dry_run) {
> > -		newlog_path = git_pathdup("logs/%s.lock", refname);
> > -		cb.newlog = fopen(newlog_path, "w");
> > +		if (hold_lock_file_for_update(&reflog_lock, log_file, 0) < 0)
> > +			goto failure;
> 
> hold_lock_file_for_update doesn't print a message.  Code to print one
> looks like
> 
> 	if (hold_lock_file_for_update(&reflog_lock, log_file, 0) < 0) {
> 		unable_to_lock_message(log_file, errno, &err);
> 		error("%s", err.buf);
> 		goto failure;
> 	}
> 
> (A patch in flight changes that to
> 
> 	if (hold_lock_file_for_update(&reflog_lock, log_file, 0, &err) < 0) {
> 		error("%s", err.buf);
> 		goto failure;
> 	}
> 
> )
> 
> > +		cb.newlog = fdopen_lock_file(&reflog_lock, "w");
> > +		if (!cb.newlog)
> > +			goto failure;
> 
> Hm.  lockfile.c::fdopen_lock_file ought to use xfdopen to make this
> case impossible.  And xfdopen should use try_to_free_routine() and
> try again on failure.
> 
> [...]
> > @@ -423,10 +429,9 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, void *c
> >  	}
> >  
> >  	if (cb.newlog) {
> > -		if (fclose(cb.newlog)) {
> > -			status |= error("%s: %s", strerror(errno),
> > -					newlog_path);
> > -			unlink(newlog_path);
> > +		if (close_lock_file(&reflog_lock)) {
> > +			status |= error("Couldn't write %s: %s", log_file,
> > +					strerror(errno));
> 
> Style nit: error messages usually start with a lowercase letter
> (though I realize nearby examples are already inconsistent).
> 
> commit_lock_file() can take care of the close_lock_file automatically.
> 
> [...]
> > @@ -434,21 +439,23 @@ static int expire_reflog(const char *refname, const unsigned char *sha1, void *c
> >  			 close_ref(lock) < 0)) {
> >  			status |= error("Couldn't write %s",
> >  					lock->lk->filename.buf);
> > -			unlink(newlog_path);
> > -		} else if (rename(newlog_path, log_file)) {
> > -			status |= error("cannot rename %s to %s",
> > -					newlog_path, log_file);
> > -			unlink(newlog_path);
> > +			rollback_lock_file(&reflog_lock);
> > +		} else if (commit_lock_file(&reflog_lock)) {
> > +			status |= error("cannot rename %s.lock to %s",
> > +					log_file, log_file);
> 
> Most callers say "unable to commit reflog '%s'", log_file to hedge their
> bets in case the close failed (which may be what you were avoiding
> above.
> 
> errno is meaningful when commit_lock_file fails, making a more
> detailed diagnosis from strerror(errno) possible.
> 
> Thanks,
> Jonathan

  parent reply	other threads:[~2014-12-05 19:18 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-04 23:08 [PATCH 00/23] Add reflog_expire() to the references API Michael Haggerty
2014-12-04 23:08 ` [PATCH 01/23] refs.c: make ref_transaction_create a wrapper for ref_transaction_update Michael Haggerty
2014-12-04 23:08 ` [PATCH 02/23] refs.c: make ref_transaction_delete " Michael Haggerty
2014-12-04 23:08 ` [PATCH 03/23] refs.c: add a function to append a reflog entry to a fd Michael Haggerty
2014-12-04 23:08 ` [PATCH 04/23] expire_reflog(): remove unused parameter Michael Haggerty
2014-12-04 23:20   ` Jonathan Nieder
2014-12-04 23:28   ` Jonathan Nieder
2014-12-05 12:43     ` Michael Haggerty
2014-12-04 23:08 ` [PATCH 05/23] expire_reflog(): rename "ref" parameter to "refname" Michael Haggerty
2014-12-04 23:44   ` Jonathan Nieder
2014-12-04 23:08 ` [PATCH 06/23] expire_reflog(): exit early if the reference has no reflog Michael Haggerty
2014-12-04 23:48   ` Jonathan Nieder
2014-12-04 23:53   ` Jonathan Nieder
2014-12-05 15:10     ` Michael Haggerty
2014-12-04 23:08 ` [PATCH 07/23] expire_reflog(): use a lock_file for rewriting the reflog file Michael Haggerty
2014-12-05  0:23   ` Jonathan Nieder
2014-12-05  2:19     ` Stefan Beller
2014-12-08 10:07       ` Michael Haggerty
2014-12-09 18:47         ` Junio C Hamano
2014-12-09 18:54           ` Jeff King
2014-12-05 19:18     ` Stefan Beller [this message]
2014-12-05 19:32       ` Junio C Hamano
2014-12-05 19:41         ` Stefan Beller
2014-12-05 20:55           ` Junio C Hamano
2014-12-08 14:05     ` Michael Haggerty
2014-12-05  2:59   ` ronnie sahlberg
2014-12-08 10:40     ` Michael Haggerty
     [not found]   ` <CAN05THTTba-1n12hBszJAU-O+wsbSFd5Lt+kMk7_MU_0C=wZGQ@mail.gmail.com>
2014-12-05 17:47     ` Stefan Beller
2014-12-04 23:08 ` [PATCH 08/23] Extract function should_expire_reflog_ent() Michael Haggerty
2014-12-08 22:33   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 09/23] expire_reflog(): extract two policy-related functions Michael Haggerty
2014-12-05 19:02   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 10/23] expire_reflog(): add a "flags" argument Michael Haggerty
2014-12-08 22:35   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 11/23] expire_reflog(): move dry_run to flags argument Michael Haggerty
2014-12-08 22:38   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 12/23] expire_reflog(): move updateref " Michael Haggerty
2014-12-08 22:42   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 13/23] Rename expire_reflog_cb to expire_reflog_policy_cb Michael Haggerty
2014-12-08 22:46   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 14/23] struct expire_reflog_cb: a new callback data type Michael Haggerty
2014-12-08 22:49   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 15/23] expire_reflog(): pass flags through to expire_reflog_ent() Michael Haggerty
2014-12-08 22:55   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 16/23] expire_reflog(): move verbose to flags argument Michael Haggerty
2014-12-08 22:56   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 17/23] expire_reflog(): move rewrite " Michael Haggerty
2014-12-08 22:58   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 18/23] Move newlog and last_kept_sha1 to "struct expire_reflog_cb" Michael Haggerty
2014-12-08 22:59   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 19/23] expire_reflog(): treat the policy callback data as opaque Michael Haggerty
2014-12-08 23:12   ` Stefan Beller
2014-12-04 23:08 ` [PATCH 20/23] reflog_expire(): new function in the reference API Michael Haggerty
2014-12-08 23:32   ` Stefan Beller
2014-12-12  8:23     ` Michael Haggerty
2014-12-12  8:50       ` Jeff King
2014-12-12 18:57         ` Junio C Hamano
2014-12-04 23:08 ` [PATCH 21/23] refs.c: remove unlock_ref/close_ref/commit_ref from the refs api Michael Haggerty
2014-12-04 23:08 ` [PATCH 22/23] lock_any_ref_for_update(): inline function Michael Haggerty
2014-12-08 23:34   ` Stefan Beller
2014-12-11  0:13     ` Michael Haggerty
2014-12-04 23:08 ` [PATCH 23/23] refs.c: don't expose the internal struct ref_lock in the header file Michael Haggerty
2014-12-04 23:47 ` [PATCH 00/23] Add reflog_expire() to the references API Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141205191829.GB16682@google.com \
    --to=sbeller@google.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jrnieder@gmail.com \
    --cc=mhagger@alum.mit.edu \
    --cc=ronniesahlberg@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.