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

[PATCH v7 4/9] core.fsyncobjectfiles: batched disk flushes

From
NGNeeraj Singh via GitGitGadget <gitgitgadget@gmail.com>
Date
Sep 28, 2021, 23:32 UTC
Message-ID
<55556bb3e90225263fa39d8813d1831eda135eb5.1632871972.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1076.v7.git.git.1632871971.gitgitgadget@gmail.com>
From: Neeraj Singh <neerajsi@microsoft.com>

When adding many objects to a repo with core.fsyncObjectFiles set to true, the cost of fsync'ing each object file can become prohibitive.

One major source of the cost of fsync is the implied flush of the hardware writeback cache within the disk drive. Fortunately, Windows, and macOS offer mechanisms to write data from the filesystem page cache without initiating a hardware flush. Linux has the sync_file_range API, which issues a pagecache writeback request reliably after version 5.2.

This patch introduces a new 'core.fsyncObjectFiles = batch' option that batches up hardware flushes. It hooks into the bulk-checkin plugging and unplugging functionality and takes advantage of tmp-objdir.

When the new mode is enabled do the following for each new object:
1. Create the object in a tmp-objdir.
2. Issue a pagecache writeback request and wait for it to complete.
At the end of the entire transaction when unplugging bulk checkin:
1. Issue an fsync against a dummy file to flush the hardware writeback
   cache, which should by now have processed the tmp-objdir writes.
2. Rename all of the tmp-objdir files to their final names.
3. When updating the index and/or refs, we assume that Git will issue
   another fsync internal to that operation. This is not the case today,
   but may be a good extension to those components.

On a filesystem with a singular journal that is updated during name operations (e.g. create, link, rename, etc), such as NTFS, HFS+, or XFS we would expect the fsync to trigger a journal writeout so that this sequence is enough to ensure that the user's data is durable by the time the git command returns.

This change also updates the macOS code to trigger a real hardware flush via fnctl(fd, F_FULLFSYNC) when fsync_or_die is called. Previously, on macOS there was no guarantee of durability since a simple fsync(2) call does not flush any hardware caches.

_Performance numbers_:
Linux - Hyper-V VM running Kernel 5.11 (Ubuntu 20.04) on a fast SSD.
Mac - macOS 11.5.1 running on a Mac mini on a 1TB Apple SSD.
Windows - Same host as Linux, a preview version of Windows 11.
	  This number is from a patch later in the series.
Adding 500 files to the repo with 'git add' Times reported in seconds.
core.fsyncObjectFiles | Linux | Mac   | Windows
----------------------|-------|-------|--------
                false | 0.06  |  0.35 | 0.61
                true  | 1.88  | 11.18 | 2.47
                batch | 0.15  |  0.41 | 1.53
Signed-off-by: Neeraj Singh <neerajsi@microsoft.com>
---
 Documentation/config/core.txt | 29 ++++++++++++---
 Makefile                      |  6 +++
 bulk-checkin.c                | 70 +++++++++++++++++++++++++++++++++++
 bulk-checkin.h                |  2 +
 cache.h                       |  8 +++-
 config.c                      |  7 +++-
 config.mak.uname              |  1 +
 configure.ac                  |  8 ++++
 environment.c                 |  2 +-
 git-compat-util.h             |  7 ++++
 object-file.c                 | 12 +++++-
 tmp-objdir.c                  |  2 -
 wrapper.c                     | 44 ++++++++++++++++++++++
 write-or-die.c                |  2 +-
 14 files changed, 187 insertions(+), 13 deletions(-)
diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt
index c04f62a54a1..200b4d9f06e 100644
--- a/Documentation/config/core.txt
+++ b/Documentation/config/core.txt
@@ -548,12 +548,29 @@ core.whitespace::
   errors. The default tab width is 8. Allowed values are 1 to 63.
 
 core.fsyncObjectFiles::
