]>
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" | |
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) {} | |
11fdf7f2 TL |
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 | } | |
7c673cae FG |
71 | } |
72 | }; | |
7c673cae FG |
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) {} | |
11fdf7f2 TL |
85 | DirStat(bufferlist::const_iterator& p, const uint64_t features) { |
86 | decode(p, features); | |
7c673cae FG |
87 | } |
88 | ||
11fdf7f2 TL |
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 | } | |
7c673cae FG |
103 | } |
104 | ||
105 | // see CDir::encode_dirstat for encoder. | |
106 | }; | |
107 | ||
108 | struct InodeStat { | |
109 | vinodeno_t vino; | |
11fdf7f2 TL |
110 | uint32_t rdev = 0; |
111 | version_t version = 0; | |
112 | version_t xattr_version = 0; | |
7c673cae FG |
113 | ceph_mds_reply_cap cap; |
114 | file_layout_t layout; | |
81eedcae | 115 | utime_t ctime, btime, mtime, atime, snap_btime; |
11fdf7f2 TL |
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; | |
7c673cae FG |
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 | ||
11fdf7f2 TL |
137 | mds_rank_t dir_pin; |
138 | ||
7c673cae FG |
139 | public: |
140 | InodeStat() {} | |
11fdf7f2 | 141 | InodeStat(bufferlist::const_iterator& p, const uint64_t features) { |
7c673cae FG |
142 | decode(p, features); |
143 | } | |
144 | ||
11fdf7f2 TL |
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 | } | |
81eedcae TL |
193 | if (struct_v >= 3) { |
194 | decode(snap_btime, p); | |
195 | } // else remains zero | |
11fdf7f2 | 196 | DECODE_FINISH(p); |
7c673cae | 197 | } |
11fdf7f2 TL |
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)); | |
7c673cae | 234 | |
11fdf7f2 TL |
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 | } | |
7c673cae FG |
259 | } |
260 | } | |
261 | ||
262 | // see CInode::encode_inodestat for encoder. | |
263 | }; | |
264 | ||
265 | ||
11fdf7f2 | 266 | class MClientReply : public MessageInstance<MClientReply> { |
7c673cae | 267 | public: |
11fdf7f2 TL |
268 | friend factory; |
269 | ||
270 | // reply data | |
271 | struct ceph_mds_reply_head head {}; | |
7c673cae FG |
272 | bufferlist trace_bl; |
273 | bufferlist extra_bl; | |
274 | bufferlist snapbl; | |
275 | ||
7c673cae FG |
276 | int get_op() const { return head.op; } |
277 | ||
278 | void set_mdsmap_epoch(epoch_t e) { head.mdsmap_epoch = e; } | |
279 | epoch_t get_mdsmap_epoch() const { return head.mdsmap_epoch; } | |
280 | ||
281 | int get_result() const { | |
31f18b77 | 282 | return ceph_to_hostos_errno((__s32)(__u32)head.result); |
7c673cae FG |
283 | } |
284 | ||
285 | void set_result(int r) { head.result = r; } | |
286 | ||
287 | void set_unsafe() { head.safe = 0; } | |
288 | ||
289 | bool is_safe() const { return head.safe; } | |
290 | ||
11fdf7f2 TL |
291 | protected: |
292 | MClientReply() : MessageInstance(CEPH_MSG_CLIENT_REPLY) {} | |
293 | MClientReply(const MClientRequest &req, int result = 0) : | |
294 | MessageInstance(CEPH_MSG_CLIENT_REPLY) { | |
7c673cae | 295 | memset(&head, 0, sizeof(head)); |
11fdf7f2 TL |
296 | header.tid = req.get_tid(); |
297 | head.op = req.get_op(); | |
7c673cae FG |
298 | head.result = result; |
299 | head.safe = 1; | |
300 | } | |
7c673cae FG |
301 | ~MClientReply() override {} |
302 | ||
303 | public: | |
11fdf7f2 | 304 | std::string_view get_type_name() const override { return "creply"; } |
7c673cae FG |
305 | void print(ostream& o) const override { |
306 | o << "client_reply(???:" << get_tid(); | |
307 | o << " = " << get_result(); | |
308 | if (get_result() <= 0) { | |
309 | o << " " << cpp_strerror(get_result()); | |
310 | } | |
311 | if (head.op & CEPH_MDS_OP_WRITE) { | |
312 | if (head.safe) | |
313 | o << " safe"; | |
314 | else | |
315 | o << " unsafe"; | |
316 | } | |
317 | o << ")"; | |
318 | } | |
319 | ||
320 | // serialization | |
321 | void decode_payload() override { | |
11fdf7f2 TL |
322 | auto p = payload.cbegin(); |
323 | decode(head, p); | |
324 | decode(trace_bl, p); | |
325 | decode(extra_bl, p); | |
326 | decode(snapbl, p); | |
327 | ceph_assert(p.end()); | |
7c673cae FG |
328 | } |
329 | void encode_payload(uint64_t features) override { | |
11fdf7f2 TL |
330 | using ceph::encode; |
331 | encode(head, payload); | |
332 | encode(trace_bl, payload); | |
333 | encode(extra_bl, payload); | |
334 | encode(snapbl, payload); | |
7c673cae FG |
335 | } |
336 | ||
337 | ||
338 | // dir contents | |
339 | void set_extra_bl(bufferlist& bl) { | |
340 | extra_bl.claim(bl); | |
341 | } | |
11fdf7f2 TL |
342 | bufferlist& get_extra_bl() { |
343 | return extra_bl; | |
344 | } | |
345 | const bufferlist& get_extra_bl() const { | |
7c673cae FG |
346 | return extra_bl; |
347 | } | |
348 | ||
349 | // trace | |
350 | void set_trace(bufferlist& bl) { | |
351 | trace_bl.claim(bl); | |
352 | } | |
353 | bufferlist& get_trace_bl() { | |
354 | return trace_bl; | |
355 | } | |
11fdf7f2 TL |
356 | const bufferlist& get_trace_bl() const { |
357 | return trace_bl; | |
358 | } | |
7c673cae FG |
359 | }; |
360 | ||
361 | #endif |