1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
16 #ifndef CEPH_MCLIENTREPLY_H
17 #define CEPH_MCLIENTREPLY_H
19 #include "include/types.h"
20 #include "include/fs_types.h"
21 #include "MClientRequest.h"
23 #include "msg/Message.h"
24 #include "include/ceph_features.h"
25 #include "common/errno.h"
29 * MClientReply - container message for MDS reply to a client's MClientRequest
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
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.
40 * for readdir replies:
41 * dir_contents is a vector of InodeStat*'s.
43 * that's mostly it, i think!
49 // this matches ceph_mds_reply_lease
54 LeaseStat() : mask(0), duration_ms(0), seq(0) {}
55 LeaseStat(__u16 msk
, __u32 dur
, __u32 sq
) : mask
{msk
}, duration_ms
{dur
}, seq
{sq
} {}
57 void decode(bufferlist::const_iterator
&bl
, const uint64_t features
) {
59 if (features
== (uint64_t)-1) {
62 decode(duration_ms
, bl
);
68 decode(duration_ms
, bl
);
74 inline ostream
& operator<<(ostream
& out
, const LeaseStat
& l
) {
75 return out
<< "lease(mask " << l
.mask
<< " dur " << l
.duration_ms
<< ")";
79 // mds distribution hints
84 DirStat() : auth(CDIR_AUTH_PARENT
) {}
85 DirStat(bufferlist::const_iterator
& p
, const uint64_t features
) {
89 void decode(bufferlist::const_iterator
& p
, const uint64_t features
) {
91 if (features
== (uint64_t)-1) {
105 // see CDir::encode_dirstat for encoder.
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;
125 fragtree_t dirfragtree
;
126 string symlink
; // symlink content (if symlink)
128 ceph_dir_layout dir_layout
;
132 bufferlist inline_data
;
133 version_t inline_version
;
141 InodeStat(bufferlist::const_iterator
& p
, const uint64_t features
) {
145 void decode(bufferlist::const_iterator
&p
, const uint64_t features
) {
147 if (features
== (uint64_t)-1) {
150 decode(vino
.snapid
, p
);
153 decode(xattr_version
, p
);
156 ceph_file_layout legacy_layout
;
157 decode(legacy_layout
, p
);
158 layout
.from_legacy(legacy_layout
);
163 decode(time_warp_seq
, p
);
166 decode(truncate_size
, p
);
167 decode(truncate_seq
, 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
);
180 decode(dir_layout
, p
);
182 decode(inline_version
, p
);
183 decode(inline_data
, p
);
185 decode(layout
.pool_ns
, p
);
187 decode(change_attr
, p
);
194 decode(snap_btime
, p
);
195 } // else remains zero
200 decode(vino
.snapid
, p
);
203 decode(xattr_version
, p
);
206 ceph_file_layout legacy_layout
;
207 decode(legacy_layout
, p
);
208 layout
.from_legacy(legacy_layout
);
213 decode(time_warp_seq
, p
);
216 decode(truncate_size
, p
);
217 decode(truncate_seq
, 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
);
230 if (features
& CEPH_FEATURE_DIRLAYOUTHASH
)
231 decode(dir_layout
, p
);
233 memset(&dir_layout
, 0, sizeof(dir_layout
));
237 if (features
& CEPH_FEATURE_MDS_INLINE_DATA
) {
238 decode(inline_version
, p
);
239 decode(inline_data
, p
);
241 inline_version
= CEPH_INLINE_NONE
;
244 if (features
& CEPH_FEATURE_MDS_QUOTA
)
247 quota
= quota_info_t
{};
249 if ((features
& CEPH_FEATURE_FS_FILE_LAYOUT_V2
))
250 decode(layout
.pool_ns
, p
);
252 if ((features
& CEPH_FEATURE_FS_BTIME
)) {
254 decode(change_attr
, p
);
262 // see CInode::encode_inodestat for encoder.
265 struct openc_response_t
{
266 _inodeno_t created_ino
;
267 interval_set
<inodeno_t
> delegated_inos
;
270 void encode(ceph::buffer::list
& bl
) const {
272 ENCODE_START(1, 1, bl
);
273 encode(created_ino
, bl
);
274 encode(delegated_inos
, bl
);
277 void decode(bufferlist::const_iterator
&p
) {
280 decode(created_ino
, p
);
281 decode(delegated_inos
, p
);
284 } __attribute__ ((__may_alias__
));
285 WRITE_CLASS_ENCODER(openc_response_t
)
287 class MClientReply
: public SafeMessage
{
290 struct ceph_mds_reply_head head
{};
295 int get_op() const { return head
.op
; }
297 void set_mdsmap_epoch(epoch_t e
) { head
.mdsmap_epoch
= e
; }
298 epoch_t
get_mdsmap_epoch() const { return head
.mdsmap_epoch
; }
300 int get_result() const {
301 return ceph_to_hostos_errno((__s32
)(__u32
)head
.result
);
304 void set_result(int r
) { head
.result
= r
; }
306 void set_unsafe() { head
.safe
= 0; }
308 bool is_safe() const { return head
.safe
; }
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
;
320 ~MClientReply() override
{}
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());
330 if (head
.op
& CEPH_MDS_OP_WRITE
) {
340 void decode_payload() override
{
341 auto p
= payload
.cbegin();
346 ceph_assert(p
.end());
348 void encode_payload(uint64_t features
) override
{
350 encode(head
, payload
);
351 encode(trace_bl
, payload
);
352 encode(extra_bl
, payload
);
353 encode(snapbl
, payload
);
358 void set_extra_bl(bufferlist
& bl
) {
361 bufferlist
& get_extra_bl() {
364 const bufferlist
& get_extra_bl() const {
369 void set_trace(bufferlist
& bl
) {
372 bufferlist
& get_trace_bl() {
375 const bufferlist
& get_trace_bl() const {
379 template<class T
, typename
... Args
>
380 friend boost::intrusive_ptr
<T
> ceph::make_message(Args
&&... args
);