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: v0.94.6~65^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F6499%2Fhead;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 (cherry picked from commit c5895d3fad9da0ab7f05f134c49e22795d5c61f3) --- diff --git a/src/osd/ECBackend.cc b/src/osd/ECBackend.cc index 845ea832eeb8..3b517402bcef 100644 --- a/src/osd/ECBackend.cc +++ b/src/osd/ECBackend.cc @@ -366,6 +366,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 b86d4d1e7444..7dab73c86ecf 100644 --- a/src/osd/ReplicatedBackend.cc +++ b/src/osd/ReplicatedBackend.cc @@ -1802,6 +1802,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);