]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
FileStore: introduce XfsFileStoreBackend class
authorIlya Dryomov <ilya.dryomov@inktank.com>
Fri, 21 Feb 2014 14:34:13 +0000 (16:34 +0200)
committerIlya Dryomov <ilya.dryomov@inktank.com>
Mon, 3 Mar 2014 18:33:44 +0000 (20:33 +0200)
Introduce XfsFileStoreBackend class, currently the only filestore
backend implementing SETALLOCHINT op.  This commit adds a build-time
dependency on libxfs as xfs-specific ioctl (XFS_IOC_FSSETXATTR /
XFS_XFLAG_EXTSIZE) is used to implement the new set_alloc_hint()
method.

Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
README
ceph.spec.in
configure.ac
debian/control
src/os/FileStore.cc
src/os/Makefile.am
src/os/XfsFileStoreBackend.cc [new file with mode: 0644]
src/os/XfsFileStoreBackend.h [new file with mode: 0644]

diff --git a/README b/README
index 825e932c0fa6de65d4aa37db98b31f994ef7eb2e..cde4bbcf895f4f33091530d9d7d20925b99448c0 100644 (file)
--- a/README
+++ b/README
@@ -115,6 +115,7 @@ To build the source code, you must install the following:
 - libtool
 - libfcgi
 - libfcgi-dev
+- xfslibs-dev
 - libfuse-dev
 - linux-kernel-headers
 - libcrypto++-dev
@@ -135,7 +136,7 @@ To build the source code, you must install the following:
 
 For example:
 
-       $ apt-get install automake autoconf pkg-config gcc g++ make libboost-dev libedit-dev libssl-dev libtool libfcgi libfcgi-dev libfuse-dev linux-kernel-headers libcrypto++-dev libaio-dev libgoogle-perftools-dev libkeyutils-dev uuid-dev libblkid-dev libatomic-ops-dev libboost-program-options-dev libboost-thread-dev libexpat1-dev libleveldb-dev libsnappy-dev libcurl4-gnutls-dev python-argparse python-flask
+       $ apt-get install automake autoconf pkg-config gcc g++ make libboost-dev libedit-dev libssl-dev libtool libfcgi libfcgi-dev xfslibs-dev libfuse-dev linux-kernel-headers libcrypto++-dev libaio-dev libgoogle-perftools-dev libkeyutils-dev uuid-dev libblkid-dev libatomic-ops-dev libboost-program-options-dev libboost-thread-dev libexpat1-dev libleveldb-dev libsnappy-dev libcurl4-gnutls-dev python-argparse python-flask
 
 rpm-based
 ---------
@@ -157,6 +158,7 @@ These are the rpm packages needed to install in an rpm-based OS:
     fcgi-devel
     expat-devel
     libcurl-devel
+    xfsprogs-devel
     fuse-devel
     gperftools-devel
     libedit-devel
@@ -168,5 +170,5 @@ These are the rpm packages needed to install in an rpm-based OS:
 
 For example:
 
-       $ yum install autoconf automake gcc gcc-c++ make libtool python-argparse python-flask libuuid-devel libblkid-devel keyutils-libs-devel cryptopp-devel nss-devel fcgi-devel expat-devel libcurl-devel fuse-devel gperftools-devel libedit-devel libatomic_ops-devel snappy-devel leveldb-devel libaio-devel boost-devel
+       $ yum install autoconf automake gcc gcc-c++ make libtool python-argparse python-flask libuuid-devel libblkid-devel keyutils-libs-devel cryptopp-devel nss-devel fcgi-devel expat-devel libcurl-devel xfsprogs-devel fuse-devel gperftools-devel libedit-devel libatomic_ops-devel snappy-devel leveldb-devel libaio-devel boost-devel
 
index 44576923d46aaad238aa8b07c18ca70dbdc47721..2f2216f3571f0a44ac749e88dd5ae27700af2a68 100644 (file)
@@ -47,6 +47,7 @@ BuildRequires:  libxml2-devel
 BuildRequires:  libuuid-devel
 BuildRequires:  libblkid-devel >= 2.17
 BuildRequires:  leveldb-devel > 1.2
+BuildRequires:  xfsprogs-devel
 BuildRequires:  yasm
 %if 0%{?rhel_version} || 0%{?centos_version} || 0%{?fedora}
 BuildRequires:  snappy-devel
