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