Skip to content

Commit

Permalink
Merge branch 'wip-crush-update'
Browse files Browse the repository at this point in the history
Reviewed-by: Greg Farnum <[email protected]>
  • Loading branch information
Sage Weil committed May 4, 2012
2 parents 720bea4 + 42f2d2f commit 845e2aa
Show file tree
Hide file tree
Showing 12 changed files with 429 additions and 21 deletions.
88 changes: 86 additions & 2 deletions src/crush/CrushWrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ int CrushWrapper::remove_item(CephContext *cct, int item)
}
was_bucket = t;
}
adjust_item_weight(cct, item, 0);
ldout(cct, 5) << "remove_device removing item " << item << " from bucket " << b->id << dendl;
crush_bucket_remove_item(b, item);
ret = 0;
Expand All @@ -59,13 +60,60 @@ int CrushWrapper::remove_item(CephContext *cct, int item)
name_map.erase(item);
have_rmaps = false;
ret = 0;
}
}

return ret;
}

bool CrushWrapper::check_item_loc(CephContext *cct, int item, map<string,string>& loc,
int *weight)
{
ldout(cct, 5) << "check_item_loc item " << item << " loc " << loc << dendl;

int cur = item;
for (map<int,string>::const_iterator p = type_map.begin(); p != type_map.end(); p++) {
if (p->first == 0)
continue;

if (loc.count(p->second) == 0) {
ldout(cct, 2) << "warning: did not specify location for '" << p->second << "' level (levels are "
<< type_map << ")" << dendl;
continue;
}

int id = get_item_id(loc[p->second].c_str());
if (!id) {
ldout(cct, 5) << "check_item_loc bucket " << loc[p->second] << " of type " << p->second << " dne" << dendl;
return false;
}

if (id >= 0) {
ldout(cct, 5) << "check_item_loc requested " << loc[p->second] << " for type " << p->second
<< " is a device, not bucket" << dendl;
return false;
}

crush_bucket *b = get_bucket(id);
assert(b);

// see if item exists in this bucket
for (unsigned j=0; j<b->size; j++) {
if (b->items[j] == cur) {
ldout(cct, 2) << "check_item_loc " << cur << " exists in bucket " << b->id << dendl;
if (weight)
*weight = crush_get_bucket_item_weight(b, j);
return true;
}
}
return false;
}

ldout(cct, 1) << "check_item_loc item " << item << " loc " << loc << dendl;
return false;
}

int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string name,
map<string,string>& loc) // typename -> bucketname
map<string,string>& loc) // typename -> bucketname
{
ldout(cct, 5) << "insert_item item " << item << " weight " << weight
<< " name " << name << " loc " << loc << dendl;
Expand Down Expand Up @@ -130,6 +178,42 @@ int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string n
return -EINVAL;
}

int CrushWrapper::update_item(CephContext *cct, int item, float weight, string name,
map<string,string>& loc) // typename -> bucketname
{
ldout(cct, 5) << "update_item item " << item << " weight " << weight
<< " name " << name << " loc " << loc << dendl;
int ret = 0;

// compare quantized (fixed-point integer) weights!
int iweight = (int)(weight * (float)0x10000);
int old_iweight;
if (check_item_loc(cct, item, loc, &old_iweight)) {
ldout(cct, 5) << "update_item " << item << " already at " << loc << dendl;
if (old_iweight != iweight) {
ldout(cct, 5) << "update_item " << item << " adjusting weight "
<< ((float)old_iweight/(float)0x10000) << " -> " << weight << dendl;
adjust_item_weight(cct, item, iweight);
ret = 1;
}
if (get_item_name(item) != name) {
ldout(cct, 5) << "update_item setting " << item << " name to " << name << dendl;
set_item_name(item, name.c_str());
ret = 1;
}
} else {
if (item_exists(item)) {
remove_item(cct, item);
}
ldout(cct, 5) << "update_item adding " << item << " weight " << weight
<< " at " << loc << dendl;
int r = insert_item(cct, item, weight, name.c_str(), loc);
if (r == 0)
ret = 1;
}
return ret;
}

