--- /dev/null
+From dcbaa3a99bffe7de65d404d21ae447b33cd49282 Mon Sep 17 00:00:00 2001
+From: Alexey Sheplyakov <asheplyakov@mirantis.com>
+Date: Thu, 21 Jan 2016 09:42:09 +0300
+Subject: [PATCH] PG::activate(): handle unexpected cached_removed_snaps more
+ gracefully
+
+PGPool::update(): ditto
+
+Fixes: #14538
+
+Signed-off-by: Alexey Sheplyakov <asheplyakov@mirantis.com>
+
+(cherry-picked from commit aba6746b850e9397ff25570f08d0af8847a7162c)
+---
+ src/osd/PG.cc | 25 ++++++++++++++++++++++---
+ 1 file changed, 22 insertions(+), 3 deletions(-)
+
+diff --git a/src/osd/PG.cc b/src/osd/PG.cc
+index c6b1d27..c08ad5d 100644
+--- a/src/osd/PG.cc
++++ b/src/osd/PG.cc
+@@ -158,8 +158,18 @@ void PGPool::update(OSDMapRef map)
+ name = map->get_pool_name(id);
+ if (pi->get_snap_epoch() == map->get_epoch()) {
+ pi->build_removed_snaps(newly_removed_snaps);
+- newly_removed_snaps.subtract(cached_removed_snaps);
+- cached_removed_snaps.union_of(newly_removed_snaps);
++ interval_set<snapid_t> intersection;
++ intersection.intersection_of(newly_removed_snaps, cached_removed_snaps);
++ if (intersection == cached_removed_snaps) {
++ newly_removed_snaps.subtract(cached_removed_snaps);
++ cached_removed_snaps.union_of(newly_removed_snaps);
++ } else {
++ lgeneric_subdout(g_ceph_context, osd, 0) << __func__
++ << " cached_removed_snaps shrank from " << cached_removed_snaps
++ << " to " << newly_removed_snaps << dendl;
++ cached_removed_snaps = newly_removed_snaps;
++ newly_removed_snaps.clear();
++ }
+ snapc = pi->get_snap_context();
+ } else {
+ newly_removed_snaps.clear();
+@@ -1550,7 +1560,16 @@ void PG::activate(ObjectStore::Transaction& t,
+ dout(20) << "activate - purged_snaps " << info.purged_snaps
+ << " cached_removed_snaps " << pool.cached_removed_snaps << dendl;
+ snap_trimq = pool.cached_removed_snaps;
+- snap_trimq.subtract(info.purged_snaps);
++ interval_set<snapid_t> intersection;
++ intersection.intersection_of(snap_trimq, info.purged_snaps);
++ if (intersection == info.purged_snaps) {
++ snap_trimq.subtract(info.purged_snaps);
++ } else {
++ dout(0) << "warning: info.purged_snaps (" << info.purged_snaps
++ << ") is not a subset of pool.cached_removed_snaps ("
++ << pool.cached_removed_snaps << ")" << dendl;
++ snap_trimq.subtract(intersection);
++ }
+ dout(10) << "activate - snap_trimq " << snap_trimq << dendl;
+ if (!snap_trimq.empty() && is_clean())
+ queue_snap_trim();
+--
+1.9.1
+