-	This boolean will enable 'fsync()' when writing object files.
-+
-This is a total waste of time and effort on a filesystem that orders
-data writes properly, but can be useful for filesystems that do not use
-journalling (traditional UNIX filesystems) or that only journal metadata
-and not file contents (OS X's HFS+, or Linux ext3 with "data=writeback").
+	A value indicating the level of effort Git will expend in
+	trying to make objects added to the repo durable in the event
+	of an unclean system shutdown. This setting currently only
+	controls loose objects in the object store, so updates to any
+	refs or the index may not be equally durable.
++
+* `false` allows data to remain in file system caches according to
+  operating system policy, whence it may be lost if the system loses power
+  or crashes.
+* `true` triggers a data integrity flush for each loose object added to the
+  object store. This is the safest setting that is likely to ensure durability
+  across all operating systems and file systems that honor the 'fsync' system
+  call. However, this setting comes with a significant performance cost on
+  common hardware. Git does not currently fsync parent directories for
+  newly-added files, so some filesystems may still allow data to be lost on
+  system crash.
+* `batch` enables an experimental mode that uses interfaces available in some
+  operating systems to write loose object data with a minimal set of FLUSH
+  CACHE (or equivalent) commands sent to the storage controller. If the
+  operating system interfaces are not available, this mode behaves the same as
+  `true`. This mode is expected to be as safe as `true` on macOS for repos
+  stored on HFS+ or APFS filesystems and on Windows for repos stored on NTFS or
+  ReFS.
 
 core.preloadIndex::
 	Enable parallel index preload for operations like 'git diff'
diff --git a/Makefile b/Makefile
index a9f9b689f0c..313b3dc7cd6 100644
--- a/Makefile
+++ b/Makefile
@@ -406,6 +406,8 @@ all::
 #
 # Define HAVE_CLOCK_MONOTONIC if your platform has CLOCK_MONOTONIC.
 #
+# Define HAVE_SYNC_FILE_RANGE if your platform has sync_file_range.
+#
 # Define NEEDS_LIBRT if your platform requires linking with librt (glibc version
 # before 2.17) for clock_gettime and CLOCK_MONOTONIC.
 #
@@ -1874,6 +1876,10 @@ ifdef HAVE_CLOCK_MONOTONIC
 	BASIC_CFLAGS += -DHAVE_CLOCK_MONOTONIC
 endif
 
+ifdef HAVE_SYNC_FILE_RANGE
+	BASIC_CFLAGS += -DHAVE_SYNC_FILE_RANGE
+endif
+
 ifdef NEEDS_LIBRT
 	EXTLIBS += -lrt
 endif
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 6ae18401e04..e6c830f9c0f 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -3,14 +3,20 @@
  */
 #include "cache.h"
 #include "bulk-checkin.h"
+#include "lockfile.h"
 #include "repository.h"
 #include "csum-file.h"
 #include "pack.h"
 #include "strbuf.h"
+#include "string-list.h"
+#include "tmp-objdir.h"
 #include "packfile.h"
 #include "object-store.h"
 
 static int bulk_checkin_plugged;
+static int needs_batch_fsync;
+
+static struct tmp_objdir *bulk_fsync_objdir;
 
 static struct bulk_checkin_state {
 	char *pack_tmp_name;
@@ -79,6 +85,34 @@ clear_exit:
 	reprepare_packed_git(the_repository);
 }
 
+/*
+ * Cleanup after batch-mode fsync_object_files.
+ */
+static void do_batch_fsync(void)
+{
+	/*
+	 * Issue a full hardware flush against a temporary file to ensure
+	 * that all objects are durable before any renames occur.  The code in
+	 * fsync_loose_object_bulk_checkin has already issued a writeout
+	 * request, but it has not flushed any writeback cache in the storage
+	 * hardware.
+	 */
+
+	if (needs_batch_fsync) {
+		struct strbuf temp_path = STRBUF_INIT;
+		struct tempfile *temp;
+
+		strbuf_addf(&temp_path, "%s/bulk_fsync_XXXXXX", get_object_directory());
+		temp = xmks_tempfile(temp_path.buf);
+		fsync_or_die(get_tempfile_fd(temp), get_tempfile_path(temp));
+		delete_tempfile(&temp);
+		strbuf_release(&temp_path);
+	}
+
+	if (bulk_fsync_objdir)
+		tmp_objdir_migrate(bulk_fsync_objdir);
+}
+
 static int already_written(struct bulk_checkin_state *state, struct object_id *oid)
 {
 	int i;
@@ -273,6 +307,26 @@ static int deflate_to_pack(struct bulk_checkin_state *state,
 	return 0;
 }
 
+void fsync_loose_object_bulk_checkin(int fd)
+{
+	assert(fsync_object_files == FSYNC_OBJECT_FILES_BATCH);
+
+	/*
+	 * If we have a plugged bulk checkin, we issue a call that
+	 * cleans the filesystem page cache but avoids a hardware flush
+	 * command. Later on we will issue a single hardware flush
+	 * before as part of do_batch_fsync.
+	 */
+	if (bulk_checkin_plugged &&
+	    git_fsync(fd, FSYNC_WRITEOUT_ONLY) >= 0) {
+		assert(the_repository->objects->odb->is_temp);
+		if (!needs_batch_fsync)
+			needs_batch_fsync = 1;
+	} else {
+		fsync_or_die(fd, "loose object file");
+	}
+}
+
 int index_bulk_checkin(struct object_id *oid,
 		       int fd, size_t size, enum object_type type,
 		       const char *path, unsigned flags)
@@ -287,6 +341,20 @@ int index_bulk_checkin(struct object_id *oid,
 void plug_bulk_checkin(void)
 {
 	assert(!bulk_checkin_plugged);
+
+	/*
+	 * Create a temporary object directory if the current
+	 * object directory is not already temporary.
+	 */
+	if (fsync_object_files == FSYNC_OBJECT_FILES_BATCH &&
+	    !the_repository->objects->odb->is_temp) {
+		bulk_fsync_objdir = tmp_objdir_create("bulk-fsync");
+		if (!bulk_fsync_objdir)
+			die(_("Could not create temporary object directory for core.fsyncobjectfiles=batch"));
+
+		tmp_objdir_replace_primary_odb(bulk_fsync_objdir, 0);
+	}
+
 	bulk_checkin_plugged = 1;
 }
 
@@ -296,4 +364,6 @@ void unplug_bulk_checkin(void)
 	bulk_checkin_plugged = 0;
 	if (bulk_checkin_state.f)
 		finish_bulk_checkin(&bulk_checkin_state);
+
+	do_batch_fsync();
 }
diff --git a/bulk-checkin.h b/bulk-checkin.h
index b26f3dc3b74..08f292379b6 100644
--- a/bulk-checkin.h
+++ b/bulk-checkin.h
@@ -6,6 +6,8 @@
 
 #include "cache.h"
 
+void fsync_loose_object_bulk_checkin(int fd);
+
 int index_bulk_checkin(struct object_id *oid,
 		       int fd, size_t size, enum object_type type,
 		       const char *path, unsigned flags);
diff --git a/cache.h b/cache.h
index f6295f3b048..1ed8137b5e6 100644
--- a/cache.h
+++ b/cache.h
@@ -984,7 +984,13 @@ void reset_shared_repository(void);
 extern int read_replace_refs;
 extern char *git_replace_ref_base;
 
-extern int fsync_object_files;
+enum fsync_object_files_mode {
+    FSYNC_OBJECT_FILES_OFF,
+    FSYNC_OBJECT_FILES_ON,
+    FSYNC_OBJECT_FILES_BATCH
+};
+
+extern enum fsync_object_files_mode fsync_object_files;
 extern int core_preload_index;
 extern int precomposed_unicode;
 extern int protect_hfs;
diff --git a/config.c b/config.c
index 2edf835262f..8315d020eeb 100644
--- a/config.c
+++ b/config.c
@@ -1506,7 +1506,12 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
 	}
 
 	if (!strcmp(var, "core.fsyncobjectfiles")) {
-		fsync_object_files = git_config_bool(var, value);
+		if (value && !strcmp(value, "batch"))
+			fsync_object_files = FSYNC_OBJECT_FILES_BATCH;
+		else if (git_config_bool(var, value))
+			fsync_object_files = FSYNC_OBJECT_FILES_ON;
+		else
+			fsync_object_files = FSYNC_OBJECT_FILES_OFF;
 		return 0;
 	}
 
diff --git a/config.mak.uname b/config.mak.uname
index 76516aaa9a5..e6d482fbcc6 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -53,6 +53,7 @@ ifeq ($(uname_S),Linux)
 	HAVE_CLOCK_MONOTONIC = YesPlease
 	# -lrt is needed for clock_gettime on glibc <= 2.16
 	NEEDS_LIBRT = YesPlease
+	HAVE_SYNC_FILE_RANGE = YesPlease
 	HAVE_GETDELIM = YesPlease
 	SANE_TEXT_GREP=-a
 	FREAD_READS_DIRECTORIES = UnfortunatelyYes
diff --git a/configure.ac b/configure.ac
index 031e8d3fee8..c711037d625 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1090,6 +1090,14 @@ AC_COMPILE_IFELSE([CLOCK_MONOTONIC_SRC],
 	[AC_MSG_RESULT([no])
 	HAVE_CLOCK_MONOTONIC=])
 GIT_CONF_SUBST([HAVE_CLOCK_MONOTONIC])
+
+#
+# Define HAVE_SYNC_FILE_RANGE=YesPlease if sync_file_range is available.
+GIT_CHECK_FUNC(sync_file_range,
+	[HAVE_SYNC_FILE_RANGE=YesPlease],
+	[HAVE_SYNC_FILE_RANGE])
+GIT_CONF_SUBST([HAVE_SYNC_FILE_RANGE])
+
 #
 # Define NO_SETITIMER if you don't have setitimer.
 GIT_CHECK_FUNC(setitimer,
diff --git a/environment.c b/environment.c
index 30fca67e6d6..371a73c1e30 100644
--- a/environment.c
+++ b/environment.c
@@ -42,7 +42,7 @@ const char *git_attributes_file;
 const char *git_hooks_path;
 int zlib_compression_level = Z_BEST_SPEED;
 int pack_compression_level = Z_DEFAULT_COMPRESSION;
-int fsync_object_files;
+enum fsync_object_files_mode fsync_object_files;
 size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
 size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
 size_t delta_base_cache_limit = 96 * 1024 * 1024;
diff --git a/git-compat-util.h b/git-compat-util.h
index 7c99eef6612..9daee873782 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -1213,6 +1213,13 @@ __attribute__((format (printf, 1, 2))) NORETURN
 void BUG(const char *fmt, ...);
 #endif
 
+enum fsync_action {
+    FSYNC_WRITEOUT_ONLY,
+    FSYNC_HARDWARE_FLUSH
+};
+
+int git_fsync(int fd, enum fsync_action action);
+
 /*
  * Preserves errno, prints a message, but gives no warning for ENOENT.
  * Returns 0 on success, which includes trying to unlink an object that does
diff --git a/object-file.c b/object-file.c
index 1a3ad558c45..8ea1348f0db 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1932,8 +1932,18 @@ int hash_object_file(const struct git_hash_algo *algo, const void *buf,
 static void close_loose_object(int fd)
 {
 	if (!the_repository->objects->odb->will_destroy) {
-		if (fsync_object_files)
+		switch (fsync_object_files) {
+		case FSYNC_OBJECT_FILES_OFF:
+			break;
+		case FSYNC_OBJECT_FILES_ON:
 			fsync_or_die(fd, "loose object file");
+			break;
+		case FSYNC_OBJECT_FILES_BATCH:
+			fsync_loose_object_bulk_checkin(fd);
+			break;
+		default:
+			BUG("Invalid fsync_object_files mode.");
+		}
 	}
 
 	if (close(fd) != 0)
diff --git a/tmp-objdir.c b/tmp-objdir.c
index 366ffe28511..c26cb5eafee 100644
--- a/tmp-objdir.c
+++ b/tmp-objdir.c
@@ -279,8 +279,6 @@ int tmp_objdir_migrate(struct tmp_objdir *t)
 	if (!t)
 		return 0;
 
-
-
 	if (t->prev_odb) {
 		if (the_repository->objects->odb->will_destroy)
 			BUG("migrating and ODB that was marked for destruction");
diff --git a/wrapper.c b/wrapper.c
index 7c6586af321..bb4f9f043ce 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -540,6 +540,50 @@ int xmkstemp_mode(char *filename_template, int mode)
 	return fd;
 }
 
+int git_fsync(int fd, enum fsync_action action)
+{
+	switch (action) {
+	case FSYNC_WRITEOUT_ONLY:
+
+#ifdef __APPLE__
+		/*
+		 * on macOS, fsync just causes filesystem cache writeback but does not
+		 * flush hardware caches.
+		 */
+		return fsync(fd);
+#endif
+
+#ifdef HAVE_SYNC_FILE_RANGE
+		/*
+		 * On linux 2.6.17 and above, sync_file_range is the way to issue
+		 * a writeback without a hardware flush. An offset of 0 and size of 0
+		 * indicates writeout of the entire file and the wait flags ensure that all
+		 * dirty data is written to the disk (potentially in a disk-side cache)
+		 * before we continue.
+		 */
+
+		return sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WAIT_BEFORE |
+						 SYNC_FILE_RANGE_WRITE |
+						 SYNC_FILE_RANGE_WAIT_AFTER);
+#endif
+
+		errno = ENOSYS;
+		return -1;
+
+	case FSYNC_HARDWARE_FLUSH:
+
+#ifdef __APPLE__
+		return fcntl(fd, F_FULLFSYNC);
+#else
+		return fsync(fd);
+#endif
+
+	default:
+		BUG("unexpected git_fsync(%d) call", action);
+	}
+
+}
+
 static int warn_if_unremovable(const char *op, const char *file, int rc)
 {
 	int err;
diff --git a/write-or-die.c b/write-or-die.c
index 0b1ec8190b6..cc8291d9794 100644
--- a/write-or-die.c
+++ b/write-or-die.c
@@ -57,7 +57,7 @@ void fprintf_or_die(FILE *f, const char *fmt, ...)
 
 void fsync_or_die(int fd, const char *msg)
 {
-	while (fsync(fd) < 0) {
+	while (git_fsync(fd, FSYNC_HARDWARE_FLUSH) < 0) {
 		if (errno != EINTR)
 			die_errno("fsync error on '%s'", msg);
 	}
-- 
gitgitgadget
Previous: Neeraj SinghNext: Neeraj Singh via GitGitGadget
Message 118 of 160 in “[RFC] Implement a bulk-checkin option for core.fsyncObjectFiles”
  1. 0/2 [RFC] Implement a bulk-checkin option for core.fsyncObjectFilesNeeraj K. Singh via GitGitGadget, Aug 25, 2021
  2. 1/2 object-file: use futimes rather than utimeNeeraj Singh via GitGitGadget, Aug 25, 2021
  3. Johannes SchindelinAug 25, 2021
  4. Neeraj SinghAug 25, 2021
  5. 2/2 core.fsyncobjectfiles: batch disk flushesNeeraj Singh via GitGitGadget, Aug 25, 2021
  6. Christoph HellwigAug 25, 2021
  7. Neeraj SinghAug 25, 2021
  8. Christoph HellwigAug 26, 2021
  9. Ævar Arnfjörð BjarmasonAug 25, 2021
  10. Neeraj SinghAug 26, 2021
  11. Christoph HellwigAug 26, 2021
  12. Neeraj SinghAug 28, 2021
  13. Christoph HellwigAug 28, 2021
  14. Neeraj SinghAug 31, 2021
  15. Christoph HellwigSep 1, 2021
  16. Christoph HellwigAug 26, 2021
  17. Johannes SchindelinAug 25, 2021
  18. Junio C HamanoAug 25, 2021
  19. Neeraj SinghAug 26, 2021
  20. Neeraj SinghAug 25, 2021
  21. 0/6 Implement a batched fsync option for core.fsyncObjectFilesNeeraj K. Singh via GitGitGadget, Aug 27, 2021
  22. 1/6 object-file: use futimens rather than utimeNeeraj Singh via GitGitGadget, Aug 27, 2021
  23. 2/6 bulk-checkin: rename 'state' variable and separate 'plugged' booleanNeeraj Singh via GitGitGadget, Aug 27, 2021
  24. 3/6 core.fsyncobjectfiles: batched disk flushesNeeraj Singh via GitGitGadget, Aug 27, 2021
  25. 5/6 update-index: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Aug 27, 2021
  26. 6/6 core.fsyncobjectfiles: performance tests for add and stashNeeraj Singh via GitGitGadget, Aug 27, 2021
  27. 4/6 core.fsyncobjectfiles: add windows support for batch modeNeeraj Singh via GitGitGadget, Aug 27, 2021
  28. Neeraj SinghSep 7, 2021
  29. Ævar Arnfjörð BjarmasonSep 7, 2021
  30. Randall S. BeckerSep 7, 2021
  31. Neeraj SinghSep 8, 2021
  32. Ævar Arnfjörð BjarmasonSep 8, 2021
  33. Randall S. BeckerSep 8, 2021
  34. Neeraj SinghSep 8, 2021
  35. Neeraj SinghSep 8, 2021
  36. Junio C HamanoSep 8, 2021
  37. Christoph HellwigSep 8, 2021
  38. Randall S. BeckerSep 8, 2021
  39. 'Christoph Hellwig'Sep 8, 2021
  40. Randall S. BeckerSep 8, 2021
  41. Neeraj SinghSep 8, 2021
  42. Junio C HamanoSep 8, 2021
  43. Neeraj SinghSep 8, 2021
  44. Ævar Arnfjörð BjarmasonSep 8, 2021
  45. 0/6 Implement a batched fsync option for core.fsyncObjectFilesNeeraj K. Singh via GitGitGadget, Sep 14, 2021
  46. 1/6 bulk-checkin: rename 'state' variable and separate 'plugged' booleanNeeraj Singh via GitGitGadget, Sep 14, 2021
  47. 2/6 core.fsyncobjectfiles: batched disk flushesNeeraj Singh via GitGitGadget, Sep 14, 2021
  48. Bagas SanjayaSep 14, 2021
  49. Neeraj SinghSep 14, 2021
  50. Junio C HamanoSep 14, 2021
  51. Junio C HamanoSep 14, 2021
  52. Neeraj SinghSep 15, 2021
  53. 3/6 core.fsyncobjectfiles: add windows support for batch modeNeeraj Singh via GitGitGadget, Sep 14, 2021
  54. 4/6 update-index: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Sep 14, 2021
  55. Junio C HamanoSep 14, 2021
  56. 5/6 core.fsyncobjectfiles: performance tests for add and stashNeeraj Singh via GitGitGadget, Sep 14, 2021
  57. 6/6 core.fsyncobjectfiles: enable batch mode for testingNeeraj Singh via GitGitGadget, Sep 14, 2021
  58. Junio C HamanoSep 15, 2021
  59. Neeraj SinghSep 15, 2021
  60. Junio C HamanoSep 15, 2021
  61. Junio C HamanoSep 16, 2021
  62. Christoph HellwigSep 14, 2021
  63. 0/6 Implement a batched fsync option for core.fsyncObjectFilesNeeraj K. Singh via GitGitGadget, Sep 20, 2021
  64. 5/6 core.fsyncobjectfiles: tests for batch modeNeeraj Singh via GitGitGadget, Sep 20, 2021
  65. Ævar Arnfjörð BjarmasonSep 21, 2021
  66. Neeraj SinghSep 22, 2021
  67. Ævar Arnfjörð BjarmasonSep 22, 2021
  68. Neeraj SinghSep 22, 2021
  69. Ævar Arnfjörð BjarmasonSep 22, 2021
  70. 2/6 core.fsyncobjectfiles: batched disk flushesNeeraj Singh via GitGitGadget, Sep 20, 2021
  71. Ævar Arnfjörð BjarmasonSep 21, 2021
  72. Neeraj SinghSep 22, 2021
  73. Ævar Arnfjörð BjarmasonSep 22, 2021
  74. Neeraj SinghSep 22, 2021
  75. 1/6 bulk-checkin: rename 'state' variable and separate 'plugged' booleanNeeraj Singh via GitGitGadget, Sep 20, 2021
  76. 4/6 update-index: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Sep 20, 2021
  77. Ævar Arnfjörð BjarmasonSep 21, 2021
  78. Neeraj SinghSep 22, 2021
  79. Neeraj SinghSep 23, 2021
  80. 3/6 core.fsyncobjectfiles: add windows support for batch modeNeeraj Singh via GitGitGadget, Sep 20, 2021
  81. Ævar Arnfjörð BjarmasonSep 21, 2021
  82. Neeraj SinghSep 22, 2021
  83. 6/6 core.fsyncobjectfiles: performance tests for add and stashNeeraj Singh via GitGitGadget, Sep 20, 2021
  84. 0/7 Implement a batched fsync option for core.fsyncObjectFilesNeeraj K. Singh via GitGitGadget, Sep 24, 2021
  85. 1/7 object-file.c: do not rename in a temp odbNeeraj Singh via GitGitGadget, Sep 24, 2021
  86. 2/7 bulk-checkin: rename 'state' variable and separate 'plugged' booleanNeeraj Singh via GitGitGadget, Sep 24, 2021
  87. 3/7 core.fsyncobjectfiles: batched disk flushesNeeraj Singh via GitGitGadget, Sep 24, 2021
  88. Neeraj SinghSep 24, 2021
  89. 4/7 update-index: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Sep 24, 2021
  90. Neeraj SinghSep 24, 2021
  91. 5/7 unpack-objects: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Sep 24, 2021
  92. 6/7 core.fsyncobjectfiles: tests for batch modeNeeraj Singh via GitGitGadget, Sep 24, 2021
  93. 7/7 core.fsyncobjectfiles: performance tests for add and stashNeeraj Singh via GitGitGadget, Sep 24, 2021
  94. Neeraj SinghSep 24, 2021
  95. 0/8 Implement a batched fsync option for core.fsyncObjectFilesNeeraj K. Singh via GitGitGadget, Sep 24, 2021
  96. 1/8 object-file.c: do not rename in a temp odbNeeraj Singh via GitGitGadget, Sep 24, 2021
  97. 2/8 bulk-checkin: rename 'state' variable and separate 'plugged' booleanNeeraj Singh via GitGitGadget, Sep 24, 2021
  98. 3/8 core.fsyncobjectfiles: batched disk flushesNeeraj Singh via GitGitGadget, Sep 24, 2021
  99. Bagas SanjayaSep 25, 2021
  100. Neeraj SinghSep 27, 2021
  101. 5/8 update-index: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Sep 24, 2021
  102. 4/8 core.fsyncobjectfiles: add windows support for batch modeNeeraj Singh via GitGitGadget, Sep 24, 2021
  103. Junio C HamanoSep 27, 2021
  104. Neeraj SinghSep 27, 2021
  105. Neeraj SinghSep 27, 2021
  106. Junio C HamanoSep 27, 2021
  107. 6/8 unpack-objects: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Sep 24, 2021
  108. 8/8 core.fsyncobjectfiles: performance tests for add and stashNeeraj Singh via GitGitGadget, Sep 24, 2021
  109. 7/8 core.fsyncobjectfiles: tests for batch modeNeeraj Singh via GitGitGadget, Sep 24, 2021
  110. 0/9 Implement a batched fsync option for core.fsyncObjectFilesNeeraj K. Singh via GitGitGadget, Sep 28, 2021
  111. 1/9 object-file.c: do not rename in a temp odbNeeraj Singh via GitGitGadget, Sep 28, 2021
  112. Jeff KingSep 28, 2021
  113. Neeraj SinghSep 29, 2021
  114. 3/9 bulk-checkin: rename 'state' variable and separate 'plugged' booleanNeeraj Singh via GitGitGadget, Sep 28, 2021
  115. 2/9 tmp-objdir: new API for creating temporary writable databasesNeeraj Singh via GitGitGadget, Sep 28, 2021
  116. Elijah NewrenSep 29, 2021
  117. Neeraj SinghSep 29, 2021
  118. 4/9 core.fsyncobjectfiles: batched disk flushesNeeraj Singh via GitGitGadget, Sep 28, 2021
  119. 5/9 core.fsyncobjectfiles: add windows support for batch modeNeeraj Singh via GitGitGadget, Sep 28, 2021
  120. 6/9 update-index: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Sep 28, 2021
  121. 8/9 core.fsyncobjectfiles: tests for batch modeNeeraj Singh via GitGitGadget, Sep 28, 2021
  122. 7/9 unpack-objects: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Sep 28, 2021
  123. 9/9 core.fsyncobjectfiles: performance tests for add and stashNeeraj Singh via GitGitGadget, Sep 28, 2021
  124. 0/9 Implement a batched fsync option for core.fsyncObjectFilesNeeraj K. Singh via GitGitGadget, Oct 4, 2021
  125. 1/9 tmp-objdir: new API for creating temporary writable databasesNeeraj Singh via GitGitGadget, Oct 4, 2021
  126. 2/9 tmp-objdir: disable ref updates when replacing the primary odbNeeraj Singh via GitGitGadget, Oct 4, 2021
  127. 3/9 bulk-checkin: rename 'state' variable and separate 'plugged' booleanNeeraj Singh via GitGitGadget, Oct 4, 2021
  128. 4/9 core.fsyncobjectfiles: batched disk flushesNeeraj Singh via GitGitGadget, Oct 4, 2021
  129. 5/9 core.fsyncobjectfiles: add windows support for batch modeNeeraj Singh via GitGitGadget, Oct 4, 2021
  130. 6/9 update-index: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Oct 4, 2021
  131. 7/9 unpack-objects: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Oct 4, 2021
  132. 8/9 core.fsyncobjectfiles: tests for batch modeNeeraj Singh via GitGitGadget, Oct 4, 2021
  133. 9/9 core.fsyncobjectfiles: performance tests for add and stashNeeraj Singh via GitGitGadget, Oct 4, 2021
  134. 0/9 Implement a batched fsync option for core.fsyncObjectFilesNeeraj K. Singh via GitGitGadget, Nov 15, 2021
  135. 2/9 tmp-objdir: disable ref updates when replacing the primary odbNeeraj Singh via GitGitGadget, Nov 15, 2021
  136. Ævar Arnfjörð BjarmasonNov 16, 2021
  137. Neeraj SinghNov 16, 2021
  138. 1/9 tmp-objdir: new API for creating temporary writable databasesNeeraj Singh via GitGitGadget, Nov 15, 2021
  139. Elijah NewrenNov 30, 2021
  140. Neeraj SinghNov 30, 2021
  141. Elijah NewrenNov 30, 2021
  142. 3/9 bulk-checkin: rename 'state' variable and separate 'plugged' booleanNeeraj Singh via GitGitGadget, Nov 15, 2021
  143. 4/9 core.fsyncobjectfiles: batched disk flushesNeeraj Singh via GitGitGadget, Nov 15, 2021
  144. 5/9 core.fsyncobjectfiles: add windows support for batch modeNeeraj Singh via GitGitGadget, Nov 15, 2021
  145. 6/9 update-index: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Nov 15, 2021
  146. 7/9 unpack-objects: use the bulk-checkin infrastructureNeeraj Singh via GitGitGadget, Nov 15, 2021
  147. 8/9 core.fsyncobjectfiles: tests for batch modeNeeraj Singh via GitGitGadget, Nov 15, 2021
  148. 9/9 core.fsyncobjectfiles: performance tests for add and stashNeeraj Singh via GitGitGadget, Nov 15, 2021
  149. Ævar Arnfjörð BjarmasonNov 16, 2021
  150. Neeraj SinghNov 17, 2021
  151. Ævar Arnfjörð BjarmasonNov 17, 2021
  152. Neeraj SinghNov 18, 2021
  153. Ævar Arnfjörð BjarmasonDec 1, 2021
  154. Ævar Arnfjörð BjarmasonMar 9, 2022
  155. Neeraj SinghMar 10, 2022
  156. Ævar Arnfjörð BjarmasonMar 10, 2022
  157. Neeraj SinghMar 10, 2022
  158. rsbecker@nexbridge.comMar 10, 2022
  159. Neeraj SinghMar 10, 2022
  160. rsbecker@nexbridge.comMar 10, 2022

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.