Skip to content

Commit

Permalink
crush/CrushTester: add check_name_maps() method
Browse files Browse the repository at this point in the history
* check for dangling bucket name or type names referenced by the
  buckets/items in the crush map.
* also check for the references from Item(0, 0, 0) which does not
  necessarily exist in the crush map under testing. the rationale
  behind this is: the "ceph osd tree" will also print stray OSDs
  whose id is greater or equal to 0. so it would be useful to
  check if the crush map offers the type name indexed by "0"
  (the name of OSDs is always "OSD.{id}", so we don't need to
  look up the name of an OSD item in the crushmap).

Signed-off-by: Kefu Chai <kchai@redhat.com>
(cherry picked from commit b75384d)
  • Loading branch information
tchaikov committed Jul 10, 2015
1 parent 3b6977b commit 960ea49
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/crush/CrushTester.cc
@@ -1,6 +1,7 @@

#include "include/stringify.h"
#include "CrushTester.h"
#include "CrushTreeDumper.h"

#include <algorithm>
#include <stdlib.h>
Expand Down Expand Up @@ -433,6 +434,54 @@ int CrushTester::test_with_crushtool(const string& crushtool,
return -r;
}

namespace {
class BadCrushMap : public std::runtime_error {
public:
int item;
BadCrushMap(const char* msg, int id)
: std::runtime_error(msg), item(id) {}
};
// throws if any node in the crush fail to print
class CrushWalker : public CrushTreeDumper::Dumper<void> {
typedef void DumbFormatter;
typedef CrushTreeDumper::Dumper<DumbFormatter> Parent;
public:
CrushWalker(const CrushWrapper *crush)
: Parent(crush) {}
void dump_item(const CrushTreeDumper::Item &qi, DumbFormatter *) {
int type = -1;
if (qi.is_bucket()) {
if (!crush->get_item_name(qi.id)) {
throw BadCrushMap("unknown item name", qi.id);
}
type = crush->get_bucket_type(qi.id);
} else {
type = 0;
}
if (!crush->get_type_name(type)) {
throw BadCrushMap("unknown type name", qi.id);
}
}
};
}

bool CrushTester::check_name_maps() const
{
CrushWalker crush_walker(&crush);
try {
// walk through the crush, to see if its self-contained
crush_walker.dump(NULL);
// and see if the maps is also able to handle straying OSDs, whose id >= 0.
// "ceph osd tree" will try to print them, even they are not listed in the
// crush map.
crush_walker.dump_item(CrushTreeDumper::Item(0, 0, 0), NULL);
} catch (const BadCrushMap& e) {
err << e.what() << ": item#" << e.item << std::endl;
return false;
}
return true;
}

int CrushTester::test()
{
if (min_rule < 0 || max_rule < 0) {
Expand Down
5 changes: 5 additions & 0 deletions src/crush/CrushTester.h
Expand Up @@ -333,6 +333,11 @@ class CrushTester {
min_rule = max_rule = rule;
}

/**
* check if any bucket/nodes is referencing an unknown name or type
* @return false if an dangling name/type is referenced, true otherwise
*/
bool check_name_maps() const;
int test();
int test_with_crushtool(const string& crushtool,
int timeout);
Expand Down

0 comments on commit 960ea49

Please sign in to comment.