diff options
| author | Simon Rettberg | 2025-10-10 18:13:16 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2025-12-09 15:33:20 +0100 |
| commit | 531ba156de326210e4807b701183eaf2f506cf2a (patch) | |
| tree | 0e732acacce0bde31e95bdf4e2bb272d39ecdd25 /src/server/sendfile.c | |
| parent | [SERVER] iscsi: Implement relaying requests to uplink servers (diff) | |
| download | dnbd3-531ba156de326210e4807b701183eaf2f506cf2a.tar.gz dnbd3-531ba156de326210e4807b701183eaf2f506cf2a.tar.xz dnbd3-531ba156de326210e4807b701183eaf2f506cf2a.zip | |
[SERVER] iscsi refactor: First working version
Work towards simplifying the iscsi implementation has begun. Goals are:
- Simpler and easier to understand resource/lifecycle management of
allocations
- Single-threaded architecture, making locking unnecessary
- Moving as many allocations as possible to the stack
- Making the call-stack more shallow for easier tracking of code flow
Diffstat (limited to 'src/server/sendfile.c')
| -rw-r--r-- | src/server/sendfile.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/server/sendfile.c b/src/server/sendfile.c new file mode 100644 index 0000000..9e27238 --- /dev/null +++ b/src/server/sendfile.c @@ -0,0 +1,60 @@ +#include "sendfile.h" + +#if defined(__linux__) +#include <sys/sendfile.h> +#elif defined(__FreeBSD__) +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/uio.h> +#else +#error "What platform is this?" +#endif + +#include <errno.h> + +bool sendfile_all(const int fd, const int sock, off_t foffset, const size_t bytes) +{ + if ( bytes == 0 ) + return true; +#ifdef DNBD3_SERVER_AFL + errno = 0; + return true; +#elif defined(__linux__) + size_t done = 0; + int againCount = 0; + + while ( done < bytes ) { + const ssize_t sent = sendfile( sock, fd, &foffset, bytes - done ); + if ( sent == 0 ) // Probably EOF, like with send(), but manpage is not clear :-/ + return false; + if ( sent < 0 ) { + if ( errno == EAGAIN || errno == EINTR ) { + // Retry once, but give up otherwise - EAGAIN might just be the send timeout + if ( ++againCount > 1 ) + return false; + continue; + } + return false; + } + done += sent; + } +#elif defined(__FreeBSD__) + off_t sent; + size_t done = 0; + int againCount = 0; + + while ( done < bytes ) { + const int ret = sendfile( fd, sock, foffset + done, bytes - done, NULL, &sent, 0 ); + if ( ret == 0 || errno == EAGAIN || errno == EINTR ) { + // Retry once, but give up otherwise - EAGAIN might just be the send timeout + if ( sent == 0 && ++againCount > 1 ) + return false; + done += sent; + continue; + } + // Something else went wrong + return false; + } +#endif + return true; +}
\ No newline at end of file |
