]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
uclient: Add functions/data members for preemptive cap dropping.
authorGreg Farnum <gregf@hq.newdream.net>
Fri, 18 Sep 2009 00:22:42 +0000 (17:22 -0700)
committerGreg Farnum <gregf@hq.newdream.net>
Fri, 18 Sep 2009 01:29:24 +0000 (18:29 -0700)
src/client/Client.cc
src/client/Client.h

index b1543ddb61f4d7a76b1114b25f94acecfd041df2..0b180aae890515becdcad9d0190549e3fe5539d1 100644 (file)
@@ -852,7 +852,6 @@ int Client::make_request(MetaRequest *request,
     }
 
     // send request.
-    //encode_cap_request(request, req);
     send_request(request, mds);
 
     // wait for signal
@@ -909,47 +908,78 @@ inline MClientRequest* Client::make_request_from_Meta(MetaRequest *request)
   return req;
 }
 
-/*This won't do anything if the MetaRequest doesn't have set:
- *MClientRequest *request
- *Inode *source
- *int caps_dropped
+int Client::encode_inode_release(Inode *in, MClientRequest *req,
+                        int mds, int drop,
+                        int unless, int force)
+{
+  int released = 0;
+  InodeCap *caps = in->caps[mds];
+  if (drop & caps->issued &&
+      !(unless & caps->issued)) {
+    caps->issued &= ~drop;
+    caps->implemented &= ~drop;
+    released = 1;
+    force = 1;
+  }
+  if (force) {
+    ceph_mds_request_release rel;
+    rel.ino = in->ino;
+    rel.cap_id = caps->cap_id;
+    rel.seq = caps->seq;
+    rel.issue_seq = caps->issue_seq;
+    rel.mseq = caps->mseq;
+    rel.caps = caps->issued;
+    rel.wanted = caps->wanted;
+    rel.dname_len = 0;
+    rel.dname_seq = 0;
+    req->releases.push_back(MClientRequest::Release(rel,""));
+  }
+  return released;
+}
+
+void Client::encode_dentry_release(Dentry *dn, MClientRequest *req,
+                          int mds, int drop, int unless)
+{
+  int released = encode_inode_release(dn->dir->parent_inode, req,
+                                     mds, drop, unless, 1);
+  if (released && dn->lease_mds == mds) {
+    MClientRequest::Release& rel = req->releases.back();
+    rel.item.dname_len = dn->name.length();
+    rel.item.dname_seq = dn->lease_seq;
+    rel.dname = dn->name;
+  }
+}
+
+
+/*
+ * This requires the MClientRequest *request member to be set.
+ * It will error out horribly without one.
+ * Additionally, if you set any *drop member, you'd better have
+ * set the corresponding dentry!
  */
