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

[PATCH v4 09/23] rename_tmp_log(): use raceproof_create_file()

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Jan 6, 2017, 16:22 UTC
Message-ID
<b783c8055c36004c09361eddd14659d83633baad.1483719289.git.mhagger@alum.mit.edu>
In-Reply-To
<cover.1483719289.git.mhagger@alum.mit.edu>

Besides shortening the code, this saves an unnecessary call to safe_create_leading_directories_const() in almost all cases.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 refs/files-backend.c | 73 +++++++++++++++++++++-------------------------------
 1 file changed, 30 insertions(+), 43 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 74de289..3f18a01 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2489,55 +2489,42 @@ static int files_delete_refs(struct ref_store *ref_store,
  */
 #define TMP_RENAMED_LOG  "logs/refs/.tmp-renamed-log"
 
-static int rename_tmp_log(const char *newrefname)
+static int rename_tmp_log_callback(const char *path, void *cb)
 {
-	int attempts_remaining = 4;
-	struct strbuf path = STRBUF_INIT;
-	int ret = -1;
+	int *true_errno = cb;
 
- retry:
-	strbuf_reset(&path);
-	strbuf_git_path(&path, "logs/%s", newrefname);
-	switch (safe_create_leading_directories_const(path.buf)) {
-	case SCLD_OK:
-		break; /* success */
-	case SCLD_VANISHED:
-		if (--attempts_remaining > 0)
-			goto retry;
-		/* fall through */
-	default:
-		error("unable to create directory for %s", newrefname);
-		goto out;
+	if (rename(git_path(TMP_RENAMED_LOG), path)) {
+		/*
+		 * rename(a, b) when b is an existing directory ought
+		 * to result in ISDIR, but Solaris 5.8 gives ENOTDIR.
+		 * Sheesh. Record the true errno for error reporting,
+		 * but report EISDIR to raceproof_create_file() so
+		 * that it knows to retry.
+		 */
+		*true_errno = errno;
+		if (errno == ENOTDIR)
+			errno = EISDIR;
+		return -1;
+	} else {
+		return 0;
 	}
+}
 
-	if (rename(git_path(TMP_RENAMED_LOG), path.buf)) {
-		if ((errno==EISDIR || errno==ENOTDIR) && --attempts_remaining > 0) {
-			/*
-			 * rename(a, b) when b is an existing
-			 * directory ought to result in ISDIR, but
-			 * Solaris 5.8 gives ENOTDIR.  Sheesh.
-			 */
-			if (remove_empty_directories(&path)) {
-				error("Directory not empty: logs/%s", newrefname);
-				goto out;
-			}
-			goto retry;
-		} else if (errno == ENOENT && --attempts_remaining > 0) {
-			/*
-			 * Maybe another process just deleted one of
-			 * the directories in the path to newrefname.
-			 * Try again from the beginning.
-			 */
-			goto retry;
-		} else {
+static int rename_tmp_log(const char *newrefname)
+{
+	char *path = git_pathdup("logs/%s", newrefname);
+	int ret, true_errno;
+
+	ret = raceproof_create_file(path, rename_tmp_log_callback, &true_errno);
+	if (ret) {
+		if (errno == EISDIR)
+			error("Directory not empty: %s", path);
+		else
 			error("unable to move logfile "TMP_RENAMED_LOG" to logs/%s: %s",
-				newrefname, strerror(errno));
-			goto out;
-		}
+				newrefname, strerror(true_errno));
 	}
-	ret = 0;
-out:
-	strbuf_release(&path);
+
+	free(path);
 	return ret;
 }
 
-- 
2.9.3
Previous: Michael HaggertyNext: Michael Haggerty
Message 8 of 25 in “Delete directories left empty after ref deletion”
  1. 00/23 Delete directories left empty after ref deletionMichael Haggerty, Jan 6, 2017
  2. 01/23 files_rename_ref(): tidy up whitespaceMichael Haggerty, Jan 6, 2017
  3. 03/23 t5505: use "for-each-ref" to test for the non-existence of referencesMichael Haggerty, Jan 6, 2017
  4. 06/23 raceproof_create_file(): new functionMichael Haggerty, Jan 6, 2017
  5. 02/23 refname_is_safe(): correct docstringMichael Haggerty, Jan 6, 2017
  6. 05/23 safe_create_leading_directories(): set errno on SCLD_EXISTSMichael Haggerty, Jan 6, 2017
  7. 10/23 rename_tmp_log(): improve error reportingMichael Haggerty, Jan 6, 2017
  8. 09/23 rename_tmp_log(): use raceproof_create_file()Michael Haggerty, Jan 6, 2017
  9. 04/23 safe_create_leading_directories_const(): preserve errnoMichael Haggerty, Jan 6, 2017
  10. 07/23 lock_ref_sha1_basic(): inline constantMichael Haggerty, Jan 6, 2017
  11. 13/23 log_ref_setup(): improve robustness against racesMichael Haggerty, Jan 6, 2017
  12. 08/23 lock_ref_sha1_basic(): use raceproof_create_file()Michael Haggerty, Jan 6, 2017
  13. 11/23 log_ref_write(): inline functionMichael Haggerty, Jan 6, 2017
  14. 23/23 files_transaction_commit(): clean up empty directoriesMichael Haggerty, Jan 6, 2017
  15. 18/23 delete_ref_loose(): derive loose reference path from lockMichael Haggerty, Jan 6, 2017
  16. 19/23 delete_ref_loose(): inline functionMichael Haggerty, Jan 6, 2017
  17. 22/23 try_remove_empty_parents(): teach to remove parents of reflogs, tooMichael Haggerty, Jan 6, 2017
  18. 21/23 try_remove_empty_parents(): don't trash argument contentsMichael Haggerty, Jan 6, 2017
  19. 20/23 try_remove_empty_parents(): rename parameter "name" -> "refname"Michael Haggerty, Jan 6, 2017
  20. 16/23 log_ref_setup(): manage the name of the reflog file internallyMichael Haggerty, Jan 6, 2017
  21. 12/23 log_ref_setup(): separate code for create vs non-createMichael Haggerty, Jan 6, 2017
  22. 15/23 log_ref_write_1(): don't depend on logfile argumentMichael Haggerty, Jan 6, 2017
  23. 17/23 log_ref_write_1(): inline functionMichael Haggerty, Jan 6, 2017
  24. 14/23 log_ref_setup(): pass the open file descriptor back to the callerMichael Haggerty, Jan 6, 2017
  25. Jeff KingJan 6, 2017

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.