index ec1e99d3dab468141a2fd9d38650e2722744c4aa..e228dab48d0bc01341b3c21d08bf3770f20a5eba 100644 (file)
@@ -656,6 +656,21 @@ AC_EGREP_CPP([yes_have_f_setpipe_sz], [
   AC_MSG_NOTICE([F_SETPIPE_SZ not found, zero-copy may be less efficent])
 ])
 
+# XFS_XFLAG_EXTSIZE in xfs/xfs.h on Linux
+AS_IF([test "x$linux" = "xyes"], [
+  AC_CHECK_HEADER([xfs/xfs.h], [], AC_MSG_ERROR([xfs/xfs.h not found]))
+  AC_MSG_CHECKING([for XFS_XFLAG_EXTSIZE in xfs/xfs.h])
+  AC_EGREP_CPP([yes_have_xfs_xflag_extsize], [
+     #include <xfs/xfs.h>
+     #ifdef XFS_XFLAG_EXTSIZE
+     yes_have_xfs_xflag_extsize
+     #endif
+  ], AC_MSG_RESULT([yes]), [
+     AC_MSG_RESULT([no])
+     AC_MSG_ERROR([XFS_XFLAG_EXTSIZE not found])
+  ])
+])
+
 AC_CHECK_FUNCS([posix_fallocate])
 AC_CHECK_HEADERS([sys/prctl.h])
 AC_CHECK_FUNCS([prctl])
index 4afe66d91698bb49b1bec7d45549870e05b659b6..1572eb0de5bdafa09b62e17b239c74bb2cf35774 100644 (file)
@@ -39,6 +39,7 @@ Build-Depends: autoconf,
                python-nose,
                uuid-dev,
                uuid-runtime,
+               xfslibs-dev,
                yasm
 Standards-Version: 3.9.3
 
index 131d894b23e37381d0d9a3806cfc3c9dfd9f8e6b..3a42e45acb0a203c67bf7396c0d039e1c14a6d2a 100644 (file)
@@ -48,6 +48,7 @@
 #include "FileStore.h"
 #include "GenericFileStoreBackend.h"
 #include "BtrfsFileStoreBackend.h"
+#include "XfsFileStoreBackend.h"
 #include "ZFSFileStoreBackend.h"
 #include "common/BackTrace.h"
 #include "include/types.h"
