]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
ceph-fuse: Delete inode's bufferhead was in Tx state would lead a assert fail 21954/head
authorYunfeiGuan <yunfeiguan@xtaotech.com>
Tue, 8 May 2018 11:35:32 +0000 (19:35 +0800)
committerPatrick Donnelly <pdonnell@redhat.com>
Fri, 11 May 2018 22:13:50 +0000 (15:13 -0700)
Prematurely delted the bh which was in Tx state may lead the object can't
be closed before its writer of this bh callback. Thus if inode's ref call
put_inode decrease ref to zero and release inode's oset.An assert fail occur
beacuse the oset can't be emptied.

If gather.has_subs() is true, we can't call flush_set_callback() because
this would cause a double drop of FILE_CACHE | FILE_BUFFER.

Fixes:http://tracker.ceph.com/issues/23837
Signed-off-by: Guan yunfei <yunfei.guan@xtaotech.com>
(cherry picked from commit 07e3bceea78dc8ecd76abb1cafca5c9d1fde521e)

src/client/Client.cc
src/osdc/ObjectCacher.cc

index d87bd1e1bf10c7cf6b01057b2a6dcfbcb84791b0..3c73a1dbe5c9ce58f92c3ac12b4f347426888efa 100644 (file)
@@ -3739,7 +3739,7 @@ void Client::_invalidate_inode_cache(Inode *in, int64_t off, int64_t len)
   if (cct->_conf->client_oc) {
     vector<ObjectExtent> 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);
index 50f9a8d6a6c07de069bcb044606fc2eff1258c51..711e71fc99a04b8940ff89d6d497de68d41c14c4 100644 (file)
@@ -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());
     }
@@ -2489,8 +2490,8 @@ void ObjectCacher::discard_writeback(ObjectSet *oset,
 
   if (gather.has_subs()) {
     gather.set_finisher(new FunctionContext(
-      [this, oset, was_dirty, on_finish](int) {
-        _discard_finish(oset, was_dirty, on_finish);
+      [this, oset, on_finish](int) {
+        _discard_finish(oset, false, on_finish);
       }));
     gather.activate();
     return;