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 <zay11022@gmail.com>
Signed-off-by: Xinze Chi <xmdxcxz@gmail.com>
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<string, bufferlist>::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;
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<string, bufferlist>::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);