From: Xinze Chi Date: Sun, 2 Aug 2015 10:36:40 +0000 (+0800) Subject: bug fix: osd: do not cache unused buffer in attrs X-Git-Tag: v9.1.0~250^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c5895d3fad9da0ab7f05f134c49e22795d5c61f3;p=ceph.git bug fix: osd: do not cache unused buffer in attrs attrs only reference the origin bufferlist (decode from MOSDPGPush or ECSubReadReply message) whose size is much greater than attrs in recovery. If obc cache it (get_obc maybe cache the attr), this causes the whole origin bufferlist would not be free until obc is evicted from obc cache. So rebuild the bufferlist before cache it. Fixes: #12565 Signed-off-by: Ning Yao Signed-off-by: Xinze Chi --- diff --git a/src/osd/ECBackend.cc b/src/osd/ECBackend.cc index 47f326efaf17..0899bc86c1c8 100644 --- a/src/osd/ECBackend.cc +++ b/src/osd/ECBackend.cc @@ -372,6 +372,15 @@ void ECBackend::handle_recovery_read_complete( op.xattrs.swap(*attrs); if (!op.obc) { + // attrs only reference the origin bufferlist (decode from ECSubReadReply message) + // whose size is much greater than attrs in recovery. If obc cache it (get_obc maybe + // cache the attr), this causes the whole origin bufferlist would not be free until + // obc is evicted from obc cache. So rebuild the bufferlist before cache it. + for (map::iterator it = op.xattrs.begin(); + it != op.xattrs.end(); + ++it) { + it->second.rebuild(); + } op.obc = get_parent()->get_obc(hoid, op.xattrs); op.recovery_info.size = op.obc->obs.oi.size; op.recovery_info.oi = op.obc->obs.oi; diff --git a/src/osd/ReplicatedBackend.cc b/src/osd/ReplicatedBackend.cc index 5ddc9fd311ef..e1cf238b2b42 100644 --- a/src/osd/ReplicatedBackend.cc +++ b/src/osd/ReplicatedBackend.cc @@ -1811,6 +1811,15 @@ bool ReplicatedBackend::handle_pull_response( bool first = pi.recovery_progress.first; if (first) { + // attrs only reference the origin bufferlist (decode from MOSDPGPush message) + // whose size is much greater than attrs in recovery. If obc cache it (get_obc maybe + // cache the attr), this causes the whole origin bufferlist would not be free until + // obc is evicted from obc cache. So rebuild the bufferlist before cache it. + for (map::iterator it = pop.attrset.begin(); + it != pop.attrset.end(); + ++it) { + it->second.rebuild(); + } pi.obc = get_parent()->get_obc(pi.recovery_info.soid, pop.attrset); pi.recovery_info.oi = pi.obc->obs.oi; pi.recovery_info = recalc_subsets(pi.recovery_info, pi.obc->ssc);