From: Yan, Zheng Date: Thu, 7 May 2015 10:44:34 +0000 (+0800) Subject: client: avoid sending unnessesary FLUSHSNAP message X-Git-Tag: v9.0.2~178^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b50ec2f53ef386ca872523b3bf19fd43dfe553c8;p=ceph.git client: avoid sending unnessesary FLUSHSNAP message when a snap notification contains no new snapshot, we can avoid sending FLUSHSNAP message to MDS. Signed-off-by: Yan, Zheng --- diff --git a/src/client/Client.cc b/src/client/Client.cc index de2856764482..5720881d2df9 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -3031,11 +3031,11 @@ void Client::check_caps(Inode *in, bool is_delayed) } -void Client::queue_cap_snap(Inode *in, snapid_t seq) +void Client::queue_cap_snap(Inode *in, SnapContext& old_snapc) { int used = get_caps_used(in); int dirty = in->caps_dirty(); - ldout(cct, 10) << "queue_cap_snap " << *in << " seq " << seq << " used " << ccap_string(used) << dendl; + ldout(cct, 10) << "queue_cap_snap " << *in << " snapc " << old_snapc << " used " << ccap_string(used) << dendl; if (in->cap_snaps.size() && in->cap_snaps.rbegin()->second->writing) { @@ -3046,8 +3046,8 @@ void Client::queue_cap_snap(Inode *in, snapid_t seq) (dirty & CEPH_CAP_ANY_WR)) { in->get(); CapSnap *capsnap = new CapSnap(in); - in->cap_snaps[seq] = capsnap; - capsnap->context = in->snaprealm->get_snap_context(); + in->cap_snaps[old_snapc.seq] = capsnap; + capsnap->context = old_snapc; capsnap->issued = in->caps_issued(); capsnap->dirty = in->caps_dirty(); @@ -3858,12 +3858,20 @@ bool Client::adjust_realm_parent(SnapRealm *realm, inodeno_t parent) return false; } +static bool has_new_snaps(const SnapContext& old_snapc, + const SnapContext& new_snapc) +{ + return !new_snapc.snaps.empty() && new_snapc.snaps[0] > old_snapc.seq; +} + inodeno_t Client::update_snap_trace(bufferlist& bl, bool flush) { inodeno_t first_realm = 0; ldout(cct, 10) << "update_snap_trace len " << bl.length() << dendl; + map dirty_realms; + bufferlist::iterator p = bl.begin(); while (!p.end()) { SnapRealmInfo info; @@ -3872,6 +3880,8 @@ inodeno_t Client::update_snap_trace(bufferlist& bl, bool flush) first_realm = info.ino(); SnapRealm *realm = get_snap_realm(info.ino()); + bool invalidate = false; + if (info.seq() > realm->seq) { ldout(cct, 10) << "update_snap_trace " << *realm << " seq " << info.seq() << " > " << realm->seq << dendl; @@ -3884,28 +3894,19 @@ inodeno_t Client::update_snap_trace(bufferlist& bl, bool flush) while (!q.empty()) { SnapRealm *realm = q.front(); q.pop_front(); - ldout(cct, 10) << " flushing caps on " << *realm << dendl; - - xlist::iterator p = realm->inodes_with_caps.begin(); - while (!p.end()) { - Inode *in = *p; - ++p; - queue_cap_snap(in, realm->get_snap_context().seq); - } for (set::iterator p = realm->pchildren.begin(); - p != realm->pchildren.end(); + p != realm->pchildren.end(); ++p) q.push_back(*p); + + if (dirty_realms.count(realm) == 0) { + realm->nref++; + dirty_realms[realm] = realm->get_snap_context(); + } } } - } - - // _always_ verify parent - bool invalidate = adjust_realm_parent(realm, info.parent()); - - if (info.seq() > realm->seq) { // update realm->seq = info.seq(); realm->created = info.created(); @@ -3914,6 +3915,11 @@ inodeno_t Client::update_snap_trace(bufferlist& bl, bool flush) realm->my_snaps = info.my_snaps; invalidate = true; } + + // _always_ verify parent + if (adjust_realm_parent(realm, info.parent())) + invalidate = true; + if (invalidate) { invalidate_snaprealm_and_children(realm); ldout(cct, 15) << "update_snap_trace " << *realm << " self|parent updated" << dendl; @@ -3926,6 +3932,25 @@ inodeno_t Client::update_snap_trace(bufferlist& bl, bool flush) put_snap_realm(realm); } + for (map::iterator q = dirty_realms.begin(); + q != dirty_realms.end(); + ++q) { + SnapRealm *realm = q->first; + // if there are new snaps ? + if (has_new_snaps(q->second, realm->get_snap_context())) { + ldout(cct, 10) << " flushing caps on " << *realm << dendl; + xlist::iterator r = realm->inodes_with_caps.begin(); + while (!r.end()) { + Inode *in = *r; + ++r; + queue_cap_snap(in, q->second); + } + } else { + ldout(cct, 10) << " no new snap on " << *realm << dendl; + } + put_snap_realm(realm); + } + return first_realm; } @@ -3943,6 +3968,7 @@ void Client::handle_snap(MClientSnap *m) list to_move; SnapRealm *realm = 0; + SnapContext old_snapc; if (m->head.op == CEPH_SNAP_OP_SPLIT) { assert(m->head.split); @@ -3954,6 +3980,7 @@ void Client::handle_snap(MClientSnap *m) // flush, then move, ino's. realm = get_snap_realm(info.ino()); ldout(cct, 10) << " splitting off " << *realm << dendl; + old_snapc = realm->get_snap_context(); for (vector::iterator p = m->split_inos.begin(); p != m->split_inos.end(); ++p) { @@ -3969,8 +3996,6 @@ void Client::handle_snap(MClientSnap *m) } ldout(cct, 10) << " moving " << *in << " from " << *in->snaprealm << dendl; - // queue for snap writeback - queue_cap_snap(in, in->snaprealm->get_snap_context().seq); in->snaprealm_item.remove_myself(); put_snap_realm(in->snaprealm); @@ -3994,11 +4019,15 @@ void Client::handle_snap(MClientSnap *m) update_snap_trace(m->bl, m->head.op != CEPH_SNAP_OP_DESTROY); if (realm) { + bool queue_snap = has_new_snaps(old_snapc, realm->get_snap_context()); for (list::iterator p = to_move.begin(); p != to_move.end(); ++p) { Inode *in = *p; in->snaprealm = realm; realm->inodes_with_caps.push_back(&in->snaprealm_item); realm->nref++; + // queue for snap writeback + if (queue_snap) + queue_cap_snap(in, old_snapc); } put_snap_realm(realm); } diff --git a/src/client/Client.h b/src/client/Client.h index 4430e565faca..d1d71acb392b 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -546,7 +546,7 @@ protected: void put_cap_ref(Inode *in, int cap); void flush_snaps(Inode *in, bool all_again=false, CapSnap *again=0); void wait_sync_caps(uint64_t want); - void queue_cap_snap(Inode *in, snapid_t seq=0); + void queue_cap_snap(Inode *in, SnapContext &old_snapc); void finish_cap_snap(Inode *in, CapSnap *capsnap, int used); void _flushed_cap_snap(Inode *in, snapid_t seq);