From: Yan, Zheng Date: Mon, 13 Oct 2014 03:34:18 +0000 (+0800) Subject: client: use finisher to abort MDS request X-Git-Tag: v0.80.9~7^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f9b6b66b05ddadef043d81676728bf40730ea16c;p=ceph.git client: use finisher to abort MDS request 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 (cherry picked from commit 09699454e729592d426aeff5b578697e850af12e) Conflicts: src/client/Client.cc src/client/Client.h Signed-off-by: Greg Farnum --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 216e5819266..6f572250955 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -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(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)); } // ========================================= diff --git a/src/client/Client.h b/src/client/Client.h index f102892b679..8e1741dc7c6 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -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); }