From cb3e368b6913a2446f245e7ae7a7e4ae4a2e6794 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 18 Feb 2025 10:20:37 +0100 Subject: reftable/stack: stop using `read_in_full()` There is a single callsite of `read_in_full()` in the reftable library. Open-code the function to reduce our dependency on the Git library. Note that we only partially port over the logic from `read_in_full()` and its underlying `xread()` helper. Most importantly, the latter also knows to handle `EWOULDBLOCK` via `handle_nonblock()`. This logic is irrelevant for us though because the reftable library never sets the `O_NONBLOCK` option in the first place. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- reftable/stack.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'reftable/stack.c') diff --git a/reftable/stack.c b/reftable/stack.c index 6c4e8be19b..1cc47b94d9 100644 --- a/reftable/stack.c +++ b/reftable/stack.c @@ -115,13 +115,16 @@ out: static int fd_read_lines(int fd, char ***namesp) { - off_t size = lseek(fd, 0, SEEK_END); char *buf = NULL; int err = 0; + off_t size; + + size = lseek(fd, 0, SEEK_END); if (size < 0) { err = REFTABLE_IO_ERROR; goto done; } + err = lseek(fd, 0, SEEK_SET); if (err < 0) { err = REFTABLE_IO_ERROR; @@ -134,9 +137,16 @@ static int fd_read_lines(int fd, char ***namesp) goto done; } - if (read_in_full(fd, buf, size) != size) { - err = REFTABLE_IO_ERROR; - goto done; + for (off_t total_read = 0; total_read < size; ) { + ssize_t bytes_read = read(fd, buf + total_read, size - total_read); + if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR)) + continue; + if (bytes_read < 0 || !bytes_read) { + err = REFTABLE_IO_ERROR; + goto done; + } + + total_read += bytes_read; } buf[size] = 0; -- cgit v1.3 From e31db89558b7f1d622e5a64cf37779b721099814 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 18 Feb 2025 10:20:38 +0100 Subject: reftable/stack: stop using `write_in_full()` Similar to the preceding commit, drop our use of `write_in_full()` and implement a new wrapper `reftable_write_full()` that handles this logic for us. This is done to reduce our dependency on the Git library. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- reftable/stack.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'reftable/stack.c') diff --git a/reftable/stack.c b/reftable/stack.c index 1cc47b94d9..c33f0c3333 100644 --- a/reftable/stack.c +++ b/reftable/stack.c @@ -48,6 +48,25 @@ static int stack_fsync(const struct reftable_write_options *opts, int fd) return fsync(fd); } +static ssize_t reftable_write_data(int fd, const void *data, size_t size) +{ + size_t total_written = 0; + const char *p = data; + + while (total_written < size) { + ssize_t bytes_written = write(fd, p, size - total_written); + if (bytes_written < 0 && (errno == EAGAIN || errno == EINTR)) + continue; + if (bytes_written < 0) + return REFTABLE_IO_ERROR; + + total_written += bytes_written; + p += bytes_written; + } + + return total_written; +} + struct fd_writer { const struct reftable_write_options *opts; int fd; @@ -56,7 +75,7 @@ struct fd_writer { static ssize_t fd_writer_write(void *arg, const void *data, size_t sz) { struct fd_writer *writer = arg; - return write_in_full(writer->fd, data, sz); + return reftable_write_data(writer->fd, data, sz); } static int fd_writer_flush(void *arg) @@ -784,7 +803,8 @@ int reftable_addition_commit(struct reftable_addition *add) goto done; } - err = write_in_full(add->tables_list_lock.fd, table_list.buf, table_list.len); + err = reftable_write_data(add->tables_list_lock.fd, + table_list.buf, table_list.len); reftable_buf_release(&table_list); if (err < 0) { err = REFTABLE_IO_ERROR; @@ -1470,8 +1490,8 @@ static int stack_compact_range(struct reftable_stack *st, goto done; } - err = write_in_full(tables_list_lock.fd, - tables_list_buf.buf, tables_list_buf.len); + err = reftable_write_data(tables_list_lock.fd, + tables_list_buf.buf, tables_list_buf.len); if (err < 0) { err = REFTABLE_IO_ERROR; unlink(new_table_path.buf); -- cgit v1.3 From 712f6cfe5411fdbbf46688c22a40fac7e0a8839b Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 18 Feb 2025 10:20:47 +0100 Subject: reftable/system: introduce `reftable_rand()` Introduce a new system-level `reftable_rand()` function that generates a single unsigned integer for us. The implementation of this function is to be provided by the calling codebase, which allows us to more easily hook into pre-seeded random number generators. Adapt the two callsites where we generated random data. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- reftable/stack.c | 4 ++-- reftable/system.c | 5 +++++ reftable/system.h | 6 ++++++ 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'reftable/stack.c') diff --git a/reftable/stack.c b/reftable/stack.c index c33f0c3333..08893fd454 100644 --- a/reftable/stack.c +++ b/reftable/stack.c @@ -523,7 +523,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st, close(fd); fd = -1; - delay = delay + (delay * git_rand(CSPRNG_BYTES_INSECURE)) / UINT32_MAX + 1; + delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1; sleep_millisec(delay); } @@ -688,7 +688,7 @@ int reftable_stack_add(struct reftable_stack *st, static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max) { char buf[100]; - uint32_t rnd = git_rand(CSPRNG_BYTES_INSECURE); + uint32_t rnd = reftable_rand(); snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x", min, max, rnd); reftable_buf_reset(dest); diff --git a/reftable/system.c b/reftable/system.c index adf8e4d30b..e25ccc0da3 100644 --- a/reftable/system.c +++ b/reftable/system.c @@ -4,6 +4,11 @@ #include "../lockfile.h" #include "../tempfile.h" +uint32_t reftable_rand(void) +{ + return git_rand(CSPRNG_BYTES_INSECURE); +} + int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern) { struct tempfile *tempfile; diff --git a/reftable/system.h b/reftable/system.h index d02eacea8f..bb6a7e6285 100644 --- a/reftable/system.h +++ b/reftable/system.h @@ -14,6 +14,12 @@ https://developers.google.com/open-source/licenses/bsd #include "git-compat-util.h" #include "compat/zlib-compat.h" +/* + * Return a random 32 bit integer. This function is expected to return + * pre-seeded data. + */ +uint32_t reftable_rand(void); + /* * An implementation-specific temporary file. By making this specific to the * implementation it becomes possible to tie temporary files into any kind of -- cgit v1.3 From 10f2935c7f2070368dadde582f94c9c76e2fe991 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 18 Feb 2025 10:20:48 +0100 Subject: reftable/stack: stop using `sleep_millisec()` Refactor our use of `sleep_millisec()` by open-coding it with poll(3p), which is the current implementation of this function. Ideally, we'd use a more direct way to sleep, but there is no equivalent to sleep(3p) that would accept milliseconds as input. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- reftable/stack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'reftable/stack.c') diff --git a/reftable/stack.c b/reftable/stack.c index 08893fd454..6dac015b47 100644 --- a/reftable/stack.c +++ b/reftable/stack.c @@ -524,7 +524,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st, fd = -1; delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1; - sleep_millisec(delay); + poll(NULL, 0, delay); } out: -- cgit v1.3