From: Ilya Dryomov Date: Fri, 21 Feb 2014 14:34:13 +0000 (+0200) Subject: FileStore: introduce XfsFileStoreBackend class X-Git-Tag: v0.78~101^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=1f5b796f586fdaf765a82bc22518e862633e658f;p=ceph.git FileStore: introduce XfsFileStoreBackend class 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 --- diff --git a/README b/README index 825e932c0fa6..cde4bbcf895f 100644 --- 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 diff --git a/ceph.spec.in b/ceph.spec.in index 44576923d46a..2f2216f3571f 100644 --- a/ceph.spec.in +++ b/ceph.spec.in @@ -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 diff --git a/configure.ac b/configure.ac index ec1e99d3dab4..e228dab48d0b 100644 --- a/configure.ac +++ b/configure.ac @@ -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 + #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]) diff --git a/debian/control b/debian/control index 4afe66d91698..1572eb0de5bd 100644 --- a/debian/control +++ b/debian/control @@ -39,6 +39,7 @@ Build-Depends: autoconf, python-nose, uuid-dev, uuid-runtime, + xfslibs-dev, yasm Standards-Version: 3.9.3 diff --git a/src/os/FileStore.cc b/src/os/FileStore.cc index 131d894b23e3..3a42e45acb0a 100644 --- a/src/os/FileStore.cc +++ b/src/os/FileStore.cc @@ -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) diff --git a/src/os/Makefile.am b/src/os/Makefile.am index 2bba7aad6a3c..f85f44a81841 100644 --- a/src/os/Makefile.am +++ b/src/os/Makefile.am @@ -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 index 000000000000..7b632d8a622e --- /dev/null +++ b/src/os/XfsFileStoreBackend.cc @@ -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 +#include +#include +#include +#include + +#include + +#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 index 000000000000..cb19bf7bf3c2 --- /dev/null +++ b/src/os/XfsFileStoreBackend.h @@ -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 */