]> git.proxmox.com Git - ceph.git/blob - ceph/src/messages/MClientCaps.h
import ceph quincy 17.2.6
[ceph.git] / ceph / src / messages / MClientCaps.h
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 final : public SafeMessage {
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 ceph::buffer::list snapbl;
48 ceph::buffer::list xattrbl;
49 ceph::buffer::list flockbl;
50 version_t inline_version = 0;
51 ceph::buffer::list 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()
132 : SafeMessage{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 : SafeMessage{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 : SafeMessage{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() final {}
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(std::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 << " ctime " << ctime
196 << " change_attr " << change_attr;
197 if (time_warp_seq)
198 out << " tws " << time_warp_seq;
199
200 if (head.xattr_version)
201 out << " xattrs(v=" << head.xattr_version << " l=" << xattrbl.length() << ")";
202
203 out << ")";
204 }
205
206 void decode_payload() override {
207 using ceph::decode;
208 auto p = payload.cbegin();
209 decode(head, p);
210 if (head.op == CEPH_CAP_OP_EXPORT) {
211 ceph_mds_caps_export_body body;
212 decode(body, p);
213 peer = body.peer;
214 p += (sizeof(ceph_mds_caps_non_export_body) -
215 sizeof(ceph_mds_caps_export_body));
216 } else {
217 ceph_mds_caps_non_export_body body;
218 decode(body, p);
219 size = body.size;
220 max_size = body.max_size;
221 truncate_size = body.truncate_size;
222 truncate_seq = body.truncate_seq;
223 mtime = utime_t(body.mtime);
224 atime = utime_t(body.atime);
225 ctime = utime_t(body.ctime);
226 layout.from_legacy(body.layout);
227 time_warp_seq = body.time_warp_seq;
228 }
229 ceph::decode_nohead(head.snap_trace_len, snapbl, p);
230
231 ceph_assert(middle.length() == head.xattr_len);
232 if (head.xattr_len)
233 xattrbl = middle;
234
235 // conditionally decode flock metadata
236 if (header.version >= 2)
237 decode(flockbl, p);
238
239 if (header.version >= 3) {
240 if (head.op == CEPH_CAP_OP_IMPORT)
241 decode(peer, p);
242 }
243
244 if (header.version >= 4) {
245 decode(inline_version, p);
246 decode(inline_data, p);
247 } else {
248 inline_version = CEPH_INLINE_NONE;
249 }
250
251 if (header.version >= 5) {
252 decode(osd_epoch_barrier, p);
253 }
254 if (header.version >= 6) {
255 decode(oldest_flush_tid, p);
256 }
257 if (header.version >= 7) {
258 decode(caller_uid, p);
259 decode(caller_gid, p);
260 }
261 if (header.version >= 8) {
262 decode(layout.pool_ns, p);
263 }
264 if (header.version >= 9) {
265 decode(btime, p);
266 decode(change_attr, p);
267 }
268 if (header.version >= 10) {
269 decode(flags, p);
270 }
271 if (header.version >= 11) {
272 decode(nfiles, p);
273 decode(nsubdirs, p);
274 }
275 }
276 void encode_payload(uint64_t features) override {
277 using ceph::encode;
278 header.version = HEAD_VERSION;
279 head.snap_trace_len = snapbl.length();
280 head.xattr_len = xattrbl.length();
281
282 encode(head, payload);
283 static_assert(sizeof(ceph_mds_caps_non_export_body) >
284 sizeof(ceph_mds_caps_export_body));
285 if (head.op == CEPH_CAP_OP_EXPORT) {
286 ceph_mds_caps_export_body body;
287 body.peer = peer;
288 encode(body, payload);
289 payload.append_zero(sizeof(ceph_mds_caps_non_export_body) -
290 sizeof(ceph_mds_caps_export_body));
291 } else {
292 ceph_mds_caps_non_export_body body;
293 body.size = size;
294 body.max_size = max_size;
295 body.truncate_size = truncate_size;
296 body.truncate_seq = truncate_seq;
297 mtime.encode_timeval(&body.mtime);
298 atime.encode_timeval(&body.atime);
299 ctime.encode_timeval(&body.ctime);
300 layout.to_legacy(&body.layout);
301 body.time_warp_seq = time_warp_seq;
302 encode(body, payload);
303 }
304 ceph::encode_nohead(snapbl, payload);
305
306 middle = xattrbl;
307
308 // conditionally include flock metadata
309 if (features & CEPH_FEATURE_FLOCK) {
310 encode(flockbl, payload);
311 } else {
312 header.version = 1;
313 return;
314 }
315
316 if (features & CEPH_FEATURE_EXPORT_PEER) {
317 if (head.op == CEPH_CAP_OP_IMPORT)
318 encode(peer, payload);
319 } else {
320 header.version = 2;
321 return;
322 }
323
324 if (features & CEPH_FEATURE_MDS_INLINE_DATA) {
325 encode(inline_version, payload);
326 encode(inline_data, payload);
327 } else {
328 encode(inline_version, payload);
329 encode(ceph::buffer::list(), payload);
330 }
331
332 encode(osd_epoch_barrier, payload);
333 encode(oldest_flush_tid, payload);
334 encode(caller_uid, payload);
335 encode(caller_gid, payload);
336
337 encode(layout.pool_ns, payload);
338 encode(btime, payload);
339 encode(change_attr, payload);
340 encode(flags, payload);
341 encode(nfiles, payload);
342 encode(nsubdirs, payload);
343 }
344 private:
345 template<class T, typename... Args>
346 friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args);
347 template<class T, typename... Args>
348 friend MURef<T> crimson::make_message(Args&&... args);
349 };
350
351 #endif