}
// send request.
- //encode_cap_request(request, req);
send_request(request, mds);
// wait for signal
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;
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());
*/
struct InodeCap;
-struct Inode;
+class Inode;
+class Dentry;
struct MetaRequest {
MClientRequest *request; // the actual request to send out
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;
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;
}
//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);