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