From 9643ee65a6e968e479ca33a102f5f575924a7ff0 Mon Sep 17 00:00:00 2001 From: Xinze Chi Date: Sun, 2 Aug 2015 18:36:40 +0800 Subject: [PATCH] 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) --- src/osd/ECBackend.cc | 9 +++++++++ src/osd/ReplicatedBackend.cc | 9 +++++++++ 2 files changed, 18 insertions(+) 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); -- 2.47.3