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

[PATCH v3 05/12] refs: manage lifetime of packed refs cache via reference counting

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Jun 20, 2013, 08:37 UTC
Message-ID
<1371717474-28942-6-git-send-email-mhagger@alum.mit.edu>
In-Reply-To
<1371717474-28942-1-git-send-email-mhagger@alum.mit.edu>

In struct packed_ref_cache, keep a count of the number of users of the data structure. Only free the packed ref cache when the reference count goes to zero rather than when the packed ref cache is cleared. This mechanism will be used to prevent the cache data structure from being freed while it is being iterated over.

So far, only the reference in struct ref_cache::packed is counted; other users will be adjusted in separate commits.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 refs.c | 39 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/refs.c b/refs.c
index b345799..80c172f 100644
--- a/refs.c
+++ b/refs.c
@@ -810,6 +810,14 @@ struct packed_ref_cache {
 	struct ref_entry *root;
 
 	/*
+	 * Count of references to the data structure in this instance,
+	 * including the pointer from ref_cache::packed if any.  The
+	 * data will not be freed as long as the reference count is
+	 * nonzero.
+	 */
+	unsigned int referrers;
+
+	/*
 	 * Iff the packed-refs file associated with this instance is
 	 * currently locked for writing, this points at the associated
 	 * lock (which is owned by somebody else).
@@ -836,14 +844,38 @@ static struct ref_cache {
 /* Lock used for the main packed-refs file: */
 static struct lock_file packlock;
 
+/*
+ * Increment the reference count of *packed_refs.
+ */
+static void acquire_packed_ref_cache(struct packed_ref_cache *packed_refs)
+{
+	packed_refs->referrers++;
+}
+
+/*
+ * Decrease the reference count of *packed_refs.  If it goes to zero,
+ * free *packed_refs and return true; otherwise return false.
+ */
+static int release_packed_ref_cache(struct packed_ref_cache *packed_refs)
+{
+	if (!--packed_refs->referrers) {
+		free_ref_entry(packed_refs->root);
+		free(packed_refs);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
 static void clear_packed_ref_cache(struct ref_cache *refs)
 {
 	if (refs->packed) {
-		if (refs->packed->lock)
+		struct packed_ref_cache *packed_refs = refs->packed;
+
+		if (packed_refs->lock)
 			die("internal error: packed-ref cache cleared while locked");
-		free_ref_entry(refs->packed->root);
-		free(refs->packed);
 		refs->packed = NULL;
+		release_packed_ref_cache(packed_refs);
 	}
 }
 
@@ -1024,6 +1056,7 @@ static struct packed_ref_cache *get_packed_ref_cache(struct ref_cache *refs)
 		FILE *f;
 
 		refs->packed = xcalloc(1, sizeof(*refs->packed));
+		acquire_packed_ref_cache(refs->packed);
 		refs->packed->root = create_dir_entry(refs, "", 0, 0);
 		if (*refs->name)
 			packed_refs_file = git_path_submodule(refs->name, "packed-refs");
-- 
1.8.3.1
Previous: Michael HaggertyNext: Michael Haggerty
Message 6 of 13 in “Fix some reference-related races”
  1. 00/12 Fix some reference-related racesMichael Haggerty, Jun 20, 2013
  2. 01/12 repack_without_ref(): split list curation and entry writingMichael Haggerty, Jun 20, 2013
  3. 02/12 pack_refs(): split creation of packed refs and entry writingMichael Haggerty, Jun 20, 2013
  4. 03/12 refs: wrap the packed refs cache in a level of indirectionMichael Haggerty, Jun 20, 2013
  5. 04/12 refs: implement simple transactions for the packed-refs fileMichael Haggerty, Jun 20, 2013
  6. 05/12 refs: manage lifetime of packed refs cache via reference countingMichael Haggerty, Jun 20, 2013
  7. 06/12 do_for_each_entry(): increment the packed refs cache refcountMichael Haggerty, Jun 20, 2013
  8. 07/12 packed_ref_cache: increment refcount when lockedMichael Haggerty, Jun 20, 2013
  9. 08/12 Extract a struct stat_data from cache_entryMichael Haggerty, Jun 20, 2013
  10. 09/12 add a stat_validity structMichael Haggerty, Jun 20, 2013
  11. 10/12 get_packed_ref_cache: reload packed-refs file when it changesMichael Haggerty, Jun 20, 2013
  12. 11/12 for_each_ref: load all loose refs before packed refsMichael Haggerty, Jun 20, 2013
  13. 12/12 refs: do not invalidate the packed-refs cache unnecessarilyMichael Haggerty, Jun 20, 2013

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.