]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: use finisher to abort MDS request
authorYan, Zheng <zyan@redhat.com>
Mon, 13 Oct 2014 03:34:18 +0000 (11:34 +0800)
committerGreg Farnum <gfarnum@redhat.com>
Fri, 13 Feb 2015 22:41:09 +0000 (14:41 -0800)
When a request is interrupted, libfuse first locks an internal mutex,
then calls the interrupt callback. libfuse need to lock the same mutex
when unregistering interrupt callback. We unregister interrupt callback
while client_lock is locked, so we can't acquiring the client_lock in
the interrupt callback.

Signed-off-by: Yan, Zheng <zyan@redhat.com>
(cherry picked from commit 09699454e729592d426aeff5b578697e850af12e)

Conflicts:
src/client/Client.cc
src/client/Client.h

Signed-off-by: Greg Farnum <gfarnum@redhat.com>
src/client/Client.cc
src/client/Client.h

index 216e58192666ed8f61b6accbe54391593f6aea47..6f5722509557454849d143602001f37c2df5a6c4 100644 (file)
@@ -158,6 +158,7 @@ Client::Client(Messenger *m, MonClient *mc)
     getgroups_cb_handle(NULL),
     async_ino_invalidator(m->cct),
     async_dentry_invalidator(m->cct),
+    interrupt_finisher(m->cct),
     tick_event(NULL),
     monclient(mc), messenger(m), whoami(m->get_myname().num()),
     initialized(false), mounted(false), unmounting(false),
@@ -444,6 +445,12 @@ void Client::shutdown()
     async_dentry_invalidator.stop();
   }
 
+  if (switch_interrupt_cb) {
+    ldout(cct, 10) << "shutdown stopping interrupt finisher" << dendl;
+    interrupt_finisher.wait_for_empty();
+    interrupt_finisher.stop();
+  }
+
   objectcacher->stop();  // outside of client_lock! this does a join.
 
   client_lock.Lock();
@@ -7188,6 +7195,7 @@ void Client::ll_register_switch_interrupt_cb(client_switch_interrupt_callback_t
   if (cb == NULL)
     return;
   switch_interrupt_cb = cb;
+  interrupt_finisher.start();
 }
 
 void Client::ll_register_getgroups_cb(client_getgroups_callback_t cb, void *handle)
@@ -9072,16 +9080,28 @@ int Client::ll_flock(Fh *fh, int cmd, uint64_t owner, void *fuse_req)
   return _flock(fh, cmd, owner, fuse_req);
 }
 
+class C_Client_RequestInterrupt : public Context  {
+private:
+  Client *client;
+  MetaRequest *req;
+public:
+  C_Client_RequestInterrupt(Client *c, MetaRequest *r) : client(c), req(r) {
+    req->get();
+  }
+  void finish(int r) {
+    Mutex::Locker l(client->client_lock);
+    assert(req->head.op == CEPH_MDS_OP_SETFILELOCK);
+    client->_interrupt_filelock(req);
+    client->put_request(req);
+  }
+};
+
 void Client::ll_interrupt(void *d)
 {
-  Mutex::Locker lock(client_lock);
-
   MetaRequest *req = static_cast<MetaRequest*>(d);
   ldout(cct, 3) << "ll_interrupt tid " << req->get_tid() << dendl;
   tout(cct) << "ll_interrupt tid " << req->get_tid() << std::endl;
-
-  assert(req->head.op == CEPH_MDS_OP_SETFILELOCK);
-  _interrupt_filelock(req);
+  interrupt_finisher.queue(new C_Client_RequestInterrupt(this, req));
 }
 
 // =========================================
index f102892b679b87be1f67c77179db7b8732b9cf98..8e1741dc7c6531f576d44e4134aac84beb966f8b 100644 (file)
@@ -229,6 +229,7 @@ class Client : public Dispatcher {
 
   Finisher async_ino_invalidator;
   Finisher async_dentry_invalidator;
+  Finisher interrupt_finisher;
 
   Context *tick_event;
   utime_t last_cap_renew;
@@ -378,6 +379,7 @@ protected:
   friend class C_Client_CacheInvalidate;  // calls ino_invalidate_cb
   friend class C_Client_DentryInvalidate;  // calls dentry_invalidate_cb
   friend class C_Block_Sync; // Calls block map and protected helpers
+  friend class C_Client_RequestInterrupt;
 
   //int get_cache_size() { return lru.lru_get_size(); }
   //void set_cache_size(int m) { lru.lru_set_max(m); }