Implement trim with the BLKDISCARD ioctl
authorWouter Verhelst <w@uter.be>
Thu, 11 Apr 2019 13:51:46 +0000 (15:51 +0200)
committerWouter Verhelst <w@uter.be>
Thu, 11 Apr 2019 13:56:42 +0000 (15:56 +0200)
Fixes gh-64

configure.ac
nbd-server.c
nbdsrv.c

index 1257b2a..5848c3e 100644 (file)
@@ -142,6 +142,8 @@ else
        AC_MSG_RESULT([no])
 fi
 
+AC_CHECK_DECL([BLKDISCARD], AC_DEFINE(HAVE_BLKDISCARD, 1, [Define to 1 if you have the BLKDISCARD ioctl]), AC_DEFINE(HAVE_BLKDISCARD, 0), [#include <linux/fs.h>])
+
 AC_CHECK_FUNC(splice, [HAVE_SPLICE=yes], [HAVE_SPLICE=no])
 if test "$HAVE_SPLICE" = "yes"
 then
index e401739..7f82370 100644 (file)
@@ -95,6 +95,9 @@
 #if HAVE_FALLOC_PH
 #include <linux/falloc.h>
 #endif
+#if HAVE_BLKDISCARD
+#include <linux/fs.h>
+#endif
 #include <arpa/inet.h>
 #include <strings.h>
 #include <dirent.h>
@@ -1555,19 +1558,37 @@ int expflush(CLIENT *client) {
 }
 
 void punch_hole(int fd, off_t off, off_t len) {
-       DEBUG("punching hole in fd=%d, starting from %llu, length %llu\n", fd, (unsigned long long)off, (unsigned long long)len);
+       DEBUG("Request to punch a hole in fd=%d, starting from %llu, length %llu\n", fd, (unsigned long long)off, (unsigned long long)len);
+       errno = 0;
+// fallocate -- files, Linux
 #if HAVE_FALLOC_PH
-       fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, off, len);
-#elif HAVE_FSCTL_SET_ZERO_DATA
+       do {
+               if(fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, off, len) == 0)
+                       return;
+       } while(errno == EINTR);
+#endif
+// ioctl(BLKDISCARD) -- block devices, Linux
+#if HAVE_BLKDISCARD
+       uint64_t range[2] = {off, len};
+       do {
+               if(ioctl(fd, BLKDISCARD, range) == 0)
+                       return;
+       } while(errno == EINTR);
+#endif
+// Windows
+#if HAVE_FSCTL_SET_ZERO_DATA
        FILE_ZERO_DATA_INFORMATION zerodata;
        zerodata.FileOffset.QuadPart = off;
        zerodata.BeyondFinalZero.QuadPart = off + len;
        HANDLE w32handle = (HANDLE)_get_osfhandle(fd);
        DWORD bytesret;
        DeviceIoControl(w32handle, FSCTL_SET_ZERO_DATA, &zerodata, sizeof(zerodata), NULL, 0, &bytesret, NULL);
-#else
-       DEBUG("punching holes not supported on this platform\n");
 #endif
+       if(errno) {
+               DEBUG("punching holes failed: %s", strerror(errno));
+       } else {
+               DEBUG("punching holes not supported on this platform\n");
+       }
 }
 
 static void send_reply(CLIENT* client, uint32_t opt, uint32_t reply_type, ssize_t datasize, void* data) {
index 1ac4d35..05caf14 100644 (file)
--- a/nbdsrv.c
+++ b/nbdsrv.c
@@ -17,6 +17,9 @@
 #include <sys/socket.h>
 #include <treefiles.h>
 #include "backend.h"
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
 #ifdef HAVE_SYS_MOUNT_H
 #include <sys/mount.h>
 #endif