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_MCLIENTCAPS_H
16   	#define CEPH_MCLIENTCAPS_H
17   	
18   	#include "msg/Message.h"
19   	#include "mds/mdstypes.h"
20   	#include "include/ceph_features.h"
21   	
22   	class MClientCaps : public Message {
23   	private:
24   	
25   	  static constexpr int HEAD_VERSION = 11;
26   	  static constexpr int COMPAT_VERSION = 1;
27   	
28   	 public:
29   	  static constexpr unsigned FLAG_SYNC		= (1<<0);
30   	  static constexpr unsigned FLAG_NO_CAPSNAP		= (1<<1); // unused
31   	  static constexpr unsigned FLAG_PENDING_CAPSNAP	= (1<<2);
32   	
33   	  struct ceph_mds_caps_head head;
34   	
35   	  uint64_t size = 0;
36   	  uint64_t max_size = 0;
37   	  uint64_t truncate_size = 0;
38   	  uint64_t change_attr = 0;
39   	  uint32_t truncate_seq = 0;
40   	  utime_t mtime, atime, ctime, btime;
41   	  uint32_t time_warp_seq = 0;
42   	  int64_t nfiles = -1;		// files in dir
43   	  int64_t nsubdirs = -1;	// subdirs in dir
44   	
45   	  struct ceph_mds_cap_peer peer;
46   	
47   	  bufferlist snapbl;
48   	  bufferlist xattrbl;
49   	  bufferlist flockbl;
50   	  version_t  inline_version = 0;
51   	  bufferlist inline_data;
52   	
53   	  // Receivers may not use their new caps until they have this OSD map
54   	  epoch_t osd_epoch_barrier = 0;
55   	  ceph_tid_t oldest_flush_tid = 0;
56   	  uint32_t caller_uid = 0;
57   	  uint32_t caller_gid = 0;
58   	
59   	  /* advisory CLIENT_CAPS_* flags to send to mds */
60   	  unsigned flags = 0;
61   	
62   	  int      get_caps() const { return head.caps; }
63   	  int      get_wanted() const { return head.wanted; }
64   	  int      get_dirty() const { return head.dirty; }
65   	  ceph_seq_t get_seq() const { return head.seq; }
66   	  ceph_seq_t get_issue_seq() const { return head.issue_seq; }
67   	  ceph_seq_t get_mseq() const { return head.migrate_seq; }
68   	
69   	  inodeno_t get_ino() const { return inodeno_t(head.ino); }
70   	  inodeno_t get_realm() const { return inodeno_t(head.realm); }
71   	  uint64_t get_cap_id() const { return head.cap_id; }
72   	
73   	  uint64_t get_size() const { return size;  }
74   	  uint64_t get_max_size() const { return max_size;  }
75   	  __u32 get_truncate_seq() const { return truncate_seq; }
76   	  uint64_t get_truncate_size() const { return truncate_size; }
77   	  utime_t get_ctime() const { return ctime; }
78   	  utime_t get_btime() const { return btime; }
79   	  utime_t get_mtime() const { return mtime; }
80   	  utime_t get_atime() const { return atime; }
81   	  __u64 get_change_attr() const { return change_attr; }
82   	  __u32 get_time_warp_seq() const { return time_warp_seq; }
83   	  uint64_t get_nfiles() const { return nfiles; }
84   	  uint64_t get_nsubdirs() const { return nsubdirs; }
85   	  bool dirstat_is_valid() const { return nfiles != -1 || nsubdirs != -1; }
86   	
87   	  const file_layout_t& get_layout() const {
88   	    return layout;
89   	  }
90   	
91   	  void set_layout(const file_layout_t &l) {
92   	    layout = l;
93   	  }
94   	
95   	  int       get_migrate_seq() const { return head.migrate_seq; }
96   	  int       get_op() const { return head.op; }
97   	
98   	  uint64_t get_client_tid() const { return get_tid(); }
99   	  void set_client_tid(uint64_t s) { set_tid(s); }
100  	
101  	  snapid_t get_snap_follows() const { return snapid_t(head.snap_follows); }
102  	  void set_snap_follows(snapid_t s) { head.snap_follows = s; }
103  	
104  	  void set_caps(int c) { head.caps = c; }
105  	  void set_wanted(int w) { head.wanted = w; }
106  	
107  	  void set_max_size(uint64_t ms) { max_size = ms; }
108  	
109  	  void set_migrate_seq(unsigned m) { head.migrate_seq = m; }
110  	  void set_op(int o) { head.op = o; }
111  	
112  	  void set_size(loff_t s) { size = s; }
113  	  void set_mtime(const utime_t &t) { mtime = t; }
114  	  void set_ctime(const utime_t &t) { ctime = t; }
115  	  void set_atime(const utime_t &t) { atime = t; }
116  	
117  	  void set_cap_peer(uint64_t id, ceph_seq_t seq, ceph_seq_t mseq, int mds, int flags) {
118  	    peer.cap_id = id;
119  	    peer.seq = seq;
120  	    peer.mseq = mseq;
121  	    peer.mds = mds;
122  	    peer.flags = flags;
123  	  }
124  	
125  	  void set_oldest_flush_tid(ceph_tid_t tid) { oldest_flush_tid = tid; }
126  	  ceph_tid_t get_oldest_flush_tid() const { return oldest_flush_tid; }
127  	
128  	  void clear_dirty() { head.dirty = 0; }
129  	
130  	protected:
131  	  MClientCaps()
(2) Event uninit_member: Non-static class member field "head.op" is not initialized in this constructor nor in any functions that it calls.
(4) Event uninit_member: Non-static class member field "head.ino" is not initialized in this constructor nor in any functions that it calls.
(6) Event uninit_member: Non-static class member field "head.realm" is not initialized in this constructor nor in any functions that it calls.
(8) Event uninit_member: Non-static class member field "head.cap_id" is not initialized in this constructor nor in any functions that it calls.
(10) Event uninit_member: Non-static class member field "head.seq" is not initialized in this constructor nor in any functions that it calls.
(12) Event uninit_member: Non-static class member field "head.issue_seq" is not initialized in this constructor nor in any functions that it calls.
(14) Event uninit_member: Non-static class member field "head.caps" is not initialized in this constructor nor in any functions that it calls.
(16) Event uninit_member: Non-static class member field "head.wanted" is not initialized in this constructor nor in any functions that it calls.
(18) Event uninit_member: Non-static class member field "head.dirty" is not initialized in this constructor nor in any functions that it calls.
(20) Event uninit_member: Non-static class member field "head.migrate_seq" is not initialized in this constructor nor in any functions that it calls.
(22) Event uninit_member: Non-static class member field "head.snap_follows" is not initialized in this constructor nor in any functions that it calls.
(24) Event uninit_member: Non-static class member field "head.snap_trace_len" is not initialized in this constructor nor in any functions that it calls.
(26) Event uninit_member: Non-static class member field "head.uid" is not initialized in this constructor nor in any functions that it calls.
(28) Event uninit_member: Non-static class member field "head.gid" is not initialized in this constructor nor in any functions that it calls.
(30) Event uninit_member: Non-static class member field "head.mode" is not initialized in this constructor nor in any functions that it calls.
(32) Event uninit_member: Non-static class member field "head.nlink" is not initialized in this constructor nor in any functions that it calls.
(34) Event uninit_member: Non-static class member field "head.xattr_len" is not initialized in this constructor nor in any functions that it calls.
(36) Event uninit_member: Non-static class member field "head.xattr_version" is not initialized in this constructor nor in any functions that it calls.
(38) Event uninit_member: Non-static class member field "peer.cap_id" is not initialized in this constructor nor in any functions that it calls.
(40) Event uninit_member: Non-static class member field "peer.seq" is not initialized in this constructor nor in any functions that it calls.
(42) Event uninit_member: Non-static class member field "peer.mseq" is not initialized in this constructor nor in any functions that it calls.
(44) Event uninit_member: Non-static class member field "peer.mds" is not initialized in this constructor nor in any functions that it calls.
(46) Event uninit_member: Non-static class member field "peer.flags" is not initialized in this constructor nor in any functions that it calls.
Also see events: [member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl][member_decl]
132  	    : Message{CEPH_MSG_CLIENT_CAPS, HEAD_VERSION, COMPAT_VERSION} {}
133  	  MClientCaps(int op,
134  		      inodeno_t ino,
135  		      inodeno_t realm,
136  		      uint64_t id,
137  		      long seq,
138  		      int caps,
139  		      int wanted,
140  		      int dirty,
141  		      int mseq,
142  	              epoch_t oeb)
143  	    : Message{CEPH_MSG_CLIENT_CAPS, HEAD_VERSION, COMPAT_VERSION},
144  	      osd_epoch_barrier(oeb) {
145  	    memset(&head, 0, sizeof(head));
146  	    head.op = op;
147  	    head.ino = ino;
148  	    head.realm = realm;
149  	    head.cap_id = id;
150  	    head.seq = seq;
151  	    head.caps = caps;
152  	    head.wanted = wanted;
153  	    head.dirty = dirty;
154  	    head.migrate_seq = mseq;
155  	    memset(&peer, 0, sizeof(peer));
156  	  }
157  	  MClientCaps(int op,
158  		      inodeno_t ino, inodeno_t realm,
159  		      uint64_t id, int mseq, epoch_t oeb)
160  	    : Message{CEPH_MSG_CLIENT_CAPS, HEAD_VERSION, COMPAT_VERSION},
161  	      osd_epoch_barrier(oeb) {
162  	    memset(&head, 0, sizeof(head));
163  	    head.op = op;
164  	    head.ino = ino;
165  	    head.realm = realm;
166  	    head.cap_id = id;
167  	    head.migrate_seq = mseq;
168  	    memset(&peer, 0, sizeof(peer));
169  	  }
170  	  ~MClientCaps() override {}
171  	
172  	private:
173  	  file_layout_t layout;
174  	
175  	public:
176  	  std::string_view get_type_name() const override { return "Cfcap";}
177  	  void print(ostream& out) const override {
178  	    out << "client_caps(" << ceph_cap_op_name(head.op)
179  		<< " ino " << inodeno_t(head.ino)
180  		<< " " << head.cap_id
181  		<< " seq " << head.seq;
182  	    if (get_tid())
183  	      out << " tid " << get_tid();
184  	    out << " caps=" << ccap_string(head.caps)
185  		<< " dirty=" << ccap_string(head.dirty)
186  		<< " wanted=" << ccap_string(head.wanted);
187  	    out << " follows " << snapid_t(head.snap_follows);
188  	    if (head.migrate_seq)
189  	      out << " mseq " << head.migrate_seq;
190  	
191  	    out << " size " << size << "/" << max_size;
192  	    if (truncate_seq)
193  	      out << " ts " << truncate_seq << "/" << truncate_size;
194  	    out << " mtime " << mtime;
195  	    if (time_warp_seq)
196  	      out << " tws " << time_warp_seq;
197  	
198  	    if (head.xattr_version)
199  	      out << " xattrs(v=" << head.xattr_version << " l=" << xattrbl.length() << ")";
200  	
201  	    out << ")";
202  	  }
203  	  
204  	  void decode_payload() override {
205  	    auto p = payload.cbegin();
206  	    decode(head, p);
207  	    ceph_mds_caps_body_legacy body;
208  	    decode(body, p);
209  	    if (head.op == CEPH_CAP_OP_EXPORT) {
210  	      peer = body.peer;
211  	    } else {
212  	      size = body.size;
213  	      max_size = body.max_size;
214  	      truncate_size = body.truncate_size;
215  	      truncate_seq = body.truncate_seq;
216  	      mtime = utime_t(body.mtime);
217  	      atime = utime_t(body.atime);
218  	      ctime = utime_t(body.ctime);
219  	      layout.from_legacy(body.layout);
220  	      time_warp_seq = body.time_warp_seq;
221  	    }
222  	    decode_nohead(head.snap_trace_len, snapbl, p);
223  	
224  	    ceph_assert(middle.length() == head.xattr_len);
225  	    if (head.xattr_len)
226  	      xattrbl = middle;
227  	
228  	    // conditionally decode flock metadata
229  	    if (header.version >= 2)
230  	      decode(flockbl, p);
231  	
232  	    if (header.version >= 3) {
233  	      if (head.op == CEPH_CAP_OP_IMPORT)
234  		decode(peer, p);
235  	    }
236  	
237  	    if (header.version >= 4) {
238  	      decode(inline_version, p);
239  	      decode(inline_data, p);
240  	    } else {
241  	      inline_version = CEPH_INLINE_NONE;
242  	    }
243  	
244  	    if (header.version >= 5) {
245  	      decode(osd_epoch_barrier, p);
246  	    }
247  	    if (header.version >= 6) {
248  	      decode(oldest_flush_tid, p);
249  	    }
250  	    if (header.version >= 7) {
251  	      decode(caller_uid, p);
252  	      decode(caller_gid, p);
253  	    }
254  	    if (header.version >= 8) {
255  	      decode(layout.pool_ns, p);
256  	    }
257  	    if (header.version >= 9) {
258  	      decode(btime, p);
259  	      decode(change_attr, p);
260  	    }
261  	    if (header.version >= 10) {
262  	      decode(flags, p);
263  	    }
264  	    if (header.version >= 11) {
265  	      decode(nfiles, p);
266  	      decode(nsubdirs, p);
267  	    }
268  	  }
269  	  void encode_payload(uint64_t features) override {
270  	    using ceph::encode;
271  	    header.version = HEAD_VERSION;
272  	    head.snap_trace_len = snapbl.length();
273  	    head.xattr_len = xattrbl.length();
274  	
275  	    encode(head, payload);
276  	    ceph_mds_caps_body_legacy body;
277  	    if (head.op == CEPH_CAP_OP_EXPORT) {
278  	      memset(&body, 0, sizeof(body));
279  	      body.peer = peer;
280  	    } else {
281  	      body.size = size;
282  	      body.max_size = max_size;
283  	      body.truncate_size = truncate_size;
284  	      body.truncate_seq = truncate_seq;
285  	      mtime.encode_timeval(&body.mtime);
286  	      atime.encode_timeval(&body.atime);
287  	      ctime.encode_timeval(&body.ctime);
288  	      layout.to_legacy(&body.layout);
289  	      body.time_warp_seq = time_warp_seq;
290  	    }
291  	    encode(body, payload);
292  	    encode_nohead(snapbl, payload);
293  	
294  	    middle = xattrbl;
295  	
296  	    // conditionally include flock metadata
297  	    if (features & CEPH_FEATURE_FLOCK) {
298  	      encode(flockbl, payload);
299  	    } else {
300  	      header.version = 1;
301  	      return;
302  	    }
303  	
304  	    if (features & CEPH_FEATURE_EXPORT_PEER) {
305  	      if (head.op == CEPH_CAP_OP_IMPORT)
306  		encode(peer, payload);
307  	    } else {
308  	      header.version = 2;
309  	      return;
310  	    }
311  	
312  	    if (features & CEPH_FEATURE_MDS_INLINE_DATA) {
313  	      encode(inline_version, payload);
314  	      encode(inline_data, payload);
315  	    } else {
316  	      encode(inline_version, payload);
317  	      encode(bufferlist(), payload);
318  	    }
319  	
320  	    encode(osd_epoch_barrier, payload);
321  	    encode(oldest_flush_tid, payload);
322  	    encode(caller_uid, payload);
323  	    encode(caller_gid, payload);
324  	
325  	    encode(layout.pool_ns, payload);
326  	    encode(btime, payload);
327  	    encode(change_attr, payload);
328  	    encode(flags, payload);
329  	    encode(nfiles, payload);
330  	    encode(nsubdirs, payload);
331  	  }
332  	private:
333  	  template<class T, typename... Args>
334  	  friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args);
335  	};
336  	
337  	#endif
338