Skip to content

Commit

Permalink
Merge branch 'wip-cephfs-tmap-migrate' of git://github.com/jcsp/ceph …
Browse files Browse the repository at this point in the history
…into greg-fs-testing

#7003
  • Loading branch information
gregsfortytwo committed Feb 8, 2016
2 parents 02dc585 + fefe7c0 commit 836deb1
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 1 deletion.
11 changes: 11 additions & 0 deletions src/test/CMakeLists.txt
Expand Up @@ -2085,6 +2085,17 @@ set_target_properties(test_rados_api_misc PROPERTIES COMPILE_FLAGS
target_link_libraries(test_rados_api_misc
librados global ${UNITTEST_LIBS} ${ALLOC_LIBS} radostest)

add_executable(test_rados_api_tmap_migrate
../tools/cephfs/DataScan.cc
../tools/cephfs/MDSUtility.cc
librados/tmap_migrate.cc
$<TARGET_OBJECTS:heap_profiler_objs>
)
set_target_properties(test_rados_api_tmap_migrate PROPERTIES COMPILE_FLAGS
${UNITTEST_CXX_FLAGS})
target_link_libraries(test_rados_api_tmap_migrate
librados mds osdc global cls_cephfs_client ${UNITTEST_LIBS} ${ALLOC_LIBS} radostest)

add_executable(test_rados_api_lock
librados/lock.cc
$<TARGET_OBJECTS:heap_profiler_objs>
Expand Down
5 changes: 5 additions & 0 deletions src/test/Makefile-client.am
Expand Up @@ -283,6 +283,11 @@ ceph_test_rados_api_lock_LDADD = $(LIBRADOS) $(UNITTEST_LDADD) $(RADOS_TEST_LDAD
ceph_test_rados_api_lock_CXXFLAGS = $(UNITTEST_CXXFLAGS)
bin_DEBUGPROGRAMS += ceph_test_rados_api_lock

ceph_test_rados_api_tmap_migrate_SOURCES = test/librados/tmap_migrate.cc tools/cephfs/DataScan.cc tools/cephfs/MDSUtility.cc
ceph_test_rados_api_tmap_migrate_LDADD = $(LIBRADOS) $(UNITTEST_LDADD) $(LIBMDS) libcls_cephfs_client.la $(CEPH_GLOBAL) $(RADOS_TEST_LDADD)
ceph_test_rados_api_tmap_migrate_CXXFLAGS = $(UNITTEST_CXXFLAGS)
bin_DEBUGPROGRAMS += ceph_test_rados_api_tmap_migrate


ceph_test_stress_watch_SOURCES = test/test_stress_watch.cc
ceph_test_stress_watch_LDADD = \
Expand Down
70 changes: 70 additions & 0 deletions src/test/librados/tmap_migrate.cc
@@ -0,0 +1,70 @@
#include "include/rados/librados.h"
#include "include/rados/librados.hpp"
#include "test/librados/test.h"
#include "test/librados/TestCase.h"
#include "include/encoding.h"
#include "tools/cephfs/DataScan.h"
#include "global/global_init.h"

#include <algorithm>
#include <errno.h>
#include "gtest/gtest.h"


using namespace librados;

typedef RadosTestPP TmapMigratePP;

TEST_F(TmapMigratePP, DataScan) {
std::vector<const char *> args;
global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
common_init_finish(g_ceph_context);

// DataScan isn't namespace-aware, so override RadosTestPP's default
// behaviour of putting everything into a namespace
ioctx.set_namespace("");

bufferlist header;
std::map<std::string, bufferlist> kvs;
bufferlist val;
val.append("custard");
kvs.insert({"rhubarb", val});

bufferlist tmap_trans;
::encode(header, tmap_trans);
::encode(kvs, tmap_trans);

// Create a TMAP object
ASSERT_EQ(0, ioctx.tmap_put("10000000000.00000000", tmap_trans));

// Create an OMAP object
std::map<std::string, bufferlist> omap_kvs;
bufferlist omap_val;
omap_val.append("waffles");
omap_kvs.insert({"tasty", omap_val});
ASSERT_EQ(0, ioctx.omap_set("10000000001.00000000", omap_kvs));

DataScan ds;
ASSERT_EQ(0, ds.init());
int r = ds.main({"tmap_upgrade", pool_name.c_str()});
ASSERT_EQ(r, 0);
ds.shutdown();

// Check that the TMAP object is now an omap object
std::map<std::string, bufferlist> read_vals;
ASSERT_EQ(0, ioctx.omap_get_vals("10000000000.00000000", "", 1, &read_vals));
ASSERT_EQ(read_vals.size(), 1);
bufferlist tmap_expect_val;
tmap_expect_val.append("custard");
ASSERT_EQ(read_vals.at("rhubarb"), tmap_expect_val);


// Check that the OMAP object is still readable
read_vals.clear();
ASSERT_EQ(0, ioctx.omap_get_vals("10000000001.00000000", "", 1, &read_vals));
ASSERT_EQ(read_vals.size(), 1);
bufferlist expect_omap_val;
expect_omap_val.append("waffles");
ASSERT_EQ(read_vals.at("tasty"), expect_omap_val);
}

84 changes: 83 additions & 1 deletion src/tools/cephfs/DataScan.cc
Expand Up @@ -39,6 +39,8 @@ void DataScan::usage()
<< " --force-pool: use data pool even if it is not in MDSMap\n"
<< "\n"
<< " cephfs-data-scan scan_frags [--force-corrupt]\n"
<< "\n"
<< " cephfs-data-scan tmap_upgrade <metadata_pool>\n"
<< std::endl;

generic_client_usage();
Expand Down Expand Up @@ -131,6 +133,7 @@ int DataScan::main(const std::vector<const char*> &args)

std::string const &command = args[0];
std::string data_pool_name;
std::string metadata_pool_name;

// Consume any known --key val or --flag arguments
for (std::vector<const char *>::const_iterator i = args.begin() + 1;
Expand All @@ -147,12 +150,19 @@ int DataScan::main(const std::vector<const char*> &args)
continue;
}

// Trailing positional argument
if (i + 1 == args.end() &&
(command == "scan_inodes" || command == "scan_extents")) {
data_pool_name = *i;
continue;
}

// Trailing positional argument
if (i + 1 == args.end() && (command == "tmap_upgrade")) {
metadata_pool_name = *i;
continue;
}

// Fall through: unhandled
std::cerr << "Unknown argument '" << *i << "'" << std::endl;
return -EINVAL;
Expand Down Expand Up @@ -207,9 +217,9 @@ int DataScan::main(const std::vector<const char*> &args)
}
}

// Initialize metadata_io from MDSMap for scan_frags
if (command == "scan_frags") {
int const metadata_pool_id = mdsmap->get_metadata_pool();

dout(4) << "resolving metadata pool " << metadata_pool_id << dendl;
std::string metadata_pool_name;
int r = rados.pool_reverse_lookup(metadata_pool_id, &metadata_pool_name);
Expand All @@ -225,13 +235,39 @@ int DataScan::main(const std::vector<const char*> &args)
}
}

