summaryrefslogtreecommitdiffstats
path: root/src/server/sendfile.c
diff options
context:
space:
mode:
authorSimon Rettberg2025-10-10 18:13:16 +0200
committerSimon Rettberg2025-12-09 15:33:20 +0100
commit531ba156de326210e4807b701183eaf2f506cf2a (patch)
tree0e732acacce0bde31e95bdf4e2bb272d39ecdd25 /src/server/sendfile.c
parent[SERVER] iscsi: Implement relaying requests to uplink servers (diff)
downloaddnbd3-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.c60
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