split_ops(child, split_bits);
_split_into(child_pgid, child, split_bits);
+ // release all backoffs so that Objecter doesn't need to handle unblock
+ // on split backoffs
+ release_backoffs(hobject_t(), hobject_t::get_max());
+ // split any remaining (deleting) backoffs among child PGs
+ split_backoffs(child, split_bits);
+
child->on_new_interval();
child->dirty_info = true;
}
}
+void PG::split_backoffs(PG *child, unsigned split_bits)
+{
+ dout(10) << __func__ << " split_bits " << split_bits << " child "
+ << child->info.pgid.pgid << dendl;
+ unsigned mask = ~((~0)<<split_bits);
+ vector<BackoffRef> backoffs_to_dup; // pg backoffs
+ vector<BackoffRef> backoffs_to_move; // oid backoffs
+ {
+ Mutex::Locker l(backoff_lock);
+ auto p = backoffs.begin();
+ while (p != backoffs.end()) {
+ if (p->first == info.pgid.pgid.get_hobj_start()) {
+ // if it is a full PG we always dup it for the child.
+ for (auto& q : p->second) {
+ dout(10) << __func__ << " pg backoff " << p->first
+ << " " << q << dendl;
+ backoffs_to_dup.push_back(q);
+ }
+ } else {
+ // otherwise, we move it to the child only if falls into the
+ // childs hash range.
+ if ((p->first.get_hash() & mask) == child->info.pgid.pgid.ps()) {
+ for (auto& q : p->second) {
+ dout(20) << __func__ << " will move " << p->first
+ << " " << q << dendl;
+ backoffs_to_move.push_back(q);
+ }
+ p = backoffs.erase(p);
+ continue;
+ } else {
+ dout(20) << __func__ << " will not move " << p->first
+ << " " << p->second << dendl;
+ }
+ }
+ ++p;
+ }
+ }
+ for (auto b : backoffs_to_dup) {
+ SessionRef s;
+ {
+ Mutex::Locker l(b->lock);
+ b->end = info.pgid.pgid.get_hobj_end(split_bits);
+ dout(10) << __func__ << " pg backoff " << *b << dendl;
+ s = b->session;
+ }
+ if (s) {
+ child->add_pg_backoff(b->session);
+ } else {
+ dout(20) << __func__ << " didn't dup pg backoff, session is null"
+ << dendl;
+ }
+ }
+ for (auto b : backoffs_to_move) {
+ Mutex::Locker l(b->lock);
+ if (b->pg == this) {
+ dout(10) << __func__ << " move backoff " << *b << " to child" << dendl;
+ b->pg = child;
+ child->backoffs[b->begin].insert(b);
+ } else {
+ dout(20) << __func__ << " move backoff " << *b << " nowhere... pg is null"
+ << dendl;
+ }
+ }
+}
+
void PG::clear_backoffs()
{
dout(10) << __func__ << " " << dendl;