From 0c7699ce54507ffa62c56433b2d0a661983e3077 Mon Sep 17 00:00:00 2001 From: YunfeiGuan Date: Tue, 8 May 2018 19:35:32 +0800 Subject: [PATCH] client: avoid freeing inode when it contains TX buffer heads ObjectCacher::discard_set() prematurely delete TX buffer heads. But the pending writebacks still pin parent objects of these buffer heads. Assertion "oset.objects.empty()" gets triggered if inode with pending writebacks get freed. Fixes: http://tracker.ceph.com/issues/23837 Signed-off-by: Guan yunfei Signed-off-by: "Yan, Zheng" (cherry picked from commit 8a03757ca0ab493c6c2ea4fa4307e053e8ebc944) --- src/client/Client.cc | 2 +- src/osdc/ObjectCacher.cc | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index d87bd1e1bf10c..3c73a1dbe5c9c 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -3739,7 +3739,7 @@ void Client::_invalidate_inode_cache(Inode *in, int64_t off, int64_t len) if (cct->_conf->client_oc) { vector ls; Striper::file_to_extents(cct, in->ino, &in->layout, off, len, in->truncate_size, ls); - objectcacher->discard_set(&in->oset, ls); + objectcacher->discard_writeback(&in->oset, ls, nullptr); } _schedule_invalidate_callback(in, off, len); diff --git a/src/osdc/ObjectCacher.cc b/src/osdc/ObjectCacher.cc index 50f9a8d6a6c07..4b658408ab2cf 100644 --- a/src/osdc/ObjectCacher.cc +++ b/src/osdc/ObjectCacher.cc @@ -609,7 +609,8 @@ void ObjectCacher::Object::discard(loff_t off, loff_t len, bh->bl.clear(); bh->set_nocache(true); oc->mark_zero(bh); - return; + // we should mark all Rx bh to zero + continue; } else { assert(bh->waitfor_read.empty()); } @@ -2488,9 +2489,14 @@ void ObjectCacher::discard_writeback(ObjectSet *oset, _discard(oset, exls, &gather); if (gather.has_subs()) { + bool flushed = was_dirty && oset->dirty_or_tx == 0; gather.set_finisher(new FunctionContext( - [this, oset, was_dirty, on_finish](int) { - _discard_finish(oset, was_dirty, on_finish); + [this, oset, flushed, on_finish](int) { + assert(lock.is_locked()); + if (flushed && flush_set_callback) + flush_set_callback(flush_set_callback_arg, oset); + if (on_finish) + on_finish->complete(0); })); gather.activate(); return; -- 2.39.5