struct ceph_timespec mtime, atime;
__le64 snaprealm;
__le64 pathbase; /* base ino for our path to this ino */
+ __le32 flock_len; /* size of flock state blob, if any */
+} __attribute__ ((packed));
+/* followed by flock blob */
+
+struct ceph_mds_cap_reconnect_v1 {
+ __le64 cap_id;
+ __le32 wanted;
+ __le32 issued;
+ __le64 size;
+ struct ceph_timespec mtime, atime;
+ __le64 snaprealm;
+ __le64 pathbase; /* base ino for our path to this ino */
} __attribute__ ((packed));
-/* followed by encoded string */
struct ceph_mds_snaprealm_reconnect {
__le64 ino; /* snap realm base */
// cap info for client reconnect
struct cap_reconnect_t {
string path;
- ceph_mds_cap_reconnect capinfo;
+ mutable ceph_mds_cap_reconnect capinfo;
+ bufferlist flockbl;
cap_reconnect_t() {}
cap_reconnect_t(uint64_t cap_id, inodeno_t pino, const string& p, int w, int i, inodeno_t sr) :
void encode(bufferlist& bl) const {
::encode(path, bl);
+ capinfo.flock_len = flockbl.length();
::encode(capinfo, bl);
+ ::encode_nohead(flockbl, bl);
}
void decode(bufferlist::iterator& bl) {
::decode(path, bl);
::decode(capinfo, bl);
+ ::decode_nohead(capinfo.flock_len, flockbl, bl);
}
};
WRITE_CLASS_ENCODER(cap_reconnect_t)
+// compat for pre-FLOCK feature
+struct old_ceph_mds_cap_reconnect {
+ __le64 cap_id;
+ __le32 wanted;
+ __le32 issued;
+ __le64 old_size;
+ struct ceph_timespec old_mtime, old_atime;
+ __le64 snaprealm;
+ __le64 pathbase; /* base ino for our path to this ino */
+} __attribute__ ((packed));
+WRITE_RAW_ENCODER(old_ceph_mds_cap_reconnect)
+
+struct old_cap_reconnect_t {
+ string path;
+ old_ceph_mds_cap_reconnect capinfo;
+
+ const old_cap_reconnect_t& operator=(const cap_reconnect_t& n) {
+ path = n.path;
+ capinfo.cap_id = n.capinfo.cap_id;
+ capinfo.wanted = n.capinfo.wanted;
+ capinfo.issued = n.capinfo.issued;
+ capinfo.snaprealm = n.capinfo.snaprealm;
+ capinfo.pathbase = n.capinfo.pathbase;
+ return *this;
+ }
+ operator cap_reconnect_t() {
+ cap_reconnect_t n;
+ n.path = path;
+ n.capinfo.cap_id = capinfo.cap_id;
+ n.capinfo.wanted = capinfo.wanted;
+ n.capinfo.issued = capinfo.issued;
+ n.capinfo.snaprealm = capinfo.snaprealm;
+ n.capinfo.pathbase = capinfo.pathbase;
+ return n;
+ }
+
+ 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(old_cap_reconnect_t)
+
// ================================================================
// dir frag
#include "msg/Message.h"
#include "mds/mdstypes.h"
+
class MClientReconnect : public Message {
public:
map<inodeno_t, cap_reconnect_t> caps; // only head inodes
}
void encode_payload() {
- ::encode(caps, data);
+ if (connection->has_feature(CEPH_FEATURE_FLOCK)) {
+ // new protocol
+ header.version = 2;
+ ::encode(caps, data);
+ } else {
+ // compat crap
+ map<inodeno_t, old_cap_reconnect_t> ocaps;
+ for (map<inodeno_t,cap_reconnect_t>::iterator p = caps.begin(); p != caps.end(); p++)
+ ocaps[p->first] = p->second;
+ ::encode(ocaps, data);
+ }
::encode_nohead(realms, data);
}
void decode_payload() {
bufferlist::iterator p = data.begin();
- ::decode(caps, p);
+ if (header.version >= 2) {
+ // new protocol
+ ::decode(caps, p);
+ } else {
+ // compat crap
+ map<inodeno_t, old_cap_reconnect_t> ocaps;
+ ::decode(ocaps, p);
+ for (map<inodeno_t,old_cap_reconnect_t>::iterator q = ocaps.begin(); q != ocaps.end(); q++)
+ caps[q->first] = q->second;
+ }
while (p.end()) {
realms.push_back(ceph_mds_snaprealm_reconnect());
::decode(realms.back(), p);