1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #ifndef CEPH_MMDSCACHEREJOIN_H
16 #define CEPH_MMDSCACHEREJOIN_H
17
18 #include <string_view>
19
20 #include "msg/Message.h"
21
22 #include "include/types.h"
23
24 #include "mds/CInode.h"
25 #include "mds/CDir.h"
26 #include "mds/mdstypes.h"
27
28 // sent from replica to auth
29
30 class MMDSCacheRejoin : public Message {
31 private:
32 static constexpr int HEAD_VERSION = 2;
33 static constexpr int COMPAT_VERSION = 1;
34
35 public:
36 static constexpr int OP_WEAK = 1; // replica -> auth, i exist, + maybe open files.
37 static constexpr int OP_STRONG = 2; // replica -> auth, i exist, + open files and lock state.
38 static constexpr int OP_ACK = 3; // auth -> replica, here is your lock state.
39 static const char *get_opname(int op) {
40 switch (op) {
41 case OP_WEAK: return "weak";
42 case OP_STRONG: return "strong";
43 case OP_ACK: return "ack";
44 default: ceph_abort(); return 0;
45 }
46 }
47
48 // -- types --
49 struct inode_strong {
50 uint32_t nonce = 0;
51 int32_t caps_wanted = 0;
52 int32_t filelock = 0, nestlock = 0, dftlock = 0;
53 inode_strong() {}
54 inode_strong(int n, int cw, int dl, int nl, int dftl) :
55 nonce(n), caps_wanted(cw),
56 filelock(dl), nestlock(nl), dftlock(dftl) { }
57 void encode(bufferlist &bl) const {
58 using ceph::encode;
59 encode(nonce, bl);
60 encode(caps_wanted, bl);
61 encode(filelock, bl);
62 encode(nestlock, bl);
63 encode(dftlock, bl);
64 }
65 void decode(bufferlist::const_iterator &bl) {
66 using ceph::decode;
67 decode(nonce, bl);
68 decode(caps_wanted, bl);
69 decode(filelock, bl);
70 decode(nestlock, bl);
71 decode(dftlock, bl);
72 }
73 };
74 WRITE_CLASS_ENCODER(inode_strong)
75
76 struct dirfrag_strong {
77 uint32_t nonce = 0;
78 int8_t dir_rep = 0;
79 dirfrag_strong() {}
80 dirfrag_strong(int n, int dr) : nonce(n), dir_rep(dr) {}
81 void encode(bufferlist &bl) const {
82 using ceph::encode;
83 encode(nonce, bl);
(1) Event overrun-buffer-val: |
Overrunning buffer pointed to by "this->dir_rep" of 4 bytes by passing it to a function which accesses it at byte offset 7. [details] |
84 encode(dir_rep, bl);
85 }
86 void decode(bufferlist::const_iterator &bl) {
87 using ceph::decode;
88 decode(nonce, bl);
89 decode(dir_rep, bl);
90 }
91 };
92 WRITE_CLASS_ENCODER(dirfrag_strong)
93
94 struct dn_strong {
95 snapid_t first;
96 inodeno_t ino;
97 inodeno_t remote_ino;
98 unsigned char remote_d_type;
99 uint32_t nonce;
100 int32_t lock;
101 dn_strong() :
102 ino(0), remote_ino(0), remote_d_type(0), nonce(0), lock(0) {}
103 dn_strong(snapid_t f, inodeno_t pi, inodeno_t ri, unsigned char rdt, int n, int l) :
104 first(f), ino(pi), remote_ino(ri), remote_d_type(rdt), nonce(n), lock(l) {}
105 bool is_primary() const { return ino > 0; }
106 bool is_remote() const { return remote_ino > 0; }
107 bool is_null() const { return ino == 0 && remote_ino == 0; }
108 void encode(bufferlist &bl) const {
109 using ceph::encode;
110 encode(first, bl);
111 encode(ino, bl);
112 encode(remote_ino, bl);
113 encode(remote_d_type, bl);
114 encode(nonce, bl);
115 encode(lock, bl);
116 }
117 void decode(bufferlist::const_iterator &bl) {
118 using ceph::decode;
119 decode(first, bl);
120 decode(ino, bl);
121 decode(remote_ino, bl);
122 decode(remote_d_type, bl);
123 decode(nonce, bl);
124 decode(lock, bl);
125 }
126 };
127 WRITE_CLASS_ENCODER(dn_strong)
128
129 struct dn_weak {
130 snapid_t first;
131 inodeno_t ino;
132 dn_weak() : ino(0) {}
133 dn_weak(snapid_t f, inodeno_t pi) : first(f), ino(pi) {}
134 void encode(bufferlist &bl) const {
135 using ceph::encode;
136 encode(first, bl);
137 encode(ino, bl);
138 }
139 void decode(bufferlist::const_iterator &bl) {
140 using ceph::decode;
141 decode(first, bl);
142 decode(ino, bl);
143 }
144 };
145 WRITE_CLASS_ENCODER(dn_weak)
146
147 // -- data --
148 int32_t op;
149
150 struct lock_bls {
151 bufferlist file, nest, dft;
152 void encode(bufferlist& bl) const {
153 using ceph::encode;
154 encode(file, bl);
155 encode(nest, bl);
156 encode(dft, bl);
157 }
158 void decode(bufferlist::const_iterator& bl) {
159 using ceph::decode;
160 decode(file, bl);
161 decode(nest, bl);
162 decode(dft, bl);
163 }
164 };
165 WRITE_CLASS_ENCODER(lock_bls)
166
167 // weak
168 map<inodeno_t, map<string_snap_t, dn_weak> > weak;
169 set<dirfrag_t> weak_dirfrags;
170 set<vinodeno_t> weak_inodes;
171 map<inodeno_t, lock_bls> inode_scatterlocks;
172
173 // strong
174 map<dirfrag_t, dirfrag_strong> strong_dirfrags;
175 map<dirfrag_t, map<string_snap_t, dn_strong> > strong_dentries;
176 map<vinodeno_t, inode_strong> strong_inodes;
177
178 // open
179 map<inodeno_t,map<client_t, cap_reconnect_t> > cap_exports;
180 map<client_t, entity_inst_t> client_map;
181 map<client_t,client_metadata_t> client_metadata_map;
182 bufferlist imported_caps;
183
184 // full
185 bufferlist inode_base;
186 bufferlist inode_locks;
187 map<dirfrag_t, bufferlist> dirfrag_bases;
188
189 // authpins, xlocks
190 struct slave_reqid {
191 metareqid_t reqid;
192 __u32 attempt;
193 slave_reqid() : attempt(0) {}
194 slave_reqid(const metareqid_t& r, __u32 a)
195 : reqid(r), attempt(a) {}
196 void encode(bufferlist& bl) const {
197 using ceph::encode;
198 encode(reqid, bl);
199 encode(attempt, bl);
200 }
201 void decode(bufferlist::const_iterator& bl) {
202 using ceph::decode;
203 decode(reqid, bl);
204 decode(attempt, bl);
205 }
206 };
207 map<vinodeno_t, list<slave_reqid> > authpinned_inodes;
208 map<vinodeno_t, slave_reqid> frozen_authpin_inodes;
209 map<vinodeno_t, map<__s32, slave_reqid> > xlocked_inodes;
210 map<vinodeno_t, map<__s32, list<slave_reqid> > > wrlocked_inodes;
211 map<dirfrag_t, map<string_snap_t, list<slave_reqid> > > authpinned_dentries;
212 map<dirfrag_t, map<string_snap_t, slave_reqid> > xlocked_dentries;
213
214 protected:
215 MMDSCacheRejoin() :
216 MMDSCacheRejoin{0}
217 {}
218 MMDSCacheRejoin(int o) :
219 Message{MSG_MDS_CACHEREJOIN, HEAD_VERSION, COMPAT_VERSION},
220 op(o) {}
221 ~MMDSCacheRejoin() override {}
222
223 public:
224 std::string_view get_type_name() const override { return "cache_rejoin"; }
225 void print(ostream& out) const override {
226 out << "cache_rejoin " << get_opname(op);
227 }
228
229 // -- builders --
230 // inodes
231 void add_weak_inode(vinodeno_t i) {
232 weak_inodes.insert(i);
233 }
234 void add_strong_inode(vinodeno_t i, int n, int cw, int dl, int nl, int dftl) {
235 strong_inodes[i] = inode_strong(n, cw, dl, nl, dftl);
236 }
237 void add_inode_locks(CInode *in, __u32 nonce, bufferlist& bl) {
238 using ceph::encode;
239 encode(in->inode.ino, inode_locks);
240 encode(in->last, inode_locks);
241 encode(nonce, inode_locks);
242 encode(bl, inode_locks);
243 }
244 void add_inode_base(CInode *in, uint64_t features) {
245 using ceph::encode;
246 encode(in->inode.ino, inode_base);
247 encode(in->last, inode_base);
248 bufferlist bl;
249 in->_encode_base(bl, features);
250 encode(bl, inode_base);
251 }
252 void add_inode_authpin(vinodeno_t ino, const metareqid_t& ri, __u32 attempt) {
253 authpinned_inodes[ino].push_back(slave_reqid(ri, attempt));
254 }
255 void add_inode_frozen_authpin(vinodeno_t ino, const metareqid_t& ri, __u32 attempt) {
256 frozen_authpin_inodes[ino] = slave_reqid(ri, attempt);
257 }
258 void add_inode_xlock(vinodeno_t ino, int lt, const metareqid_t& ri, __u32 attempt) {
259 xlocked_inodes[ino][lt] = slave_reqid(ri, attempt);
260 }
261 void add_inode_wrlock(vinodeno_t ino, int lt, const metareqid_t& ri, __u32 attempt) {
262 wrlocked_inodes[ino][lt].push_back(slave_reqid(ri, attempt));
263 }
264
265 void add_scatterlock_state(CInode *in) {
266 if (inode_scatterlocks.count(in->ino()))
267 return; // already added this one
268 in->encode_lock_state(CEPH_LOCK_IFILE, inode_scatterlocks[in->ino()].file);
269 in->encode_lock_state(CEPH_LOCK_INEST, inode_scatterlocks[in->ino()].nest);
270 in->encode_lock_state(CEPH_LOCK_IDFT, inode_scatterlocks[in->ino()].dft);
271 }
272
273 // dirfrags
274 void add_strong_dirfrag(dirfrag_t df, int n, int dr) {
275 strong_dirfrags[df] = dirfrag_strong(n, dr);
276 }
277 void add_dirfrag_base(CDir *dir) {
278 bufferlist& bl = dirfrag_bases[dir->dirfrag()];
279 dir->_encode_base(bl);
280 }
281
282 // dentries
283 void add_weak_dirfrag(dirfrag_t df) {
284 weak_dirfrags.insert(df);
285 }
286 void add_weak_dentry(inodeno_t dirino, std::string_view dname, snapid_t last, dn_weak& dnw) {
287 weak[dirino][string_snap_t(dname, last)] = dnw;
288 }
289 void add_weak_primary_dentry(inodeno_t dirino, std::string_view dname, snapid_t first, snapid_t last, inodeno_t ino) {
290 weak[dirino][string_snap_t(dname, last)] = dn_weak(first, ino);
291 }
292 void add_strong_dentry(dirfrag_t df, std::string_view dname, snapid_t first, snapid_t last, inodeno_t pi, inodeno_t ri, unsigned char rdt, int n, int ls) {
293 strong_dentries[df][string_snap_t(dname, last)] = dn_strong(first, pi, ri, rdt, n, ls);
294 }
295 void add_dentry_authpin(dirfrag_t df, std::string_view dname, snapid_t last,
296 const metareqid_t& ri, __u32 attempt) {
297 authpinned_dentries[df][string_snap_t(dname, last)].push_back(slave_reqid(ri, attempt));
298 }
299 void add_dentry_xlock(dirfrag_t df, std::string_view dname, snapid_t last,
300 const metareqid_t& ri, __u32 attempt) {
301 xlocked_dentries[df][string_snap_t(dname, last)] = slave_reqid(ri, attempt);
302 }
303
304 // -- encoding --
305 void encode_payload(uint64_t features) override {
306 using ceph::encode;
307 encode(op, payload);
308 encode(strong_inodes, payload);
309 encode(inode_base, payload);
310 encode(inode_locks, payload);
311 encode(inode_scatterlocks, payload);
312 encode(authpinned_inodes, payload);
313 encode(frozen_authpin_inodes, payload);
314 encode(xlocked_inodes, payload);
315 encode(wrlocked_inodes, payload);
316 encode(cap_exports, payload);
317 encode(client_map, payload, features);
318 encode(imported_caps, payload);
319 encode(strong_dirfrags, payload);
320 encode(dirfrag_bases, payload);
321 encode(weak, payload);
322 encode(weak_dirfrags, payload);
323 encode(weak_inodes, payload);
324 encode(strong_dentries, payload);
325 encode(authpinned_dentries, payload);
326 encode(xlocked_dentries, payload);
327 encode(client_metadata_map, payload);
328 }
329 void decode_payload() override {
330 auto p = payload.cbegin();
331 using ceph::decode;
332 decode(op, p);
333 decode(strong_inodes, p);
334 decode(inode_base, p);
335 decode(inode_locks, p);
336 decode(inode_scatterlocks, p);
337 decode(authpinned_inodes, p);
338 decode(frozen_authpin_inodes, p);
339 decode(xlocked_inodes, p);
340 decode(wrlocked_inodes, p);
341 decode(cap_exports, p);
342 decode(client_map, p);
343 decode(imported_caps, p);
344 decode(strong_dirfrags, p);
345 decode(dirfrag_bases, p);
346 decode(weak, p);
347 decode(weak_dirfrags, p);
348 decode(weak_inodes, p);
349 decode(strong_dentries, p);
350 decode(authpinned_dentries, p);
351 decode(xlocked_dentries, p);
352 if (header.version >= 2)
353 decode(client_metadata_map, p);
354 }
355 private:
356 template<class T, typename... Args>
357 friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args);
358 };
359
360 WRITE_CLASS_ENCODER(MMDSCacheRejoin::inode_strong)
361 WRITE_CLASS_ENCODER(MMDSCacheRejoin::dirfrag_strong)
362 WRITE_CLASS_ENCODER(MMDSCacheRejoin::dn_strong)
363 WRITE_CLASS_ENCODER(MMDSCacheRejoin::dn_weak)
364 WRITE_CLASS_ENCODER(MMDSCacheRejoin::lock_bls)
365 WRITE_CLASS_ENCODER(MMDSCacheRejoin::slave_reqid)
366
367 inline ostream& operator<<(ostream& out, const MMDSCacheRejoin::slave_reqid& r) {
368 return out << r.reqid << '.' << r.attempt;
369 }
370
371 #endif
372