On windows, copy file into memory instead of mmap. Since mmap() on windows locks the file, and this map is long-lived, just copy the file into memory instead. This enables us to keep the lookup() paths the same, while avoiding the downsides of mmap() on windows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 98b25e8..af5345d 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -485,6 +485,19 @@ static char *packed_set_peeling_mode(
return data;
}
+static void packed_map_free(refdb_fs_backend *backend)
+{
+ if (backend->packed_refs_map.data) {
+#ifdef GIT_WIN32
+ git__free(backend->packed_refs_map.data);
+#else
+ git_futils_mmap_free(&backend->packed_refs_map);
+#endif
+ backend->packed_refs_map.data = NULL;
+ backend->packed_refs_map.len = 0;
+ }
+}
+
static int packed_map_check(refdb_fs_backend *backend)
{
int error = 0;
@@ -522,7 +535,23 @@ static int packed_map_check(refdb_fs_backend *backend)
return 0;
}
+#ifdef GIT_WIN32
+ /* on windows, we copy the entire file into memory rather than using
+ * mmap() because using mmap() on windows also locks the file and this
+ * map is long-lived. */
+ backend->packed_refs_map.len = (size_t)st.st_size;
+ backend->packed_refs_map.data =
+ git__malloc(backend->packed_refs_map.len);
+ GIT_ERROR_CHECK_ALLOC(backend->packed_refs_map.data);
+ {
+ ssize_t bytesread =
+ p_read(fd, backend->packed_refs_map.data,
+ backend->packed_refs_map.len);
+ error = (bytesread == (ssize_t)backend->packed_refs_map.len) ? 0 : -1;
+ }
+#else
error = git_futils_mmap_ro(&backend->packed_refs_map, fd, 0, (size_t)st.st_size);
+#endif
p_close(fd);
if (error < 0) {
git_mutex_unlock(&backend->prlock);
@@ -1302,10 +1331,7 @@ static int packed_write(refdb_fs_backend *backend)
return error;
}
- if (backend->packed_refs_map.data) {
- git_futils_mmap_free(&backend->packed_refs_map);
- backend->packed_refs_map.data = NULL;
- }
+ packed_map_free(backend);
git_mutex_unlock(&backend->prlock);
@@ -1798,10 +1824,7 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend)
git_sortedcache_free(backend->refcache);
git_mutex_lock(&backend->prlock);
- if (backend->packed_refs_map.data) {
- git_futils_mmap_free(&backend->packed_refs_map);
- backend->packed_refs_map.data = NULL;
- }
+ packed_map_free(backend);
git_mutex_unlock(&backend->prlock);
git_mutex_free(&backend->prlock);