]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
common: posix_fallocate on ZFS returns EINVAL 21514/head
authorWillem Jan Withagen <wjw@digiware.nl>
Sun, 11 Feb 2018 21:06:46 +0000 (22:06 +0100)
committerNathan Cutler <ncutler@suse.com>
Thu, 19 Apr 2018 09:08:04 +0000 (11:08 +0200)
But even still it would not work on any COW FS.
So reorganised the code to have a common routine
that in the end will allocate a file on disk if needed

FileStore would not build when there was no HAVE_POSIX_FALLOCATE
other than on Apple. With ceph_posix_fallocate FileStore will also
fallback to manually allocating the required file.

Signed-off-by: Willem Jan Withagen <wjw@digiware.nl>
(cherry picked from commit 1230e696c4424b1744db9972133a369a3fe2a996)

src/CMakeLists.txt
src/common/compat.cc [new file with mode: 0644]
src/include/compat.h
src/os/bluestore/BlueStore.cc
src/os/filestore/FileJournal.cc

index 7aa8a4392e1e2a7d1258fc1278adbcc2ee66208f..d647783423e175e9d098e72d4f9fd2e29ae836de 100644 (file)
@@ -531,6 +531,7 @@ set(libcommon_files
   common/bit_str.cc
   osdc/Striper.cc
   osdc/Objecter.cc
+  common/compat.cc
   common/Graylog.cc
   common/fs_types.cc
   common/dns_resolve.cc
diff --git a/src/common/compat.cc b/src/common/compat.cc
new file mode 100644 (file)
index 0000000..18b7587
--- /dev/null
@@ -0,0 +1,78 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#if defined(__linux__) 
+#include <sys/vfs.h>
+#endif
+
+#include "include/compat.h" 
+#include "common/safe_io.h"
+
+// The type-value for a ZFS FS in fstatfs.
+#define FS_ZFS_TYPE 0xde
+
+// On FreeBSD, ZFS fallocate always fails since it is considered impossible to
+// reserve space on a COW filesystem. posix_fallocate() returns EINVAL
+// Linux in this case already emulates the reservation in glibc
+// In which case it is allocated manually, and still that is not a real guarantee
+// that a full buffer is allocated on disk, since it could be compressed.
+// To prevent this the written buffer needs to be loaded with random data.
+int manual_fallocate(int fd, off_t offset, off_t len) {
+  int r = lseek(fd, offset, SEEK_SET);
+  if (r == -1)
+    return errno;
+  char data[1024*128];
+  // TODO: compressing filesystems would require random data
+  memset(data, 0x42, sizeof(data));
+  for (off_t off = 0; off < len; off += sizeof(data)) {
+    if (off + sizeof(data) > len)
+      r = safe_write(fd, data, len - off);
+    else
+      r = safe_write(fd, data, sizeof(data));
+    if (r == -1) {
+      return errno;
+    }
+  }
+  return 0;
+}
+
+int on_zfs(int basedir_fd) {
+  struct statfs basefs;
+  (void)fstatfs(basedir_fd, &basefs);
+  return (basefs.f_type == FS_ZFS_TYPE);
+}
+
+int ceph_posix_fallocate(int fd, off_t offset, off_t len) {
+  // Return 0 if oke, otherwise errno > 0
+
+#ifdef HAVE_POSIX_FALLOCATE
+  if (on_zfs(fd)) {
+    return manual_fallocate(fd, offset, len);
+  } else {
+    return posix_fallocate(fd, offset, len);
+  }
+#elif defined(__APPLE__)
+  fstore_t store;
+  store.fst_flags = F_ALLOCATECONTIG;
+  store.fst_posmode = F_PEOFPOSMODE;
+  store.fst_offset = offset;
+  store.fst_length = len;
+
+  int ret = fcntl(fd, F_PREALLOCATE, &store);
+  if (ret == -1) {
+    ret = errno;
+  }
+  return ret;
+#else
+  return manual_fallocate(fd, offset, len);
+#endif
+} 
+
index d4120478c88ead29a932704e25c5bd8a33849a13..eb384c2e137985a8078b82bbcc0a1a961c849006 100644 (file)
@@ -13,6 +13,7 @@
 #define CEPH_COMPAT_H
 
 #include "acconfig.h"
+#include <sys/types.h>
 
 #if defined(__linux__)
 #define PROCPREFIX
     0; })
 #endif
 
+int ceph_posix_fallocate(int fd, off_t offset, off_t len);
+
 #endif /* !CEPH_COMPAT_H */
index efbfd7f33a817ea961e4ff57223bb071500768ce..0932459ca3dcde4cb05d2a2730395ae43dea1d77 100644 (file)
@@ -5116,30 +5116,13 @@ int BlueStore::_setup_block_symlink_or_file(
        }
 
        if (cct->_conf->bluestore_block_preallocate_file) {
-#ifdef HAVE_POSIX_FALLOCATE
-         r = ::posix_fallocate(fd, 0, size);
-         if (r) {
+          r = ::ceph_posix_fallocate(fd, 0, size);
+          if (r > 0) {
            derr << __func__ << " failed to prefallocate " << name << " file to "
              << size << ": " << cpp_strerror(r) << dendl;
            VOID_TEMP_FAILURE_RETRY(::close(fd));
            return -r;
          }
-#else
-         char data[1024*128];
-         for (uint64_t off = 0; off < size; off += sizeof(data)) {
-           if (off + sizeof(data) > size)
-             r = ::write(fd, data, size - off);
-           else
-             r = ::write(fd, data, sizeof(data));
-           if (r < 0) {
-             r = -errno;
-             derr << __func__ << " failed to prefallocate w/ write " << name << " file to "
-               << size << ": " << cpp_strerror(r) << dendl;
-             VOID_TEMP_FAILURE_RETRY(::close(fd));
-             return r;
-           }
-         }
-#endif
        }
        dout(1) << __func__ << " resized " << name << " file to "
                << pretty_si_t(size) << "B" << dendl;
index 6037ee4860279342ba0ec3bd2aae3a1634394cbc..6482317fce3d9d913797f10b8fba22a100321b0c 100644 (file)
@@ -198,32 +198,13 @@ int FileJournal::_open_file(int64_t oldsize, blksize_t blksize,
           << newsize << " bytes: " << cpp_strerror(err) << dendl;
       return -err;
     }
-#ifdef HAVE_POSIX_FALLOCATE
-    ret = ::posix_fallocate(fd, 0, newsize);
+    ret = ceph_posix_fallocate(fd, 0, newsize);
     if (ret) {
       derr << "FileJournal::_open_file : unable to preallocation journal to "
           << newsize << " bytes: " << cpp_strerror(ret) << dendl;
       return -ret;
     }
     max_size = newsize;
-#elif defined(__APPLE__)
-    fstore_t store;
-    store.fst_flags = F_ALLOCATECONTIG;
-    store.fst_posmode = F_PEOFPOSMODE;
-    store.fst_offset = 0;
-    store.fst_length = newsize;
-
-    ret = ::fcntl(fd, F_PREALLOCATE, &store);
-    if (ret == -1) {
-      ret = -errno;
-      derr << "FileJournal::_open_file : unable to preallocation journal to "
-          << newsize << " bytes: " << cpp_strerror(ret) << dendl;
-      return ret;
-    }
-    max_size = newsize;
-#else
-# error "Journal pre-allocation not supported on platform."
-#endif
   }
   else {
     max_size = oldsize;