]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: drop inode when rmdir request finishes 4302/head
authorYan, Zheng <zyan@redhat.com>
Wed, 8 Apr 2015 12:16:45 +0000 (20:16 +0800)
committerYan, Zheng <zyan@redhat.com>
Sun, 19 Apr 2015 03:01:08 +0000 (11:01 +0800)
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 <zyan@redhat.com>
src/client/Client.cc
src/client/MetaRequest.h

index 7cb71a8e52ba392240c475df1ebfb2fc7abaeb2c..22032a7aa261ec80e8217fed34b7adb4f2d7e272 100644 (file)
@@ -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);
   }
index e3b6bd167cc0a8c5015c04047b032646f84943c4..f580b99ab3986659bcb7f1e38a2ade8d7f6aab75 100644 (file)
@@ -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"),