From 531ba156de326210e4807b701183eaf2f506cf2a Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 10 Oct 2025 18:13:16 +0200 Subject: [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 --- src/server/sendfile.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/server/sendfile.c (limited to 'src/server/sendfile.c') 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 +#elif defined(__FreeBSD__) +#include +#include +#include +#else +#error "What platform is this?" +#endif + +#include + +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 -- cgit v1.2.3-55-g7522