Handle short writes and EINTR in sflush, handle_write, and parity_write

This commit is contained in:
Andrea Mazzoleni 2026-08-16 16:09:12 +02:00
parent 712b54ec98
commit 091e44afed
3 changed files with 50 additions and 24 deletions

View file

@ -273,13 +273,15 @@ ssize_t handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsign
read_size = file_block_size(handle->file, file_pos, block_size);
count = 0;
errno = 0;
do {
bw_limit(handle->bw, block_size - count);
bw_limit(handle->bw, block_size);
count = 0;
do {
read_ret = pread(handle->f, block_buffer + count, block_size - count, offset + count);
if (read_ret == -1) {
if (errno == EINTR)
continue;
/* LCOV_EXCL_START */
log_error(errno, "Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", handle->path, offset + count, block_size - count, strerror(errno));
return -1;
@ -287,8 +289,7 @@ ssize_t handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsign
}
if (read_ret == 0) {
/* LCOV_EXCL_START */
if (errno == 0)
errno = ENXIO;
errno = ENXIO;
log_error(errno, "Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno));
return -1;
/* LCOV_EXCL_STOP */
@ -333,12 +334,15 @@ int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned
write_size = file_block_size(handle->file, file_pos, block_size);
bw_limit(handle->bw, write_size);
count = 0;
do {
bw_limit(handle->bw, write_size - count);
write_ret = pwrite(handle->f, block_buffer + count, write_size - count, offset + count);
if (write_ret == -1) {
if (errno == EINTR)
continue;
/* LCOV_EXCL_START */
log_fatal(errno, "Error writing file '%s'. %s.\n", handle->path, strerror(errno));
return -1;

View file

@ -839,12 +839,15 @@ int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigne
if (split->valid_size < offset + block_size)
split->valid_size = offset + block_size;
bw_limit(handle->bw, block_size);
count = 0;
do {
bw_limit(handle->bw, block_size - count);
write_ret = pwrite(split->f, block_buffer + count, block_size - count, offset + count);
if (write_ret == -1) {
if (errno == EINTR)
continue;
/* LCOV_EXCL_START */
if (errno == ENOSPC) {
log_fatal(errno, "Failed to grow parity file '%s' using write due lack of space.\n", split->path);
@ -904,13 +907,15 @@ int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned
/* LCOV_EXCL_STOP */
}
count = 0;
errno = 0;
do {
bw_limit(handle->bw, block_size - count);
bw_limit(handle->bw, block_size);
count = 0;
do {
read_ret = pread(split->f, block_buffer + count, block_size - count, offset + count);
if (read_ret == -1) {
if (errno == EINTR)
continue;
/* LCOV_EXCL_START */
log_error(errno, "Error reading parity file '%s' at offset %" PRIu64 " for size %u. %s.\n", split->path, offset + count, block_size - count, strerror(errno));
return -1;
@ -918,8 +923,7 @@ int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned
}
if (read_ret == 0) {
/* LCOV_EXCL_START */
if (errno == 0)
errno = ENXIO;
errno = ENXIO;
log_error(errno, "Unexpected end of parity file '%s' at offset %" PRIu64 ". %s.\n", split->path, offset, strerror(errno));
return -1;
/* LCOV_EXCL_STOP */

View file

@ -309,6 +309,7 @@ int sflush(STREAM* s)
{
ssize_t ret;
ssize_t size;
ssize_t count;
unsigned i;
if (s->state != STREAM_STATE_WRITE) {
@ -322,15 +323,32 @@ int sflush(STREAM* s)
return 0;
for (i = 0; i < s->handle_size; ++i) {
ret = write(s->handle[i].f, s->buffer, size);
count = 0;
do {
ret = write(s->handle[i].f, s->buffer + count, size - count);
if (ret != size) {
/* LCOV_EXCL_START */
s->state = STREAM_STATE_ERROR;
s->state_index = i;
return EOF;
/* LCOV_EXCL_STOP */
}
if (ret < 0) {
if (errno == EINTR)
continue;
/* LCOV_EXCL_START */
s->state = STREAM_STATE_ERROR;
s->state_index = i;
return EOF;
/* LCOV_EXCL_STOP */
}
if (ret == 0) {
/* LCOV_EXCL_START */
errno = EIO;
s->state = STREAM_STATE_ERROR;
s->state_index = i;
return EOF;
/* LCOV_EXCL_STOP */
}
count += ret;
} while (count < size);
}
/*