io-util: introduce loop_write_full that takes a timeout

Also drop do_poll as the use case is covered
by timeout.
This commit is contained in:
Mike Yuan
2023-09-07 20:30:44 +08:00
parent 82b7bf8c1c
commit e22c60a9d5
34 changed files with 103 additions and 81 deletions
+7 -7
View File
@@ -614,7 +614,7 @@ int compress_stream_xz(int fdf, int fdt, uint64_t max_bytes, uint64_t *ret_uncom
n = sizeof(out) - s.avail_out;
k = loop_write(fdt, out, n, false);
k = loop_write(fdt, out, n);
if (k < 0)
return k;
@@ -693,7 +693,7 @@ int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes, uint64_t *ret_unco
"Compressed stream longer than %" PRIu64 " bytes", max_bytes);
if (out_allocsize - offset < frame_size + 4) {
k = loop_write(fdt, out_buff, offset, false);
k = loop_write(fdt, out_buff, offset);
if (k < 0)
return k;
offset = 0;
@@ -706,7 +706,7 @@ int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes, uint64_t *ret_unco
offset += n;
total_out += n;
r = loop_write(fdt, out_buff, offset, false);
r = loop_write(fdt, out_buff, offset);
if (r < 0)
return r;
@@ -779,7 +779,7 @@ int decompress_stream_xz(int fdf, int fdt, uint64_t max_bytes) {
max_bytes -= n;
}
k = loop_write(fdt, out, n, false);
k = loop_write(fdt, out, n);
if (k < 0)
return k;
@@ -845,7 +845,7 @@ int decompress_stream_lz4(int in, int out, uint64_t max_bytes) {
goto cleanup;
}
r = loop_write(out, buf, produced, false);
r = loop_write(out, buf, produced);
if (r < 0)
goto cleanup;
}
@@ -931,7 +931,7 @@ int compress_stream_zstd(int fdf, int fdt, uint64_t max_bytes, uint64_t *ret_unc
if (left < output.pos)
return -EFBIG;
wrote = loop_write(fdt, output.dst, output.pos, 1);
wrote = loop_write_full(fdt, output.dst, output.pos, USEC_INFINITY);
if (wrote < 0)
return wrote;
@@ -1041,7 +1041,7 @@ int decompress_stream_zstd(int fdf, int fdt, uint64_t max_bytes) {
if (left < output.pos)
return -EFBIG;
wrote = loop_write(fdt, output.dst, output.pos, 1);
wrote = loop_write_full(fdt, output.dst, output.pos, USEC_INFINITY);
if (wrote < 0)
return wrote;
+1 -1
View File
@@ -232,7 +232,7 @@ int efi_set_variable(const char *variable, const void *value, size_t size) {
buf->attr = attr;
memcpy(buf->buf, value, size);
r = loop_write(fd, buf, sizeof(uint32_t) + size, false);
r = loop_write(fd, buf, sizeof(uint32_t) + size);
if (r < 0)
goto finish;
+29 -10
View File
@@ -5,6 +5,7 @@
#include <stdio.h>
#include <unistd.h>
#include "errno-util.h"
#include "io-util.h"
#include "string-util.h"
#include "time-util.h"
@@ -105,18 +106,19 @@ int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
return 0;
}
int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
int loop_write_full(int fd, const void *buf, size_t nbytes, usec_t timeout) {
const uint8_t *p;
usec_t end;
int r;
assert(fd >= 0);
assert(buf || nbytes == 0);
if (nbytes == 0) {
static const dummy_t dummy[0];
assert_cc(sizeof(dummy) == 0);
p = (const void*) dummy; /* Some valid pointer, in case NULL was specified */
} else {
assert(buf);
if (nbytes == SIZE_MAX)
nbytes = strlen(buf);
else if (_unlikely_(nbytes > (size_t) SSIZE_MAX))
@@ -125,6 +127,9 @@ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
p = buf;
}
/* When timeout is 0 or USEC_INFINITY this is not used. But we initialize it to a sensible value. */
end = timestamp_is_set(timeout) ? usec_add(now(CLOCK_MONOTONIC), timeout) : USEC_INFINITY;
do {
ssize_t k;
@@ -133,16 +138,30 @@ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
if (errno == EINTR)
continue;
if (errno == EAGAIN && do_poll) {
/* We knowingly ignore any return value here,
* and expect that any error/EOF is reported
* via write() */
if (errno != EAGAIN || timeout == 0)
return -errno;
(void) fd_wait_for_event(fd, POLLOUT, USEC_INFINITY);
continue;
usec_t wait_for;
if (timeout == USEC_INFINITY)
wait_for = USEC_INFINITY;
else {
usec_t t = now(CLOCK_MONOTONIC);
if (t >= end)
return -ETIME;
wait_for = usec_sub_unsigned(end, t);
}
return -errno;
r = fd_wait_for_event(fd, POLLOUT, wait_for);
if (timeout == USEC_INFINITY || ERRNO_IS_NEG_TRANSIENT(r))
/* If timeout == USEC_INFINITY we knowingly ignore any return value
* here, and expect that any error/EOF is reported via write() */
continue;
if (r < 0)
return r;
if (r == 0)
return -ETIME;
}
if (_unlikely_(nbytes > 0 && k == 0)) /* Can't really happen */
+5 -1
View File
@@ -15,7 +15,11 @@ int flush_fd(int fd);
ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll);
int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll);
int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll);
int loop_write_full(int fd, const void *buf, size_t nbytes, usec_t timeout);
static inline int loop_write(int fd, const void *buf, size_t nbytes) {
return loop_write_full(fd, buf, nbytes, 0);
}
int pipe_eof(int fd);
+1 -1
View File
@@ -223,7 +223,7 @@ int random_write_entropy(int fd, const void *seed, size_t size, bool credit) {
if (ioctl(fd, RNDADDENTROPY, info) < 0)
return -errno;
} else {
r = loop_write(fd, seed, size, false);
r = loop_write(fd, seed, size);
if (r < 0)
return r;
}
+2 -2
View File
@@ -569,7 +569,7 @@ int vt_disallocate(const char *name) {
"\033[r" /* clear scrolling region */
"\033[H" /* move home */
"\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
10, false);
10);
return 0;
}
@@ -1544,7 +1544,7 @@ int set_terminal_cursor_position(int fd, unsigned int row, unsigned int column)
xsprintf(cursor_position, "\x1B[%u;%uH", row, column);
r = loop_write(fd, cursor_position, SIZE_MAX, /* do_poll = */false);
r = loop_write(fd, cursor_position, SIZE_MAX);
if (r < 0)
return log_warning_errno(r, "Failed to set cursor position, ignoring: %m");