-void Client::encode_cap_release(MetaRequest *req, int mds) {
-  Inode *in;
-  int caps;
-  if (!req->source) goto invalid_exit;
-  in = req->source;
-  caps = in->caps_issued();
-  dout(20) << "encode_cap_release " << req->caps_dropped << " unless "
-          << in << " has " << req->unless_have_caps
-          << ". Inode caps are " << caps << dendl;
-  if ( req->request &&                   //we need a request to bundle with
-       req->caps_dropped &&              //and caps to drop
-       (caps & req->caps_dropped) &&     //and to have some of those caps
-       !(caps & req->unless_have_caps) ) {//and to not have the 'saving' caps
-    InodeCap *icap = in->caps[mds];
-    //encode message to drop the caps
-    ceph_mds_request_release release;
-    icap->issued &= ~req->caps_dropped;
-    icap->implemented &= ~req->caps_dropped;
-    release.ino = in->ino;
-    release.cap_id = icap->cap_id;
-    release.caps = icap->issued;
-    release.wanted = icap->wanted;
-    release.seq = icap->seq;
-    release.issue_seq = icap->issue_seq;
-    release.mseq = icap->mseq;
-    release.dname_seq = 0;
-    release.dname_len = 0;
-    dout(20) << "encode_cap_release quitting after encoding drop of "
-            << req->caps_dropped << " from inode " << in << dendl;
-    goto clean_exit;
-  }
- invalid_exit:
-  dout(20) << "encode_cap_release is quitting because we don't need to drop!" << dendl;
- clean_exit: ;
+void Client::encode_cap_releases(MetaRequest *req, int mds) {
+  if (req->inode_drop)
+    encode_inode_release(req->inode, req->request,
+                        mds, req->inode_drop,
+                        req->inode_unless);
+
+  if (req->old_inode_drop)
+    encode_inode_release(req->old_inode, req->request,
+                        mds, req->old_inode_drop,
+                        req->old_inode_unless);
+
+  if (req->dentry_drop)
+    encode_dentry_release(req->dentry, req->request,
+                         mds, req->dentry_drop,
+                         req->dentry_unless);
+  
+  if (req->old_dentry_drop)
+    encode_dentry_release(req->old_dentry, req->request,
+                         mds, req->old_dentry_drop,
+                         req->old_dentry_unless);
 }
 
+
 void Client::handle_client_session(MClientSession *m) 
 {
   dout(10) << "handle_client_session " << *m << dendl;
@@ -1008,9 +1038,12 @@ void Client::send_request(MetaRequest *request, int mds)
     r->set_dentry_wanted();
     if (request->got_unsafe)
       r->set_replayed_op();
+    request->request = r;
   }
   else
     request->retry_attempt++;
+  if (!r->releases.size())
+    encode_cap_releases(request, mds);
   request->request = 0;
 
   r->set_mdsmap_epoch(mdsmap->get_epoch());
index 4b0364a56bb361a6c849f0a6e2e7cbcf3eb4116e..ef4b9128457d2b03753b988e3337ac4c1f999e81 100644 (file)
@@ -90,7 +90,8 @@ extern class Logger  *client_logger;
  
 */
 struct InodeCap;
-struct Inode;
+class Inode;
+class Dentry;
 
 struct MetaRequest {
   MClientRequest *request;    // the actual request to send out
@@ -98,8 +99,15 @@ struct MetaRequest {
   ceph_mds_request_head head;
   filepath path, path2;
   bufferlist data;
-  int caps_dropped; //the caps this operation will drop
-  int unless_have_caps; //unless we have these caps already
+  int inode_drop; //the inode caps this operation will drop
+  int inode_unless; //unless we have these caps already
+  int old_inode_drop, old_inode_unless;
+  int dentry_drop, dentry_unless;
+  int old_dentry_drop, old_dentry_unless;
+  Inode *inode;
+  Inode *old_inode;
+  Dentry *dentry; //associated with path
+  Dentry *old_dentry; //associated with path2
 
  
   utime_t  sent_stamp;
@@ -122,28 +130,37 @@ struct MetaRequest {
   Cond  *caller_cond;          // who to take up
   Cond  *dispatch_cond;        // who to kick back
 
-  Inode *source; //Inode being affected -- useful for cap references
   Inode *target;
 
   MetaRequest(MClientRequest *req, tid_t t) : 
-    request(req), caps_dropped(0), unless_have_caps(0),
+    request(req), inode_drop(0), inode_unless(0),
+    old_inode_drop(0), old_inode_unless(0),
+    dentry_drop(0), dentry_unless(0),
+    old_dentry_drop(0), old_dentry_unless(0),
+    inode(NULL), old_inode(NULL),
+    dentry(NULL), old_dentry(NULL),
     resend_mds(-1), num_fwd(0), retry_attempt(0),
     ref(1), reply(0), 
     kick(false), got_safe(false), got_unsafe(false), unsafe_item(this),
     lock("MetaRequest lock"),
     caller_cond(0), dispatch_cond(0),
-    source(0), target(0) {
+    target(0) {
     memcpy(&head, &req->head, sizeof(ceph_mds_request_head));
   }
 
   MetaRequest(int op) : 
-    request(NULL), caps_dropped(0), unless_have_caps(0),
+    request(NULL), inode_drop(0), inode_unless(0),
+    old_inode_drop(0), old_inode_unless(0),
+    dentry_drop(0), dentry_unless(0),
+    old_dentry_drop(0), old_dentry_unless(0),
+    inode(NULL), old_inode(NULL),
+    dentry(NULL), old_dentry(NULL),
     resend_mds(-1), num_fwd(0), retry_attempt(0),
     ref(1), reply(0), 
     kick(false), got_safe(false), got_unsafe(false), unsafe_item(this),
     lock("MetaRequest lock"),
     caller_cond(0), dispatch_cond(0),
-    source(0), target(0) {
+    target(0) {
     memset(&head, 0, sizeof(ceph_mds_request_head));
     head.op = op;
 }
@@ -820,7 +837,12 @@ public:
                   //MClientRequest *req, int uid, int gid,
                   Inode **ptarget = 0,
                   int use_mds=-1, bufferlist *pdirbl=0);
-  void encode_cap_release(MetaRequest *request, int mds);
+  void encode_cap_releases(MetaRequest *request, int mds);
+  int encode_inode_release(Inode *in, MClientRequest *req,
+                          int mds, int drop,
+                          int unless,int force=0);
+  void encode_dentry_release(Dentry *dn, MClientRequest *req,
+                            int mds, int drop, int unless);
   int choose_target_mds(MClientRequest *req);
   void send_request(MetaRequest *request, int mds);
   void kick_requests(int mds, bool signal);