int CrushWrapper::adjust_item_weight(CephContext *cct, int id, int weight)
{
ldout(cct, 5) << "adjust_item_weight " << id << " weight " << weight << dendl;
Expand Down
55 changes: 54 additions & 1 deletion src/crush/CrushWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,68 @@ class CrushWrapper {


void find_roots(set<int>& roots) const;

/**
* see if item is located where we think it is
*
* @param cct cct
* @param item item id
* @param loc location to check (map of type to bucket names)
* @param weight optional pointer to weight of item at that location
* @return true if item is at specified location
*/
bool check_item_loc(CephContext *cct, int item, map<string,string>& loc, int *iweight);
bool check_item_loc(CephContext *cct, int item, map<string,string>& loc, float *weight) {
int iweight;
bool ret = check_item_loc(cct, item, loc, &iweight);
if (weight)
*weight = (float)iweight / (float)0x10000;
return ret;
}

/**
* insert an item into the map at a specific position
*
* If the item is already present in the map, we will return EEXIST or similar errors.
*
* @param cct cct
* @param id item id
* @param weight item weight
* @param name item name
* @param loc location (map of type to bucket names)
* @return 0 for success, negative on error
*/
int insert_item(CephContext *cct, int id, float weight, string name, map<string,string>& loc);

/**
* add or update an item's position in the map
*
* This is analogous to insert_item, except we will move an item if
* it is already present.
*
* @param cct cct
* @param id item id
* @param weight item weight
* @param name item name
* @param loc location (map of type to bucket names)
* @return 0 for no change, 1 for successful change, negative on error
*/
int update_item(CephContext *cct, int id, float weight, string name, map<string,string>& loc);

/**
* remove an item from the map
*
* @param cct cct
* @param id item id to remove
* @return 0 on success, negative on error
*/
int remove_item(CephContext *cct, int id);
int adjust_item_weight(CephContext *cct, int id, int weight);
int adjust_item_weightf(CephContext *cct, int id, float weight) {
return adjust_item_weight(cct, id, (int)(weight * (float)0x10000));
}
void reweight(CephContext *cct);


/*** devices ***/
int get_max_devices() const {
if (!crush) return 0;
Expand Down
31 changes: 26 additions & 5 deletions src/crushtool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ void usage()
cout << " -i mapfn --add-item id weight name [--loc type name ...]\n";
cout << " insert an item into the hierarchy at the\n";
cout << " given location\n";
cout << " -i mapfn --update-item id weight name [--loc type name ...]\n";
cout << " insert or move an item into the hierarchy at the\n";
cout << " given location\n";
cout << " -i mapfn --remove-item name\n"
<< " remove the given item\n";
cout << " -i mapfn --reweight-item name weight\n";
Expand Down Expand Up @@ -103,6 +106,7 @@ int main(int argc, const char **argv)

bool reweight = false;
int add_item = -1;
bool update_item = false;
float add_weight = 0;
map<string,string> add_loc;
float reweight_weight = 0;
Expand Down Expand Up @@ -158,6 +162,20 @@ int main(int argc, const char **argv)
usage();
add_name.assign(*i);
i = args.erase(i);
} else if (ceph_argparse_withint(args, i, &add_item, &err, "--update_item", (char*)NULL)) {
update_item = true;
if (!err.str().empty()) {
cerr << err.str() << std::endl;
exit(EXIT_FAILURE);
}
if (i == args.end())
usage();
add_weight = atof(*i);
i = args.erase(i);
if (i == args.end())
usage();
add_name.assign(*i);
i = args.erase(i);
} else if (ceph_argparse_witharg(args, i, &val, "--loc", (char*)NULL)) {
std::string type(val);
if (i == args.end())
Expand Down Expand Up @@ -467,12 +485,15 @@ int main(int argc, const char **argv)
}
}
if (add_item >= 0) {
cout << me << " adding item " << add_item << " weight " << add_weight
<< " at " << add_loc << std::endl;
int r = crush.insert_item(g_ceph_context, add_item, add_weight, add_name.c_str(), add_loc);
if (r == 0)
int r;
if (update_item) {
r = crush.update_item(g_ceph_context, add_item, add_weight, add_name.c_str(), add_loc);
} else {
r = crush.insert_item(g_ceph_context, add_item, add_weight, add_name.c_str(), add_loc);
}
if (r >= 0) {
modified = true;
else {
} else {
cerr << me << " " << cpp_strerror(r) << std::endl;
return r;
}
Expand Down
21 changes: 10 additions & 11 deletions src/mon/OSDMonitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1755,9 +1755,9 @@ bool OSDMonitor::prepare_command(MMonCommand *m)
paxos->wait_for_commit(new Monitor::C_Command(mon, m, 0, rs, paxos->get_version()));
return true;
}
else if (m->cmd.size() >= 6 && m->cmd[1] == "crush" && m->cmd[2] == "add") {
else if (m->cmd.size() >= 6 && m->cmd[1] == "crush" && m->cmd[2] == "set") {
do {
// osd crush add <id> <name> <weight> [<loc1> [<loc2> ...]]
// osd crush update <id> <name> <weight> [<loc1> [<loc2> ...]]
int id = atoi(m->cmd[3].c_str());
string name = m->cmd[4];
float weight = atof(m->cmd[5].c_str());
Expand All @@ -1772,7 +1772,7 @@ bool OSDMonitor::prepare_command(MMonCommand *m)
loc[key] = value;
}

dout(0) << "adding crush item id " << id << " name '" << name << "' weight " << weight
dout(0) << "adding/updating crush item id " << id << " name '" << name << "' weight " << weight
<< " at location " << loc << dendl;
bufferlist bl;
if (pending_inc.crush.length())
Expand All @@ -1784,17 +1784,16 @@ bool OSDMonitor::prepare_command(MMonCommand *m)
bufferlist::iterator p = bl.begin();
newcrush.decode(p);

err = newcrush.insert_item(g_ceph_context, id, weight, name, loc);
err = newcrush.update_item(g_ceph_context, id, weight, name, loc);
if (err == 0) {
if (newcrush.get_max_devices() > osdmap.get_max_osd()) {
err = -ERANGE;
ss << "crushmap max_devices " << newcrush.get_max_devices()
<< " > osdmap max_osd " << osdmap.get_max_osd();
break;
}
ss << "updated item id " << id << " name '" << name << "' weight " << weight
<< " at location " << loc << " to crush map";
break;
}
if (err > 0) {
pending_inc.crush.clear();
newcrush.encode(pending_inc.crush);
ss << "added item id " << id << " name '" << name << "' weight " << weight
ss << "updated item id " << id << " name '" << name << "' weight " << weight
<< " at location " << loc << " to crush map";
getline(ss, rs);
paxos->wait_for_commit(new Monitor::C_Command(mon, m, 0, rs, paxos->get_version()));
Expand Down
13 changes: 12 additions & 1 deletion src/test/cli/crushtool/add-item.t
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
$ crushtool -i "$TESTDIR/simple.template" --add-item 0 1.0 device0 --loc host host0 --loc cluster cluster0 -o one > /dev/null
$ crushtool -i one --add-item 1 1.0 device1 --loc host host0 --loc cluster cluster0 -o two > /dev/null
$ crushtool -d two -o final
$ cmp final "$TESTDIR/simple.template.out"
$ cmp final "$TESTDIR/simple.template.two"
$ crushtool -i two --add-item 1 1.0 device1 --loc host host0 --loc cluster cluster0 -o three 2>/dev/null >/dev/null || echo FAIL
FAIL
$ crushtool -i two --remove-item device1 -o four > /dev/null
$ crushtool -d four -o final
$ cmp final "$TESTDIR/simple.template.four"
$ crushtool -i two --update-item 1 2.0 osd1 --loc host host1 --loc cluster cluster0 -o five > /dev/null
$ crushtool -d five -o final
$ cmp final "$TESTDIR/simple.template.five"
$ crushtool -i five --update-item 1 2.0 osd1 --loc host host1 --loc cluster cluster0 -o six > /dev/null
$ crushtool -d six -o final
$ cmp final "$TESTDIR/simple.template.five"
3 changes: 3 additions & 0 deletions src/test/cli/crushtool/help.t
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
-i mapfn --add-item id weight name [--loc type name ...]
insert an item into the hierarchy at the
given location
-i mapfn --update-item id weight name [--loc type name ...]
insert or move an item into the hierarchy at the
given location
-i mapfn --remove-item name
remove the given item
-i mapfn --reweight-item name weight
Expand Down
65 changes: 65 additions & 0 deletions src/test/cli/crushtool/simple.template.five
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# begin crush map

# devices
device 0 device0
device 1 osd1

# types
type 0 device
type 1 host
type 2 cluster

# buckets
host host0 {
id -2 # do not change unnecessarily
# weight 1.000
alg straw
hash 0 # rjenkins1
item device0 weight 1.000
}
host host1 {
id -3 # do not change unnecessarily
# weight 2.000
alg straw
hash 0 # rjenkins1
item osd1 weight 2.000
}
cluster cluster0 {
id -1 # do not change unnecessarily
# weight 3.000
alg straw
hash 0 # rjenkins1
item host0 weight 1.000
item host1 weight 2.000
}

# rules
rule data {
ruleset 0
type replicated
min_size 1
max_size 10
step take cluster0
step chooseleaf firstn 0 type host
step emit
}
rule metadata {
ruleset 1
type replicated
min_size 1
max_size 10
step take cluster0
step chooseleaf firstn 0 type host
step emit
}
rule rbd {
ruleset 2
type replicated
min_size 1
max_size 10
step take cluster0
step chooseleaf firstn 0 type host
step emit
}

# end crush map
Loading

0 comments on commit 845e2aa

Please sign in to comment.