summaryrefslogtreecommitdiffstats
path: root/src/server/net.c
diff options
context:
space:
mode:
authorSimon Rettberg2025-10-16 14:50:30 +0200
committerSimon Rettberg2025-12-09 15:33:20 +0100
commit619502eea60436f50b63300ab3d4e73077f5194c (patch)
tree47e52ee43d51a2760bd07422d0cdb334a1107930 /src/server/net.c
parent[SERVER] iscsi refactor: First working version (diff)
downloaddnbd3-619502eea60436f50b63300ab3d4e73077f5194c.tar.gz
dnbd3-619502eea60436f50b63300ab3d4e73077f5194c.tar.xz
dnbd3-619502eea60436f50b63300ab3d4e73077f5194c.zip
[SERVER] iscsi: use sendfile()
Diffstat (limited to 'src/server/net.c')
-rw-r--r--src/server/net.c109
1 files changed, 22 insertions, 87 deletions
diff --git a/src/server/net.c b/src/server/net.c
index 48890df..e94e549 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -26,6 +26,7 @@
#include "rpc.h"
#include "altservers.h"
#include "reference.h"
+#include "sendfile.h"
#include <dnbd3/shared/sockhelper.h>
#include <dnbd3/shared/timing.h>
@@ -35,14 +36,6 @@
#include <assert.h>
#include <netinet/tcp.h>
-#ifdef __linux__
-#include <sys/sendfile.h>
-#endif
-#ifdef __FreeBSD__
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#endif
#include <jansson.h>
#include <inttypes.h>
#include <stdatomic.h>
@@ -52,8 +45,6 @@ static dnbd3_client_t *_clients[SERVER_MAX_CLIENTS];
static int _num_clients = 0;
static pthread_mutex_t _clients_lock;
-static char nullbytes[500];
-
static atomic_uint_fast64_t totalBytesSent = 0;
// Adding and removing clients -- list management
@@ -133,21 +124,6 @@ static inline bool send_reply(int sock, dnbd3_reply_t *reply, const void *payloa
return true;
}
-/**
- * Send given amount of null bytes. The caller has to acquire the sendMutex first.
- */
-static inline bool sendPadding( const int fd, uint32_t bytes )
-{
- ssize_t ret;
- while ( bytes >= sizeof(nullbytes) ) {
- ret = sock_sendAll( fd, nullbytes, sizeof(nullbytes), 2 );
- if ( ret <= 0 )
- return false;
- bytes -= (uint32_t)ret;
- }
- return sock_sendAll( fd, nullbytes, bytes, 2 ) == (ssize_t)bytes;
-}
-
void net_init()
{
mutex_init( &_clients_lock, LOCK_CLIENT_LIST );
@@ -408,74 +384,33 @@ void* net_handleNewConnection(void *clientPtr)
if ( lock ) mutex_lock( &client->sendMutex );
// Send reply header
if ( send( client->sock, &reply, sizeof(dnbd3_reply_t), (request.size == 0 ? 0 : MSG_MORE) ) != sizeof(dnbd3_reply_t) ) {
+ logadd( LOG_DEBUG1, "Sending CMD_GET_BLOCK reply header to %s failed (errno=%d)", client->hostName, errno );
if ( lock ) mutex_unlock( &client->sendMutex );
- logadd( LOG_DEBUG1, "Sending CMD_GET_BLOCK reply header to %s failed", client->hostName );
goto exit_client_cleanup;
}
- if ( request.size != 0 ) {
- // Send payload if request length > 0
- size_t done = 0;
- off_t foffset = (off_t)offset;
- size_t realBytes;
- if ( offset + request.size <= image->realFilesize ) {
- realBytes = request.size;
- } else {
- realBytes = (size_t)(image->realFilesize - offset);
+ const size_t realBytes = offset + request.size <= image->realFilesize
+ ? request.size : (image->realFilesize - offset);
+ bool ret = sendfile_all( image_file, client->sock, offset, realBytes );
+ if ( !ret ) {
+ const int err = errno;
+
+ if ( lock ) mutex_unlock( &client->sendMutex );
+ if ( err != EPIPE && err != ECONNRESET && err != ESHUTDOWN
+ && err != EAGAIN && err != EWOULDBLOCK ) {
+ logadd( LOG_DEBUG1, "sendfile to %s failed (%d bytes, errno=%d)",
+ client->hostName, (int)realBytes, err );
}
- while ( done < realBytes ) {
- // TODO: Should we consider EOPNOTSUPP on BSD for sendfile and fallback to read/write?
- // Linux would set EINVAL or ENOSYS instead, which it unfortunately also does for a couple of other failures :/
- // read/write would kill performance anyways so a fallback would probably be of little use either way.
-#ifdef DNBD3_SERVER_AFL
- char buf[1000];
- size_t cnt = realBytes - done;
- if ( cnt > 1000 ) {
- cnt = 1000;
- }
- const ssize_t sent = pread( image_file, buf, cnt, foffset );
- if ( sent > 0 ) {
- //write( client->sock, buf, sent ); // This is not verified in any way, so why even do it...
- } else {
- const int err = errno;
-#elif defined(__linux__)
- const ssize_t sent = sendfile( client->sock, image_file, &foffset, realBytes - done );
- if ( sent <= 0 ) {
- const int err = errno;
-#elif defined(__FreeBSD__)
- off_t sent;
- const int ret = sendfile( image_file, client->sock, foffset, realBytes - done, NULL, &sent, 0 );
- if ( ret == -1 || sent == 0 ) {
- const int err = errno;
- if ( ret == -1 ) {
- if ( err == EAGAIN || err == EINTR ) { // EBUSY? manpage doesn't explicitly mention *sent here.. But then again we dont set the according flag anyways
- done += sent;
- continue;
- }
- sent = -1;
- }
-#endif
- if ( lock ) mutex_unlock( &client->sendMutex );
- if ( sent == -1 ) {
- if ( err != EPIPE && err != ECONNRESET && err != ESHUTDOWN
- && err != EAGAIN && err != EWOULDBLOCK ) {
- logadd( LOG_DEBUG1, "sendfile to %s failed (image to net. sent %d/%d, errno=%d)",
- client->hostName, (int)done, (int)realBytes, err );
- }
- if ( err == EBADF || err == EFAULT || err == EINVAL || err == EIO ) {
- logadd( LOG_INFO, "Disabling %s:%d", image->name, image->rid );
- image->problem.read = true;
- }
- }
- goto exit_client_cleanup;
- }
- done += sent;
+ if ( err == EBADF || err == EFAULT || err == EINVAL || err == EIO ) {
+ logadd( LOG_INFO, "Disabling %s:%d", image->name, image->rid );
+ image->problem.read = true;
}
- if ( request.size > (uint32_t)realBytes ) {
- if ( !sendPadding( client->sock, request.size - (uint32_t)realBytes ) ) {
- if ( lock ) mutex_unlock( &client->sendMutex );
- goto exit_client_cleanup;
- }
+ goto exit_client_cleanup;
+ }
+ if ( request.size > (uint32_t)realBytes ) {
+ if ( !sock_sendPadding( client->sock, request.size - (uint32_t)realBytes ) ) {
+ if ( lock ) mutex_unlock( &client->sendMutex );
+ goto exit_client_cleanup;
}
}
if ( lock ) mutex_unlock( &client->sendMutex );