mirror of
https://git.zx2c4.com/cgit
synced 2024-11-22 00:18:41 +00:00
cache: tolerate short writes in print_slot
sendfile() can return after a short read/write, so we may need to call it more than once. As suggested in the manual page, we fall back to read/write if sendfile fails with EINVAL or ENOSYS. On the read/write path, use write_in_full which deals with short writes. Signed-off-by: Hristo Venev <hristo@venev.name> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
4c520cefc9
commit
852cb3b0e2
39
cache.c
39
cache.c
@ -85,40 +85,45 @@ static int close_slot(struct cache_slot *slot)
|
|||||||
/* Print the content of the active cache slot (but skip the key). */
|
/* Print the content of the active cache slot (but skip the key). */
|
||||||
static int print_slot(struct cache_slot *slot)
|
static int print_slot(struct cache_slot *slot)
|
||||||
{
|
{
|
||||||
|
off_t off;
|
||||||
#ifdef HAVE_LINUX_SENDFILE
|
#ifdef HAVE_LINUX_SENDFILE
|
||||||
off_t start_off;
|
off_t size;
|
||||||
int ret;
|
#endif
|
||||||
|
|
||||||
start_off = slot->keylen + 1;
|
off = slot->keylen + 1;
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_SENDFILE
|
||||||
|
size = slot->cache_st.st_size;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = sendfile(STDOUT_FILENO, slot->cache_fd, &start_off,
|
ssize_t ret;
|
||||||
slot->cache_st.st_size - start_off);
|
ret = sendfile(STDOUT_FILENO, slot->cache_fd, &off, size - off);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
if (errno == EAGAIN || errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
|
/* Fall back to read/write on EINVAL or ENOSYS */
|
||||||
|
if (errno == EINVAL || errno == ENOSYS)
|
||||||
|
break;
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
if (off == size)
|
||||||
return 0;
|
return 0;
|
||||||
} while (1);
|
} while (1);
|
||||||
#else
|
#endif
|
||||||
ssize_t i, j;
|
|
||||||
|
|
||||||
i = lseek(slot->cache_fd, slot->keylen + 1, SEEK_SET);
|
if (lseek(slot->cache_fd, off, SEEK_SET) != off)
|
||||||
if (i != slot->keylen + 1)
|
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
i = j = xread(slot->cache_fd, slot->buf, sizeof(slot->buf));
|
ssize_t ret;
|
||||||
if (i > 0)
|
ret = xread(slot->cache_fd, slot->buf, sizeof(slot->buf));
|
||||||
j = xwrite(STDOUT_FILENO, slot->buf, i);
|
if (ret < 0)
|
||||||
} while (i > 0 && j == i);
|
|
||||||
|
|
||||||
if (i < 0 || j != i)
|
|
||||||
return errno;
|
return errno;
|
||||||
else
|
if (ret == 0)
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
if (write_in_full(STDOUT_FILENO, slot->buf, ret) < 0)
|
||||||
|
return errno;
|
||||||
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the slot has expired */
|
/* Check if the slot has expired */
|
||||||
|
Loading…
Reference in New Issue
Block a user