From: Yan, Zheng Date: Wed, 8 Apr 2015 12:16:45 +0000 (+0800) Subject: client: drop inode when rmdir request finishes X-Git-Tag: v9.0.1~108^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F4302%2Fhead;p=ceph.git 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 --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 7cb71a8e52ba..22032a7aa261 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 e3b6bd167cc0..f580b99ab398 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"),