// Initialize metadata_io from pool on command line for tmap_upgrade
if (command == "tmap_upgrade") {
if (metadata_pool_name.empty()) {
std::cerr << "Metadata pool not specified" << std::endl;
usage();
return -EINVAL;
}

long metadata_pool_id = rados.pool_lookup(metadata_pool_name.c_str());
if (metadata_pool_id < 0) {
std::cerr << "Pool '" << metadata_pool_name << "' not found!" << std::endl;
return -ENOENT;
} else {
dout(4) << "pool '" << metadata_pool_name
<< "' has ID " << metadata_pool_id << dendl;
}

r = rados.ioctx_create(metadata_pool_name.c_str(), metadata_io);
if (r != 0) {
return r;
}
std::cerr << "Created ioctx for " << metadata_pool_name << std::endl;
}

// Finally, dispatch command
if (command == "scan_inodes") {
return scan_inodes();
} else if (command == "scan_extents") {
return scan_extents();
} else if (command == "scan_frags") {
return scan_frags();
} else if (command == "tmap_upgrade") {
return tmap_upgrade();
} else if (command == "init") {
return driver->init_roots(mdsmap->get_first_data_pool());
} else {
Expand Down Expand Up @@ -765,6 +801,52 @@ int DataScan::scan_inodes()
return 0;
}

bool DataScan::valid_ino(inodeno_t ino) const
{
return (ino >= inodeno_t((1ull << 40)))
|| (MDS_INO_IS_STRAY(ino))
|| (MDS_INO_IS_MDSDIR(ino))
|| ino == MDS_INO_ROOT
|| ino == MDS_INO_CEPH;
}

int DataScan::tmap_upgrade()
{
librados::NObjectIterator i = metadata_io.nobjects_begin();
const librados::NObjectIterator i_end = metadata_io.nobjects_end();

int overall_r = 0;

for (; i != i_end; ++i) {
const std::string oid = i->get_oid();

uint64_t inode_no = 0;
uint64_t frag_id = 0;
int r = parse_oid(oid, &inode_no, &frag_id);
if (r == -EINVAL) {
dout(10) << "Not a dirfrag: '" << oid << "'" << dendl;
continue;
} else {
// parse_oid can only do 0 or -EINVAL
assert(r == 0);
}

if (!valid_ino(inode_no)) {
dout(10) << "Not a difrag (invalid ino): '" << oid << "'" << dendl;
continue;
}

r = metadata_io.tmap_to_omap(oid, true);
dout(20) << "tmap2omap(" << oid << "): " << r << dendl;
if (r < 0) {
derr << "Error converting '" << oid << "': " << cpp_strerror(r) << dendl;
overall_r = r;
}
}

return overall_r;
}

int DataScan::scan_frags()
{
librados::NObjectIterator i;
Expand Down
10 changes: 10 additions & 0 deletions src/tools/cephfs/DataScan.h
Expand Up @@ -249,6 +249,16 @@ class DataScan : public MDSUtility, public MetadataTool
*/
int scan_frags();

/**
* Check if an inode number is in the permitted ranges
*/
bool valid_ino(inodeno_t ino) const;

/**
* Invoke tmap_to_omap on all metadata pool objects
*/
int tmap_upgrade();

// Accept pools which are not in the MDSMap
bool force_pool;
// Respond to decode errors by overwriting
Expand Down

0 comments on commit 836deb1

Please sign in to comment.