aboutsummaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2026-03-24 12:31:34 -0700
committerJunio C Hamano <gitster@pobox.com>2026-03-24 12:31:34 -0700
commit8023abc632ea45a9a1b7f78b13db2cf541849775 (patch)
treeb06aa8b5ec54b28bd580d80dbee0afe14b9149bc /compat
parent231f8100c41fdbdd49f5bca953fff775a79321db (diff)
parent835e0aaf6f0e07e9f9a393ed0e456db7c1be33ef (diff)
downloadgit-8023abc632ea45a9a1b7f78b13db2cf541849775.tar.xz
Merge branch 'ps/upload-pack-buffer-more-writes'
Reduce system overhead "git upload-pack" spends on relaying "git pack-objects" output to the "git fetch" running on the other end of the connection. * ps/upload-pack-buffer-more-writes: builtin/pack-objects: reduce lock contention when writing packfile data csum-file: drop `hashfd_throughput()` csum-file: introduce `hashfd_ext()` sideband: use writev(3p) to send pktlines wrapper: introduce writev(3p) wrappers compat/posix: introduce writev(3p) wrapper upload-pack: reduce lock contention when writing packfile data upload-pack: prefer flushing data over sending keepalive upload-pack: adapt keepalives based on buffering upload-pack: fix debug statement when flushing packfile data
Diffstat (limited to 'compat')
-rw-r--r--compat/posix.h14
-rw-r--r--compat/writev.c44
2 files changed, 58 insertions, 0 deletions
diff --git a/compat/posix.h b/compat/posix.h
index 245386fa4a..3c611d2736 100644
--- a/compat/posix.h
+++ b/compat/posix.h
@@ -137,6 +137,9 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/statvfs.h>
+#ifndef NO_WRITEV
+#include <sys/uio.h>
+#endif
#include <termios.h>
#ifndef NO_SYS_SELECT_H
#include <sys/select.h>
@@ -323,6 +326,17 @@ int git_lstat(const char *, struct stat *);
ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
#endif
+#ifdef NO_WRITEV
+#define writev git_writev
+#define iovec git_iovec
+struct git_iovec {
+ void *iov_base;
+ size_t iov_len;
+};
+
+ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt);
+#endif
+
#ifdef NO_SETENV
#define setenv gitsetenv
int gitsetenv(const char *, const char *, int);
diff --git a/compat/writev.c b/compat/writev.c
new file mode 100644
index 0000000000..3a94870a2f
--- /dev/null
+++ b/compat/writev.c
@@ -0,0 +1,44 @@
+#include "../git-compat-util.h"
+#include "../wrapper.h"
+
+ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt)
+{
+ size_t total_written = 0;
+ size_t sum = 0;
+
+ /*
+ * According to writev(3p), the syscall shall error with EINVAL in case
+ * the sum of `iov_len` overflows `ssize_t`.
+ */
+ for (int i = 0; i < iovcnt; i++) {
+ if (iov[i].iov_len > maximum_signed_value_of_type(ssize_t) ||
+ iov[i].iov_len + sum > maximum_signed_value_of_type(ssize_t)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ sum += iov[i].iov_len;
+ }
+
+ for (int i = 0; i < iovcnt; i++) {
+ const char *bytes = iov[i].iov_base;
+ size_t iovec_written = 0;
+
+ while (iovec_written < iov[i].iov_len) {
+ ssize_t bytes_written = xwrite(fd, bytes + iovec_written,
+ iov[i].iov_len - iovec_written);
+ if (bytes_written < 0) {
+ if (total_written)
+ goto out;
+ return bytes_written;
+ }
+ if (!bytes_written)
+ goto out;
+ iovec_written += bytes_written;
+ total_written += bytes_written;
+ }
+ }
+
+out:
+ return (ssize_t) total_written;
+}