Skip to content

Commit

Permalink
tools: add cephfs-table-tool 'take_inos'
Browse files Browse the repository at this point in the history
For when your InoTable is wrong, and you want to
bluntly mark all the inos up to the highest you've
seen as in use.  You'll waste some inos by marking
in use when they're really not, but you'll guarantee
that the system won't try and re-use an ino that's
really already used by a file.

Since this breaks the mould of the apply_rank_fn
prototype, and I'm using lambdas here now, also go
ahead and convert the other actions to be lambdas
instead of having lots of _reset_foo_table boilerplate
at class scope.

Signed-off-by: John Spray <john.spray@redhat.com>
  • Loading branch information
John Spray committed Nov 19, 2015
1 parent b2f2e6c commit d1cbebd
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 138 deletions.
19 changes: 19 additions & 0 deletions src/mds/InoTable.h
Expand Up @@ -83,6 +83,25 @@ class InoTable : public MDSTable {
return false;
}
}

/**
* If this ino is in this rank's range, consume up to and including it.
* For use in tools, when we know the max ino in use and want to make
* sure we're only allocating new inodes from above it.
*
* @return true if the table was modified
*/
bool force_consume_to(inodeno_t ino)
{
if (free.contains(ino)) {
inodeno_t min = free.begin().get_start();
std::cerr << "Erasing 0x" << std::hex << min << " to 0x" << ino << std::dec << std::endl;
free.erase(min, ino - min);
return true;
} else {
return false;
}
}
};

#endif
275 changes: 147 additions & 128 deletions src/tools/cephfs/TableTool.cc
Expand Up @@ -30,112 +30,21 @@ void TableTool::usage()
{
std::cout << "Usage: \n"
<< " cephfs-table-tool <all|[mds rank]> <reset|show> <session|snap|inode>"
<< " cephfs-table-tool <all|[mds rank]> <take_inos> <max_ino>"
<< std::endl;

generic_client_usage();
}


int TableTool::main(std::vector<const char*> &argv)
{
int r;

dout(10) << __func__ << dendl;

// RADOS init
// ==========
r = rados.init_with_context(g_ceph_context);
if (r < 0) {
derr << "RADOS unavailable, cannot scan filesystem journal" << dendl;
return r;
}

dout(4) << "connecting to RADOS..." << dendl;
rados.connect();

int const pool_id = mdsmap->get_metadata_pool();
dout(4) << "resolving pool " << pool_id << dendl;
std::string pool_name;
r = rados.pool_reverse_lookup(pool_id, &pool_name);
if (r < 0) {
derr << "Pool " << pool_id << " identified in MDS map not found in RADOS!" << dendl;
return r;
}

dout(4) << "creating IoCtx.." << dendl;
r = rados.ioctx_create(pool_name.c_str(), io);
assert(r == 0);

// Require at least 3 args <action> <table> <rank>
if (argv.size() < 3) {
usage();
return -EINVAL;
}

const std::string rank_str = std::string(argv[0]);
const std::string mode = std::string(argv[1]);
const std::string table = std::string(argv[2]);

if (rank_str == "all") {
rank = MDS_RANK_NONE;
} else {
std::string rank_err;
rank = strict_strtol(rank_str.c_str(), 10, &rank_err);
if (!rank_err.empty()) {
derr << "Bad rank '" << rank_str << "'" << dendl;
usage();
}
}

JSONFormatter jf(true);
if (mode == "reset") {
if (table == "session") {
r = apply_rank_fn(&TableTool::_reset_session_table, &jf);
} else if (table == "inode") {
r = apply_rank_fn(&TableTool::_reset_ino_table, &jf);
} else if (table == "snap") {
r = _reset_snap_table(&jf);
} else {
derr << "Invalid table '" << table << "'" << dendl;
usage();
return -EINVAL;
}
} else if (mode == "show") {
if (table == "session") {
r = apply_rank_fn(&TableTool::_show_session_table, &jf);
} else if (table == "inode") {
r = apply_rank_fn(&TableTool::_show_ino_table, &jf);
} else if (table == "snap") {
r = _show_snap_table(&jf);
} else {
derr << "Invalid table '" << table << "'" << dendl;
usage();
return -EINVAL;
}
} else {
derr << "Invalid mode '" << mode << "'" << dendl;
usage();
return -EINVAL;
}

// Subcommand should have written to formatter, flush it
jf.flush(std::cout);
std::cout << std::endl;
return r;
}






