From 7df2cf243b51f33cd4672650e0a21d774d446ecc Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Wed, 8 Apr 2015 20:16:45 +0800 Subject: [PATCH] client: drop inode when rmdir request finishes Current client code relies on cap message to trim unlinked inode from cache. This method is too sensitive to message ordering. If client receives the cap message while directory inode still contains dentries that are referenced by unsafe requests, the inode can't get trimmed. The fix is, when rmdir/rename request finishes, try trimming the unlinked inode again. Fixes: #11339 Signed-off-by: Yan, Zheng --- src/client/Client.cc | 19 +++++++++++++++---- src/client/MetaRequest.h | 3 ++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 7cb71a8e52b..22032a7aa26 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -1558,6 +1558,8 @@ int Client::make_request(MetaRequest *request, MClientReply *reply = request->reply; request->reply = NULL; r = reply->get_result(); + if (r >= 0) + request->success = true; // kick dispatcher (we've got it!) assert(request->dispatch_cond); @@ -1591,9 +1593,18 @@ void Client::put_request(MetaRequest *request) put_inode(request->take_inode()); if (request->old_inode()) put_inode(request->take_old_inode()); - if (request->other_inode()) - put_inode(request->take_other_inode()); + int op = -1; + if (request->success) + op = request->get_op(); + Inode *other_in = request->take_other_inode(); delete request; + + if (other_in) { + if (other_in->dir && + (op == CEPH_MDS_OP_RMDIR || op == CEPH_MDS_OP_RENAME)) + _try_to_trim_inode(other_in); + put_inode(other_in); + } } } @@ -9372,7 +9383,7 @@ int Client::_rmdir(Inode *dir, const char *name, int uid, int gid) req->dentry_drop = CEPH_CAP_FILE_SHARED; req->dentry_unless = CEPH_CAP_FILE_EXCL; - req->inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL; + req->other_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL; Dentry *de; int res = get_or_create(dir, name, &de); @@ -9384,7 +9395,7 @@ int Client::_rmdir(Inode *dir, const char *name, int uid, int gid) goto fail; if (req->get_op() == CEPH_MDS_OP_RMDIR) { req->set_dentry(de); - req->set_inode(in); + req->set_other_inode(in); } else { unlink(de, true, true); } diff --git a/src/client/MetaRequest.h b/src/client/MetaRequest.h index e3b6bd167cc..f580b99ab39 100644 --- a/src/client/MetaRequest.h +++ b/src/client/MetaRequest.h @@ -54,6 +54,7 @@ public: MClientReply *reply; // the reply bool kick; bool aborted; + bool success; // readdir result frag_t readdir_frag; @@ -91,7 +92,7 @@ public: mds(-1), resend_mds(-1), send_to_auth(false), sent_on_mseq(0), num_fwd(0), retry_attempt(0), ref(1), reply(0), - kick(false), aborted(false), + kick(false), aborted(false), success(false), readdir_offset(0), readdir_end(false), readdir_num(0), got_unsafe(false), item(this), unsafe_item(this), lock("MetaRequest lock"),