]> git.proxmox.com Git - ceph.git/blob - ceph/src/messages/MClientReply.h
Import ceph 15.2.8
[ceph.git] / ceph / src / messages / MClientReply.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
16 #ifndef CEPH_MCLIENTREPLY_H
17 #define CEPH_MCLIENTREPLY_H
18
19 #include "include/types.h"
20 #include "include/fs_types.h"
21 #include "MClientRequest.h"
22
23 #include "msg/Message.h"
24 #include "include/ceph_features.h"
25 #include "common/errno.h"
26
27 /***
28 *
29 * MClientReply - container message for MDS reply to a client's MClientRequest
30 *
31 * key fields:
32 * long tid - transaction id, so the client can match up with pending request
33 * int result - error code, or fh if it was open
34 *
35 * for most requests:
36 * trace is a vector of InodeStat's tracing from root to the file/dir/whatever
37 * the operation referred to, so that the client can update it's info about what
38 * metadata lives on what MDS.
39 *
40 * for readdir replies:
41 * dir_contents is a vector of InodeStat*'s.
42 *
43 * that's mostly it, i think!
44 *
45 */
46
47
48 struct LeaseStat {
49 // this matches ceph_mds_reply_lease
50 __u16 mask;
51 __u32 duration_ms;
52 __u32 seq;
53
54 LeaseStat() : mask(0), duration_ms(0), seq(0) {}
55 LeaseStat(__u16 msk, __u32 dur, __u32 sq) : mask{msk}, duration_ms{dur}, seq{sq} {}
56
57 void decode(bufferlist::const_iterator &bl, const uint64_t features) {
58 using ceph::decode;
59 if (features == (uint64_t)-1) {
60 DECODE_START(1, bl);
61 decode(mask, bl);
62 decode(duration_ms, bl);
63 decode(seq, bl);
64 DECODE_FINISH(bl);
65 }
66 else {
67 decode(mask, bl);
68 decode(duration_ms, bl);
69 decode(seq, bl);
70 }
71 }
72 };
73
74 inline ostream& operator<<(ostream& out, const LeaseStat& l) {
75 return out << "lease(mask " << l.mask << " dur " << l.duration_ms << ")";
76 }
77
78 struct DirStat {
79 // mds distribution hints
80 frag_t frag;
81 __s32 auth;
82 set<__s32> dist;
83
84 DirStat() : auth(CDIR_AUTH_PARENT) {}
85 DirStat(bufferlist::const_iterator& p, const uint64_t features) {
86 decode(p, features);
87 }
88
89 void decode(bufferlist::const_iterator& p, const uint64_t features) {
90 using ceph::decode;
91 if (features == (uint64_t)-1) {
92 DECODE_START(1, p);
93 decode(frag, p);
94 decode(auth, p);
95 decode(dist, p);
96 DECODE_FINISH(p);
97 }
98 else {
99 decode(frag, p);
100 decode(auth, p);
101 decode(dist, p);
102 }
103 }
104
105 // see CDir::encode_dirstat for encoder.
106 };
107
108 struct InodeStat {
109 vinodeno_t vino;
110 uint32_t rdev = 0;
111 version_t version = 0;
112 version_t xattr_version = 0;
113 ceph_mds_reply_cap cap;
114 file_layout_t layout;
115 utime_t ctime, btime, mtime, atime, snap_btime;
116 uint32_t time_warp_seq = 0;
117 uint64_t size = 0, max_size = 0;
118 uint64_t change_attr = 0;
119 uint64_t truncate_size = 0;
120 uint32_t truncate_seq = 0;
121 uint32_t mode = 0, uid = 0, gid = 0, nlink = 0;
122 frag_info_t dirstat;
123 nest_info_t rstat;
124
125 fragtree_t dirfragtree;
126 string symlink; // symlink content (if symlink)
127
128 ceph_dir_layout dir_layout;
129
130 bufferlist xattrbl;
131
132 bufferlist inline_data;
133 version_t inline_version;
134
135 quota_info_t quota;
136
137 mds_rank_t dir_pin;
138
139 public:
140 InodeStat() {}
141 InodeStat(bufferlist::const_iterator& p, const uint64_t features) {
142 decode(p, features);
143 }
144
145 void decode(bufferlist::const_iterator &p, const uint64_t features) {
146 using ceph::decode;
147 if (features == (uint64_t)-1) {
148 DECODE_START(2, p);
149 decode(vino.ino, p);
150 decode(vino.snapid, p);
151 decode(rdev, p);
152 decode(version, p);
153 decode(xattr_version, p);
154 decode(cap, p);
155 {
156 ceph_file_layout legacy_layout;
157 decode(legacy_layout, p);
158 layout.from_legacy(legacy_layout);
159 }
160 decode(ctime, p);
161 decode(mtime, p);
162 decode(atime, p);
163 decode(time_warp_seq, p);
164 decode(size, p);
165 decode(max_size, p);
166 decode(truncate_size, p);
167 decode(truncate_seq, p);
168 decode(mode, p);
169 decode(uid, p);
170 decode(gid, p);
171 decode(nlink, p);
172 decode(dirstat.nfiles, p);
173 decode(dirstat.nsubdirs, p);
174 decode(rstat.rbytes, p);
175 decode(rstat.rfiles, p);
176 decode(rstat.rsubdirs, p);
177 decode(rstat.rctime, p);
178 decode(dirfragtree, p);
179 decode(symlink, p);
180 decode(dir_layout, p);
181 decode(xattrbl, p);
182 decode(inline_version, p);
183 decode(inline_data, p);
184 decode(quota, p);
185 decode(layout.pool_ns, p);
186 decode(btime, p);
187 decode(change_attr, p);
188 if (struct_v > 1) {
189 decode(dir_pin, p);
190 } else {
191 dir_pin = -ENODATA;
192 }
193 if (struct_v >= 3) {
194 decode(snap_btime, p);
195 } // else remains zero
196 DECODE_FINISH(p);
197 }
198 else {
199 decode(vino.ino, p);
200 decode(vino.snapid, p);
201 decode(rdev, p);
202 decode(version, p);
203 decode(xattr_version, p);
204 decode(cap, p);
205 {
206 ceph_file_layout legacy_layout;
207 decode(legacy_layout, p);
208 layout.from_legacy(legacy_layout);
209 }
210 decode(ctime, p);
211 decode(mtime, p);
212 decode(atime, p);
213 decode(time_warp_seq, p);
214 decode(size, p);
215 decode(max_size, p);
216 decode(truncate_size, p);
217 decode(truncate_seq, p);
218 decode(mode, p);
219 decode(uid, p);
220 decode(gid, p);
221 decode(nlink, p);
222 decode(dirstat.nfiles, p);
223 decode(dirstat.nsubdirs, p);
224 decode(rstat.rbytes, p);
225 decode(rstat.rfiles, p);
226 decode(rstat.rsubdirs, p);
227 decode(rstat.rctime, p);
228 decode(dirfragtree, p);
229 decode(symlink, p);
230 if (features & CEPH_FEATURE_DIRLAYOUTHASH)
231 decode(dir_layout, p);
232 else
233 memset(&dir_layout, 0, sizeof(dir_layout));
234
235 decode(xattrbl, p);
236
237 if (features & CEPH_FEATURE_MDS_INLINE_DATA) {
238 decode(inline_version, p);
239 decode(inline_data, p);
240 } else {
241 inline_version = CEPH_INLINE_NONE;
242 }
243
244 if (features & CEPH_FEATURE_MDS_QUOTA)
245 decode(quota, p);
246 else
247 quota = quota_info_t{};
248
249 if ((features & CEPH_FEATURE_FS_FILE_LAYOUT_V2))
250 decode(layout.pool_ns, p);
251
252 if ((features & CEPH_FEATURE_FS_BTIME)) {
253 decode(btime, p);
254 decode(change_attr, p);
255 } else {
256 btime = utime_t();
257 change_attr = 0;
258 }
259 }
260 }
261
262 // see CInode::encode_inodestat for encoder.
263 };
264
265 struct openc_response_t {
266 _inodeno_t created_ino;
267 interval_set<inodeno_t> delegated_inos;
268
269 public:
270 void encode(ceph::buffer::list& bl) const {
271 using ceph::encode;
272 ENCODE_START(1, 1, bl);
273 encode(created_ino, bl);
274 encode(delegated_inos, bl);
275 ENCODE_FINISH(bl);
276 }
277 void decode(bufferlist::const_iterator &p) {
278 using ceph::decode;
279 DECODE_START(1, p);
280 decode(created_ino, p);
281 decode(delegated_inos, p);
282 DECODE_FINISH(p);
283 }
284 } __attribute__ ((__may_alias__));
285 WRITE_CLASS_ENCODER(openc_response_t)
286
287 class MClientReply : public SafeMessage {
288 public:
289 // reply data
290 struct ceph_mds_reply_head head {};
291 bufferlist trace_bl;
292 bufferlist extra_bl;
293 bufferlist snapbl;
294
295 int get_op() const { return head.op; }
296
297 void set_mdsmap_epoch(epoch_t e) { head.mdsmap_epoch = e; }
298 epoch_t get_mdsmap_epoch() const { return head.mdsmap_epoch; }
299
300 int get_result() const {
301 return ceph_to_hostos_errno((__s32)(__u32)head.result);
302 }
303
304 void set_result(int r) { head.result = r; }
305
306 void set_unsafe() { head.safe = 0; }
307
308 bool is_safe() const { return head.safe; }
309
310 protected:
311 MClientReply() : SafeMessage{CEPH_MSG_CLIENT_REPLY} {}
312 MClientReply(const MClientRequest &req, int result = 0) :
313 SafeMessage{CEPH_MSG_CLIENT_REPLY} {
314 memset(&head, 0, sizeof(head));
315 header.tid = req.get_tid();
316 head.op = req.get_op();
317 head.result = result;
318 head.safe = 1;
319 }
320 ~MClientReply() override {}
321
322 public:
323 std::string_view get_type_name() const override { return "creply"; }
324 void print(ostream& o) const override {
325 o << "client_reply(???:" << get_tid();
326 o << " = " << get_result();
327 if (get_result() <= 0) {
328 o << " " << cpp_strerror(get_result());
329 }
330 if (head.op & CEPH_MDS_OP_WRITE) {
331 if (head.safe)
332 o << " safe";
333 else
334 o << " unsafe";
335 }
336 o << ")";
337 }
338
339 // serialization
340 void decode_payload() override {
341 auto p = payload.cbegin();
342 decode(head, p);
343 decode(trace_bl, p);
344 decode(extra_bl, p);
345 decode(snapbl, p);
346 ceph_assert(p.end());
347 }
348 void encode_payload(uint64_t features) override {
349 using ceph::encode;
350 encode(head, payload);
351 encode(trace_bl, payload);
352 encode(extra_bl, payload);
353 encode(snapbl, payload);
354 }
355
356
357 // dir contents
358 void set_extra_bl(bufferlist& bl) {
359 extra_bl.claim(bl);
360 }
361 bufferlist& get_extra_bl() {
362 return extra_bl;
363 }
364 const bufferlist& get_extra_bl() const {
365 return extra_bl;
366 }
367
368 // trace
369 void set_trace(bufferlist& bl) {
370 trace_bl.claim(bl);
371 }
372 bufferlist& get_trace_bl() {
373 return trace_bl;
374 }
375 const bufferlist& get_trace_bl() const {
376 return trace_bl;
377 }
378 private:
379 template<class T, typename... Args>
380 friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args);
381 };
382
383 #endif