@@ -678,6 +679,10 @@ int FileStore::mkfs()
   if (basefs.f_type == BTRFS_SUPER_MAGIC) {
 #if defined(__linux__)
     backend = new BtrfsFileStoreBackend(this);
+#endif
+  } else if (basefs.f_type == XFS_SUPER_MAGIC) {
+#if defined(__linux__)
+    backend = new XfsFileStoreBackend(this);
 #endif
   } else if (basefs.f_type == ZFS_SUPER_MAGIC) {
 #ifdef HAVE_LIBZFS
@@ -876,7 +881,8 @@ int FileStore::_detect_fs()
 #endif
   } else if (st.f_type == XFS_SUPER_MAGIC) {
 #if defined(__linux__)
-    dout(0) << "mount detected xfs" << dendl;
+    dout(0) << "mount detected xfs (libxfs)" << dendl;
+    backend = new XfsFileStoreBackend(this);
     m_fs_type = FS_TYPE_XFS;
 
     // wbthrottle is constructed with fs(WBThrottle::XFS)
index 2bba7aad6a3c25f6d898527cb1080af11c95dc04..f85f44a818410bec7fb0d83c283c32e2b9aef978 100644 (file)
@@ -19,6 +19,7 @@ libos_la_SOURCES = \
 
 if LINUX
 libos_la_SOURCES += os/BtrfsFileStoreBackend.cc
+libos_la_SOURCES += os/XfsFileStoreBackend.cc
 endif
 
 if WITH_LIBZFS
@@ -52,6 +53,7 @@ noinst_HEADERS += \
        os/ObjectStore.h \
        os/SequencerPosition.h \
        os/WBThrottle.h \
+       os/XfsFileStoreBackend.h \
        os/ZFSFileStoreBackend.h
 
 if WITH_LIBZFS
diff --git a/src/os/XfsFileStoreBackend.cc b/src/os/XfsFileStoreBackend.cc
new file mode 100644 (file)
index 0000000..7b632d8
--- /dev/null
@@ -0,0 +1,124 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2014 Inktank, Inc
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#include "XfsFileStoreBackend.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <xfs/xfs.h>
+
+#include "common/errno.h"
+#include "include/assert.h"
+#include "include/compat.h"
+
+#define dout_subsys ceph_subsys_filestore
+#undef dout_prefix
+#define dout_prefix *_dout << "xfsfilestorebackend(" << get_basedir_path() << ") "
+
+XfsFileStoreBackend::XfsFileStoreBackend(FileStore *fs):
+  GenericFileStoreBackend(fs), m_has_extsize(false) { }
+
+/*
+ * Set extsize attr on a file to val.  Should be a free-standing
+ * function, but dout_prefix expanding to a call to get_basedir_path()
+ * protected member function won't let it.
+ */
+int XfsFileStoreBackend::set_extsize(int fd, unsigned int val)
+{
+  struct fsxattr fsx;
+  struct stat sb;
+  int ret;
+
+  if (fstat(fd, &sb) < 0) {
+    ret = -errno;
+    dout(0) << "set_extsize: fstat: " << cpp_strerror(ret) << dendl;
+    goto out;
+  }
+  if (!S_ISREG(sb.st_mode)) {
+    ret = -EINVAL;
+    dout(0) << "set_extsize: invalid target file type" << dendl;
+    goto out;
+  }
+
+  if (ioctl(fd, XFS_IOC_FSGETXATTR, &fsx) < 0) {
+    ret = -errno;
+    dout(0) << "set_extsize: FSGETXATTR: " << cpp_strerror(ret) << dendl;
+    goto out;
+  }
+
+  fsx.fsx_xflags |= XFS_XFLAG_EXTSIZE;
+  fsx.fsx_extsize = val;
+
+  if (ioctl(fd, XFS_IOC_FSSETXATTR, &fsx) < 0) {
+    ret = -errno;
+    dout(0) << "set_extsize: FSSETXATTR: " << cpp_strerror(ret) << dendl;
+    goto out;
+  }
+  ret = 0;
+
+out:
+  return ret;
+}
+
+int XfsFileStoreBackend::detect_features()
+{
+  int ret;
+
+  ret = GenericFileStoreBackend::detect_features();
+  if (ret < 0)
+    return ret;
+
+  // extsize?
+  int fd = ::openat(get_basedir_fd(), "extsize_test", O_CREAT|O_WRONLY, 0600);
+  if (fd < 0) {
+    ret = -errno;
+    dout(0) << "detect_feature: failed to create test file for extsize attr: "
+            << cpp_strerror(ret) << dendl;
+    goto out;
+  }
+  if (::unlinkat(get_basedir_fd(), "extsize_test", 0) < 0) {
+    ret = -errno;
+    dout(0) << "detect_feature: failed to unlink test file for extsize attr: "
+            << cpp_strerror(ret) << dendl;
+    goto out_close;
+  }
+
+  ret = set_extsize(fd, 1U << 15); // a few pages
+  if (ret) {
+    ret = 0;
+    dout(0) << "detect_feature: failed to set test file extsize, assuming extsize is NOT supported" << dendl;
+    goto out_close;
+  }
+
+  dout(0) << "detect_feature: extsize is supported" << dendl;
+  m_has_extsize = true;
+
+out_close:
+  TEMP_FAILURE_RETRY(::close(fd));
+out:
+  return ret;
+}
+
+int XfsFileStoreBackend::set_alloc_hint(int fd, uint64_t hint)
+{
+  if (!m_has_extsize)
+    return -EOPNOTSUPP;
+
+  assert(hint < UINT_MAX);
+  return set_extsize(fd, hint);
+}
diff --git a/src/os/XfsFileStoreBackend.h b/src/os/XfsFileStoreBackend.h
new file mode 100644 (file)
index 0000000..cb19bf7
--- /dev/null
@@ -0,0 +1,33 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2014 Inktank, Inc
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#ifndef CEPH_XFSFILESTOREBACKEND_H
+#define CEPH_XFSFILESTOREBACKEND_H
+
+#include "GenericFileStoreBackend.h"
+
+#include "include/int_types.h"
+
+class XfsFileStoreBackend : public GenericFileStoreBackend {
+private:
+  bool m_has_extsize;
+  int set_extsize(int fd, unsigned int val);
+public:
+  XfsFileStoreBackend(FileStore *fs);
+  ~XfsFileStoreBackend() {};
+  int detect_features();
+  int set_alloc_hint(int fd, uint64_t hint);
+};
+
+#endif /* CEPH_XFSFILESTOREBACKEND_H */