@@ -336,21 +336,17 @@ class MClientReply final : public MMDSOp {
336336 epoch_t get_mdsmap_epoch () const { return head.mdsmap_epoch ; }
337337
338338 int get_result () const {
339- #ifdef _WIN32
340- // libclient and libcephfs return CEPHFS_E* errors, which are basically
341- // Linux errno codes. If we convert mds errors to host errno values, we
342- // end up mixing error codes.
343- //
344- // For Windows, we'll preserve the original error value, which is expected
345- // to be a linux (CEPHFS_E*) error. It may be worth doing the same for
346- // other platforms.
339+ // MDS now uses host errors, as defined in errno.cc, for current platform.
340+ // errorcode32_t is converting, internally, the error code from host to ceph, when encoding, and vice versa,
341+ // when decoding, resulting having LINUX codes on the wire, and HOST code on the receiver.
342+ // assumes this code is executing after decode_payload() function has been called
347343 return head.result ;
348- #else
349- return ceph_to_hostos_errno ((__s32)(__u32)head.result );
350- #endif
351344 }
352345
353- void set_result (int r) { head.result = r; }
346+ // errorcode32_t is used in decode/encode methods
347+ void set_result (int r) {
348+ head.result = r;
349+ }
354350
355351 void set_unsafe () { head.safe = 0 ; }
356352
@@ -363,8 +359,8 @@ class MClientReply final : public MMDSOp {
363359 memset (&head, 0 , sizeof (head));
364360 header.tid = req.get_tid ();
365361 head.op = req.get_op ();
366- head.result = result;
367362 head.safe = 1 ;
363+ set_result (result);
368364 }
369365 ~MClientReply () final {}
370366
@@ -390,14 +386,30 @@ class MClientReply final : public MMDSOp {
390386 using ceph::decode;
391387 auto p = payload.cbegin ();
392388 decode (head, p);
389+ // errorcode32_t implements conversion from/to different host error codes
390+ // casting needed since error codes are signed int32 and head.result is unsigned int32
391+ // errortype_t::code_t is alias for __s32, which is signed
392+ // ceph_mds_reply_head::code_t is alias for __le32 which is unsigned
393+ errorcode32_t temp;
394+ temp.set_wire_to_host (static_cast <errorcode32_t ::code_t >(head.result ));
395+ head.result = static_cast <ceph_mds_reply_head::code_t >(temp.code );
393396 decode (trace_bl, p);
394397 decode (extra_bl, p);
395398 decode (snapbl, p);
396399 ceph_assert (p.end ());
397400 }
398401 void encode_payload (uint64_t features) override {
399402 using ceph::encode;
400- encode (head, payload);
403+ // errorcode32_t implements conversion from/to different host error codes
404+ // casting needed since error codes are signed int32 and head.result is unsigned int32
405+ // errortype_t::code_t is alias for __s32, which is signed
406+ // ceph_mds_reply_head::code_t is alias for __le32 which is unsigned
407+ // the Messenger layer expects to be able to call encode_payload multiple times on message retries
408+ // this is the reason we must copy the head and to modify the copy's 'result' field
409+ auto temp_head = head;
410+ errorcode32_t temp{static_cast <errorcode32_t ::code_t >(temp_head.result )};
411+ temp_head.result = static_cast <ceph_mds_reply_head::code_t >(temp.get_host_to_wire ());
412+ encode (temp_head, payload);
401413 encode (trace_bl, payload);
402414 encode (extra_bl, payload);
403415 encode (snapbl, payload);
0 commit comments