<< " " << cap_string(in->caps[mds]->issued)
<< " wants " << cap_string(in->caps_wanted())
<< dendl;
- in->caps[mds]->seq = 0; // reset seq.
- m->add_inode_caps(p->first.ino, // ino
- in->caps_wanted(), // wanted
- in->caps[mds]->issued, // issued
- in->inode.size, in->inode.mtime, in->inode.atime);
filepath path;
in->make_path(path);
dout(10) << " path on " << p->first << " is " << path << dendl;
- m->add_inode_path(p->first.ino, path.get_path());
+
+ in->caps[mds]->seq = 0; // reset seq.
+ m->add_cap(p->first, path.get_path(), // ino
+ in->caps_wanted(), // wanted
+ in->caps[mds]->issued, // issued
+ in->inode.size, in->inode.mtime, in->inode.atime);
}
if (in->exporting_mds == mds) {
dout(10) << " clearing exporting_caps on " << p->first << dendl;
op = CEPH_CAP_OP_RELEASE;
dout(10) << " op = " << op << dendl;
MClientFileCaps *m = new MClientFileCaps(op,
- in->inode,
+ in->inode, in->snapid,
0,
cap->seq,
cap->issued,
struct ceph_mds_file_caps {
__le32 op;
+ __le64 ino;
+ __le64 snapid;
__le32 seq;
__le32 caps, wanted;
- __le64 ino;
__le64 size, max_size;
__le32 migrate_seq;
struct ceph_timespec mtime, atime, ctime;
WRITE_RAW_ENCODER(ceph_mds_lease)
WRITE_RAW_ENCODER(ceph_mds_reply_head)
WRITE_RAW_ENCODER(ceph_mds_reply_inode)
+WRITE_RAW_ENCODER(ceph_mds_cap_reconnect)
WRITE_RAW_ENCODER(ceph_frag_tree_split)
WRITE_RAW_ENCODER(ceph_inopath_item)
operator double() {
return (double)sec() + ((double)usec() / 1000000.0L);
}
+ operator ceph_timespec() {
+ ceph_timespec ts;
+ ts.tv_sec = sec();
+ ts.tv_nsec = nsec();
+ return ts;
+ }
};
WRITE_CLASS_ENCODER(utime_t)
containing_realm = realm;
}
- Capability *reconnect_cap(int client, inode_caps_reconnect_t& icr) {
+ Capability *reconnect_cap(int client, ceph_mds_cap_reconnect& icr) {
Capability *cap = get_client_cap(client);
if (cap) {
cap->merge(icr.wanted, icr.issued);
cap->issue(icr.issued);
}
inode.size = MAX(inode.size, icr.size);
- inode.mtime = MAX(inode.mtime, icr.mtime);
- inode.atime = MAX(inode.atime, icr.atime);
+ inode.mtime = MAX(inode.mtime, utime_t(icr.mtime));
+ inode.atime = MAX(inode.atime, utime_t(icr.atime));
return cap;
}
void clear_client_caps() {
<< " new pending " << cap_string(cap->pending()) << " was " << cap_string(before)
<< dendl;
mds->send_message_client(new MClientFileCaps(CEPH_CAP_OP_GRANT,
- in->inode,
+ in->inode, in->last,
in->find_snaprealm()->inode->ino(),
cap->get_last_seq(),
cap->pending(),
it++) {
Capability *cap = it->second;
mds->send_message_client(new MClientFileCaps(CEPH_CAP_OP_TRUNC,
- in->inode,
+ in->inode, in->last,
in->find_snaprealm()->inode->ino(),
cap->get_last_seq(),
cap->pending(),
if (cap->pending() & CEPH_CAP_WR) {
dout(10) << "share_inode_max_size with client" << client << dendl;
mds->send_message_client(new MClientFileCaps(CEPH_CAP_OP_GRANT,
- in->inode,
+ in->inode, in->last,
in->find_snaprealm()->inode->ino(),
cap->get_last_seq(),
cap->pending(),
ack = new MMDSCacheRejoin(MMDSCacheRejoin::OP_ACK);
// check cap exports
- for (map<inodeno_t,map<int,inode_caps_reconnect_t> >::iterator p = weak->cap_exports.begin();
+ for (map<vinodeno_t,map<int,ceph_mds_cap_reconnect> >::iterator p = weak->cap_exports.begin();
p != weak->cap_exports.end();
++p) {
CInode *in = get_inode(p->first);
if (!in || !in->is_auth()) continue;
- for (map<int,inode_caps_reconnect_t>::iterator q = p->second.begin();
+ for (map<int,ceph_mds_cap_reconnect>::iterator q = p->second.begin();
q != p->second.end();
++q) {
dout(10) << " claiming cap import " << p->first << " client" << q->first << " on " << *in << dendl;
assert(mds->is_rejoin());
// check cap exports.
- for (map<inodeno_t,map<int,inode_caps_reconnect_t> >::iterator p = weak->cap_exports.begin();
+ for (map<vinodeno_t,map<int,ceph_mds_cap_reconnect> >::iterator p = weak->cap_exports.begin();
p != weak->cap_exports.end();
++p) {
CInode *in = get_inode(p->first);
if (in && !in->is_auth()) continue;
+ string& path = weak->cap_export_paths[p->first];
if (!in) {
- if (!path_is_mine(weak->cap_export_paths[p->first]))
+ if (!path_is_mine(path))
continue;
- cap_import_paths[p->first] = weak->cap_export_paths[p->first];
- dout(10) << " noting cap import " << p->first << " path " << weak->cap_export_paths[p->first] << dendl;
+ cap_import_paths[p->first] = path;
+ dout(10) << " noting cap import " << p->first << " path " << path << dendl;
}
// note
- for (map<int,inode_caps_reconnect_t>::iterator q = p->second.begin();
+ for (map<int,ceph_mds_cap_reconnect>::iterator q = p->second.begin();
q != p->second.end();
++q) {
dout(10) << " claiming cap import " << p->first << " client" << q->first << dendl;
* returns a C_Gather* is there is work to do. caller is responsible for setting
* the C_Gather completer.
*/
-C_Gather *MDCache::parallel_fetch(map<inodeno_t,string>& pathmap)
+C_Gather *MDCache::parallel_fetch(map<vinodeno_t,string>& pathmap)
{
dout(10) << "parallel_fetch on " << pathmap.size() << " paths" << dendl;
// scan list
set<CDir*> fetch_queue;
- map<inodeno_t,string>::iterator p = pathmap.begin();
+ map<vinodeno_t,string>::iterator p = pathmap.begin();
while (p != pathmap.end()) {
CInode *in = get_inode(p->first);
if (in) {
// process cap imports
// ino -> client -> frommds -> capex
- for (map<inodeno_t,map<int, map<int,inode_caps_reconnect_t> > >::iterator p = cap_imports.begin();
+ for (map<vinodeno_t,map<int, map<int,ceph_mds_cap_reconnect> > >::iterator p = cap_imports.begin();
p != cap_imports.end();
++p) {
CInode *in = get_inode(p->first);
assert(in);
mds->server->add_reconnected_cap_inode(in);
- for (map<int, map<int,inode_caps_reconnect_t> >::iterator q = p->second.begin();
+ for (map<int, map<int,ceph_mds_cap_reconnect> >::iterator q = p->second.begin();
q != p->second.end();
++q)
- for (map<int,inode_caps_reconnect_t>::iterator r = q->second.begin();
+ for (map<int,ceph_mds_cap_reconnect>::iterator r = q->second.begin();
r != q->second.end();
++r)
if (r->first >= 0)
mds->rejoin_done();
}
-void MDCache::rejoin_import_cap(CInode *in, int client, inode_caps_reconnect_t& icr, int frommds)
+void MDCache::rejoin_import_cap(CInode *in, int client, ceph_mds_cap_reconnect& icr, int frommds)
{
dout(10) << "rejoin_import_cap for client" << client << " from mds" << frommds
<< " on " << *in << dendl;
// send IMPORT
SnapRealm *realm = in->find_snaprealm();
MClientFileCaps *reap = new MClientFileCaps(CEPH_CAP_OP_IMPORT,
- in->inode,
+ in->inode, in->last,
realm->inode->ino(),
cap->get_last_seq(),
cap->pending(),
set<int> rejoin_sent; // nodes i sent a rejoin to
set<int> rejoin_ack_gather; // nodes from whom i need a rejoin ack
- map<inodeno_t,map<int,inode_caps_reconnect_t> > cap_exports; // ino -> client -> capex
- map<inodeno_t,string> cap_export_paths;
+ map<vinodeno_t,map<int,ceph_mds_cap_reconnect> > cap_exports; // ino -> client -> capex
+ map<vinodeno_t,string> cap_export_paths;
- map<inodeno_t,map<int, map<int,inode_caps_reconnect_t> > > cap_imports; // ino -> client -> frommds -> capex
- map<inodeno_t,string> cap_import_paths;
+ map<vinodeno_t,map<int,map<int,ceph_mds_cap_reconnect> > > cap_imports; // ino -> client -> frommds -> capex
+ map<vinodeno_t,string> cap_import_paths;
set<CInode*> rejoin_undef_inodes;
set<CInode*> rejoin_potential_updated_scatterlocks;
public:
void rejoin_gather_finish();
void rejoin_send_rejoins();
- void rejoin_export_caps(inodeno_t ino, string& path, int client, inode_caps_reconnect_t& icr) {
- cap_exports[ino][client] = icr;
- cap_export_paths[ino] = path;
+ void rejoin_export_caps(vinodeno_t vino, int client, cap_reconnect_t& icr) {
+ cap_exports[vino][client] = icr.capinfo;
+ cap_export_paths[vino] = icr.path;
}
- void rejoin_recovered_caps(inodeno_t ino, string& path, int client, inode_caps_reconnect_t& icr,
+ void rejoin_recovered_caps(vinodeno_t vino, int client, cap_reconnect_t& icr,
int frommds=-1) {
- cap_imports[ino][client][frommds] = icr;
- cap_import_paths[ino] = path;
+ cap_imports[vino][client][frommds] = icr.capinfo;
+ cap_import_paths[vino] = icr.path;
}
- void rejoin_import_cap(CInode *in, int client, inode_caps_reconnect_t& icr, int frommds);
+ void rejoin_import_cap(CInode *in, int client, ceph_mds_cap_reconnect& icr, int frommds);
friend class Locker;
vector<Anchor>& anchortrace,
Context *onfinish);
- C_Gather *parallel_fetch(map<inodeno_t,string>& pathmap);
+ C_Gather *parallel_fetch(map<vinodeno_t,string>& pathmap);
void make_trace(vector<CDentry*>& trace, CInode *in);
dout(7) << "finish_export_inode telling client" << it->first
<< " exported caps on " << *in << dendl;
MClientFileCaps *m = new MClientFileCaps(CEPH_CAP_OP_EXPORT,
- in->inode,
+ in->inode, in->last,
in->find_snaprealm()->inode->ino(),
cap->get_last_seq(),
cap->pending(),
SnapRealm *realm = in->find_snaprealm();
MClientFileCaps *caps = new MClientFileCaps(CEPH_CAP_OP_IMPORT,
- in->inode,
+ in->inode, in->last,
realm->inode->ino(),
cap->get_last_seq(),
cap->pending(),
} else {
// caps
- for (map<inodeno_t, inode_caps_reconnect_t>::iterator p = m->inode_caps.begin();
- p != m->inode_caps.end();
+ for (map<vinodeno_t, cap_reconnect_t>::iterator p = m->caps.begin();
+ p != m->caps.end();
++p) {
CInode *in = mdcache->get_inode(p->first);
if (in && in->is_auth()) {
// we recovered it, and it's ours. take note.
dout(15) << "open caps on " << *in << dendl;
- Capability *cap = in->reconnect_cap(from, p->second);
+ Capability *cap = in->reconnect_cap(from, p->second.capinfo);
session->touch_cap(cap);
reconnected_caps.insert(in);
continue;
}
- filepath path = m->inode_path[p->first];
+ filepath path = p->second.path;
if ((in && !in->is_auth()) ||
!mds->mdcache->path_is_mine(path)) {
// not mine.
- dout(0) << "non-auth " << p->first << " " << m->inode_path[p->first]
+ dout(0) << "non-auth " << p->first << " " << path
<< ", will pass off to authority" << dendl;
// mark client caps stale.
inode_t fake_inode;
memset(&fake_inode, 0, sizeof(fake_inode));
- fake_inode.ino = p->first;
+ fake_inode.ino = p->first.ino;
MClientFileCaps *stale = new MClientFileCaps(CEPH_CAP_OP_EXPORT,
- fake_inode,
+ fake_inode, p->first.snapid,
0,
0,
0, // doesn't matter.
- p->second.wanted, // doesn't matter.
+ p->second.capinfo.wanted, // doesn't matter.
0); // FIXME get proper mseq here? hmm.
mds->send_message_client(stale, m->get_source_inst());
// add to cap export list.
- mdcache->rejoin_export_caps(p->first, m->inode_path[p->first], from, p->second);
+ mdcache->rejoin_export_caps(p->first, from, p->second);
} else {
// mine. fetch later.
- dout(0) << "missing " << p->first << " " << m->inode_path[p->first]
+ dout(0) << "missing " << p->first << " " << path
<< " (mine), will load later" << dendl;
- mdcache->rejoin_recovered_caps(p->first, m->inode_path[p->first], from, p->second,
+ mdcache->rejoin_recovered_caps(p->first, from, p->second,
-1); // "from" me.
}
}
}
-// inode caps info for client reconnect
-struct inode_caps_reconnect_t {
- int32_t wanted;
- int32_t issued;
- uint64_t size;
- utime_t mtime, atime;
-
- inode_caps_reconnect_t() {}
- inode_caps_reconnect_t(int w, int i) :
- wanted(w), issued(i), size(0) {}
- inode_caps_reconnect_t(int w, int i, uint64_t sz, utime_t mt, utime_t at) :
- wanted(w), issued(i), size(sz), mtime(mt), atime(at) {}
-};
+// cap info for client reconnect
+struct cap_reconnect_t {
+ string path;
+ ceph_mds_cap_reconnect capinfo;
+
+ cap_reconnect_t() {}
+ cap_reconnect_t(const string& p, int w, int i, uint64_t sz, utime_t mt, utime_t at) :
+ path(p) {
+ capinfo.wanted = w;
+ capinfo.issued = i;
+ capinfo.size = sz;
+ capinfo.mtime = mt;
+ capinfo.atime = at;
+ }
-static inline void encode(const inode_caps_reconnect_t &ic, bufferlist &bl)
-{
- ::encode(ic.wanted, bl);
- ::encode(ic.issued, bl);
- ::encode(ic.size, bl);
- ::encode(ic.mtime, bl);
- ::encode(ic.atime, bl);
-}
-static inline void decode(inode_caps_reconnect_t &ic, bufferlist::iterator &p)
-{
- ::decode(ic.wanted, p);
- ::decode(ic.issued, p);
- ::decode(ic.size, p);
- ::decode(ic.mtime, p);
- ::decode(ic.atime, p);
-}
+ void encode(bufferlist& bl) const {
+ ::encode(path, bl);
+ ::encode(capinfo, bl);
+ }
+ void decode(bufferlist::iterator& bl) {
+ ::decode(path, bl);
+ ::decode(capinfo, bl);
+ }
+};
+WRITE_CLASS_ENCODER(cap_reconnect_t)
// ================================================================
capseq_t get_mseq() { return h.migrate_seq; }
inodeno_t get_ino() { return inodeno_t(h.ino); }
+ snapid_t get_snapid() { return snapid_t(h.snapid); }
+
__u64 get_size() { return h.size; }
__u64 get_max_size() { return h.max_size; }
utime_t get_ctime() { return utime_t(h.ctime); }
MClientFileCaps() {}
MClientFileCaps(int op,
inode_t& inode,
+ snapid_t snapid,
inodeno_t realm,
long seq,
int caps,
int mseq) :
Message(CEPH_MSG_CLIENT_FILECAPS) {
h.op = op;
+ h.ino = inode.ino;
+ h.snapid = snapid;
h.seq = seq;
h.caps = caps;
h.wanted = wanted;
- h.ino = inode.ino;
h.size = inode.size;
h.max_size = inode.max_size;
h.migrate_seq = mseq;
class MClientReconnect : public Message {
public:
- map<inodeno_t, inode_caps_reconnect_t> inode_caps;
- map<inodeno_t, string> inode_path;
+ map<vinodeno_t, cap_reconnect_t> caps;
__u8 closed; // true if this session was closed by the client.
MClientReconnect() : Message(CEPH_MSG_CLIENT_RECONNECT),
const char *get_type_name() { return "client_reconnect"; }
void print(ostream& out) {
- out << "client_reconnect(" << inode_caps.size() << " caps)";
+ out << "client_reconnect("
+ << (closed ? "closed":"")
+ << caps.size() << " caps)";
}
- void add_inode_caps(inodeno_t ino,
- int wanted, int issued,
- loff_t sz, utime_t mt, utime_t at) {
- inode_caps[ino] = inode_caps_reconnect_t(wanted, issued, sz, mt, at);
- }
- void add_inode_path(inodeno_t ino, const string& path) {
- inode_path[ino] = path;
+ void add_cap(vinodeno_t ino, const string& path,
+ int wanted, int issued,
+ loff_t sz, utime_t mt, utime_t at) {
+ caps[ino] = cap_reconnect_t(path, wanted, issued, sz, mt, at);
}
void encode_payload() {
- __u32 n = inode_caps.size();
::encode(closed, payload);
- ::encode(n, payload);
- for (map<inodeno_t, inode_caps_reconnect_t>::iterator p = inode_caps.begin();
- p != inode_caps.end();
- p++) {
- ::encode(p->first, payload);
- ::encode(p->second, payload);
- ::encode(inode_path[p->first], payload);
- }
+ ::encode(caps, payload);
}
void decode_payload() {
bufferlist::iterator p = payload.begin();
::decode(closed, p);
- __u32 n;
- ::decode(n, p);
- while (n--) {
- inodeno_t ino;
- ::decode(ino, p);
- ::decode(inode_caps[ino], p);
- ::decode(inode_path[ino], p);
- }
+ ::decode(caps, p);
}
};
// open
bufferlist cap_export_bl;
- map<inodeno_t,map<__s32, inode_caps_reconnect_t> > cap_exports;
- map<inodeno_t,string> cap_export_paths;
+ map<vinodeno_t,map<__s32, ceph_mds_cap_reconnect> > cap_exports;
+ map<vinodeno_t,string> cap_export_paths;
// full
bufferlist inode_base;