/**
* For a function that takes an MDS rank as an argument and
* returns an error code, execute it either on all ranks (if
* this->rank is MDS_RANK_NONE), or on the rank specified
* by this->rank.
*/
int TableTool::apply_rank_fn(int (TableTool::*fptr) (mds_rank_t, Formatter*), Formatter *f)
//int TableTool::apply_rank_fn(int (TableTool::*fptr) (mds_rank_t, Formatter*), Formatter *f)
int TableTool::apply_rank_fn(std::function<int(mds_rank_t, Formatter *)> fptr, Formatter *f)
{
assert(f != NULL);

Expand All @@ -156,7 +65,7 @@ int TableTool::apply_rank_fn(int (TableTool::*fptr) (mds_rank_t, Formatter*), Fo
f->open_object_section(rank_str.str().c_str());

f->open_object_section("data");
int rank_r = (this->*fptr)(*rank_i, f);
int rank_r = fptr(*rank_i, f);
f->close_section();
r = r ? r : rank_r;

Expand All @@ -178,7 +87,7 @@ int TableTool::apply_rank_fn(int (TableTool::*fptr) (mds_rank_t, Formatter*), Fo
template <typename A>
class TableHandler
{
private:
protected:
// The RADOS object ID for the table
std::string object_name;

Expand Down Expand Up @@ -238,10 +147,17 @@ class TableHandler
int reset(librados::IoCtx *io)
{
A table_inst;
// Compose new (blank) table
table_inst.set_rank(rank);
table_inst.reset_state();

// Compose new (blank) table
// Write the table out
return write(table_inst, io);
}

protected:

int write(const A &table_inst, librados::IoCtx *io)
{
bufferlist new_bl;
if (mds_table) {
version_t version = 1;
Expand Down Expand Up @@ -346,7 +262,6 @@ class TableHandlerOmap
A table_inst;
table_inst.set_rank(rank);
table_inst.reset_state();

bufferlist header_bl;
table_inst.encode_header(&header_bl);

Expand All @@ -360,46 +275,150 @@ class TableHandlerOmap
}
};

int TableTool::_show_session_table(mds_rank_t rank, Formatter *f)
class InoTableHandler : public TableHandler<InoTable>
{
return TableHandlerOmap<SessionMapStore>(rank, "sessionmap", false).load_and_dump(&io, f);
}
public:
InoTableHandler(mds_rank_t r)
: TableHandler(r, "inotable", true)
{}

int TableTool::_reset_session_table(mds_rank_t rank, Formatter *f)
{
return TableHandlerOmap<SessionMapStore>(rank, "sessionmap", false).reset(&io);
}
int take_inos(librados::IoCtx *io, inodeno_t max)
{
InoTable inst;
inst.set_rank(rank);
inst.reset_state();

int TableTool::_show_ino_table(mds_rank_t rank, Formatter *f)
{
return TableHandler<InoTable>(rank, "inotable", true).load_and_dump(&io, f);;
}
if (inst.force_consume_to(max)) {
return write(inst, io);
} else {
return 0;
}
}
};

int TableTool::_reset_ino_table(mds_rank_t rank, Formatter *f)
{
return TableHandler<InoTable>(rank, "inotable", true).reset(&io);
}

int TableTool::_show_snap_table(Formatter *f)
int TableTool::main(std::vector<const char*> &argv)
{
int r;

f->open_object_section("show_snap_table");
{
r = TableHandler<SnapServer>(MDS_RANK_NONE, "snaptable", true).load_and_dump(&io, f);
f->dump_int("result", r);
dout(10) << __func__ << dendl;

// RADOS init
// ==========
r = rados.init_with_context(g_ceph_context);
if (r < 0) {
derr << "RADOS unavailable, cannot scan filesystem journal" << dendl;
return r;
}
f->close_section();

return r;
}
dout(4) << "connecting to RADOS..." << dendl;
rados.connect();

int const pool_id = mdsmap->get_metadata_pool();
dout(4) << "resolving pool " << pool_id << dendl;
std::string pool_name;
r = rados.pool_reverse_lookup(pool_id, &pool_name);
if (r < 0) {
derr << "Pool " << pool_id << " identified in MDS map not found in RADOS!" << dendl;
return r;
}

int TableTool::_reset_snap_table(Formatter *f)
{
int r = TableHandler<SnapServer>(MDS_RANK_NONE, "snaptable", true).reset(&io);
f->open_object_section("reset_snap_status");
f->dump_int("result", r);
f->close_section();
dout(4) << "creating IoCtx.." << dendl;
r = rados.ioctx_create(pool_name.c_str(), io);
assert(r == 0);

// Require at least 3 args <rank> <mode> <arg> [args...]
if (argv.size() < 3) {
usage();
return -EINVAL;
}

const std::string rank_str = std::string(argv[0]);
const std::string mode = std::string(argv[1]);

if (rank_str == "all") {
rank = MDS_RANK_NONE;
} else {
std::string rank_err;
rank = strict_strtol(rank_str.c_str(), 10, &rank_err);
if (!rank_err.empty()) {
derr << "Bad rank '" << rank_str << "'" << dendl;
usage();
}
}

JSONFormatter jf(true);
if (mode == "reset") {
const std::string table = std::string(argv[2]);
if (table == "session") {
r = apply_rank_fn([this](mds_rank_t rank, Formatter *f) -> int {
return TableHandlerOmap<SessionMapStore>(rank, "sessionmap", false).reset(&io);
}, &jf);
} else if (table == "inode") {
r = apply_rank_fn([this](mds_rank_t rank, Formatter *f) -> int {
return TableHandler<InoTable>(rank, "inotable", true).reset(&io);
}, &jf);
} else if (table == "snap") {
r = apply_rank_fn([this](mds_rank_t rank, Formatter *f) -> int {
int r = TableHandler<SnapServer>(MDS_RANK_NONE, "snaptable", true).reset(&io);
f->open_object_section("reset_snap_status");
f->dump_int("result", r);
f->close_section();
return r;
}, &jf);
} else {
derr << "Invalid table '" << table << "'" << dendl;
usage();
return -EINVAL;
}
} else if (mode == "show") {
const std::string table = std::string(argv[2]);
if (table == "session") {
r = apply_rank_fn([this](mds_rank_t rank, Formatter *f) -> int {
return TableHandlerOmap<SessionMapStore>(rank, "sessionmap", false).load_and_dump(&io, f);
}, &jf);
} else if (table == "inode") {
r = apply_rank_fn([this](mds_rank_t rank, Formatter *f) -> int {
return TableHandler<InoTable>(rank, "inotable", true).load_and_dump(&io, f);;
}, &jf);
} else if (table == "snap") {
r = apply_rank_fn([this](mds_rank_t rank, Formatter *f) -> int {
int r;

f->open_object_section("show_snap_table");
{
r = TableHandler<SnapServer>(MDS_RANK_NONE, "snaptable", true).load_and_dump(&io, f);
f->dump_int("result", r);
}
f->close_section();

return r;
}, &jf);
} else {
derr << "Invalid table '" << table << "'" << dendl;
usage();
return -EINVAL;
}
} else if (mode == "take_inos") {
const std::string ino_str = std::string(argv[2]);
std::string ino_err;
inodeno_t ino = strict_strtoll(ino_str.c_str(), 10, &ino_err);
if (!ino_err.empty()) {
derr << "Bad ino '" << ino_str << "'" << dendl;
return -EINVAL;
}
r = apply_rank_fn([this, ino](mds_rank_t rank, Formatter *f) -> int {
return InoTableHandler(rank).take_inos(&io, ino);
}, &jf);
} else {
derr << "Invalid mode '" << mode << "'" << dendl;
usage();
return -EINVAL;
}

// Subcommand should have written to formatter, flush it
jf.flush(std::cout);
std::cout << std::endl;
return r;
}

11 changes: 1 addition & 10 deletions src/tools/cephfs/TableTool.h
Expand Up @@ -30,16 +30,7 @@ class TableTool : public MDSUtility
librados::Rados rados;
librados::IoCtx io;

int apply_rank_fn(int (TableTool::*fptr) (mds_rank_t, Formatter *), Formatter *f);

int _reset_session_table(mds_rank_t rank, Formatter *f);
int _show_session_table(mds_rank_t rank, Formatter *f);

int _show_ino_table(mds_rank_t rank, Formatter *f);
int _reset_ino_table(mds_rank_t rank, Formatter *f);

int _show_snap_table(Formatter *f);
int _reset_snap_table(Formatter *f);
int apply_rank_fn(std::function<int(mds_rank_t, Formatter *)> fptr, Formatter *f);

public:
void usage();
Expand Down

0 comments on commit d1cbebd

Please sign in to comment.