Skip to content

Commit

Permalink
FileStore: introduce XfsFileStoreBackend class
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
idryomov committed Mar 3, 2014
1 parent 391257c commit 1f5b796
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 3 deletions.
6 changes: 4 additions & 2 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
---------
Expand All @@ -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
Expand All @@ -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

1 change: 1 addition & 0 deletions ceph.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 15 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
1 change: 1 addition & 0 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Build-Depends: autoconf,
python-nose,
uuid-dev,
uuid-runtime,
xfslibs-dev,
yasm
Standards-Version: 3.9.3

Expand Down
8 changes: 7 additions & 1 deletion src/os/FileStore.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions src/os/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -52,6 +53,7 @@ noinst_HEADERS += \
os/ObjectStore.h \
os/SequencerPosition.h \
os/WBThrottle.h \
os/XfsFileStoreBackend.h \
os/ZFSFileStoreBackend.h

if WITH_LIBZFS
Expand Down
124 changes: 124 additions & 0 deletions src/os/XfsFileStoreBackend.cc
Original file line number Diff line number Diff line change
@@ -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);
}
33 changes: 33 additions & 0 deletions src/os/XfsFileStoreBackend.h
Original file line number Diff line number Diff line change
@@ -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 */

0 comments on commit 1f5b796

Please sign in to comment.