From: Greg Farnum Date: Fri, 18 Sep 2009 00:22:42 +0000 (-0700) Subject: uclient: Add functions/data members for preemptive cap dropping. X-Git-Tag: v0.15~34 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=9843d1fdd4c7e807ee3a77f8f7417ebb28272e47;p=ceph.git uclient: Add functions/data members for preemptive cap dropping. --- diff --git a/src/client/Client.cc b/src/client/Client.cc index b1543ddb61f..0b180aae890 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -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()); diff --git a/src/client/Client.h b/src/client/Client.h index 4b0364a56bb..ef4b9128457 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -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);