Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) ****************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) RDMA Transport (RTRS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) ****************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) RTRS (RDMA Transport) is a reliable high speed transport library
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) which provides support to establish optimal number of connections
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) between client and server machines using RDMA (InfiniBand, RoCE, iWarp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) transport. It is optimized to transfer (read/write) IO blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) In its core interface it follows the BIO semantics of providing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) possibility to either write data from an sg list to the remote side
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) or to request ("read") data transfer from the remote side into a given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) sg list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) RTRS provides I/O fail-over and load-balancing capabilities by using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) multipath I/O (see "add_path" and "mp_policy" configuration entries in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) Documentation/ABI/testing/sysfs-class-rtrs-client).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) RTRS is used by the RNBD (RDMA Network Block Device) modules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) ==================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) Transport protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) ==================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) Overview
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) --------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) An established connection between a client and a server is called rtrs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) session. A session is associated with a set of memory chunks reserved on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) server side for a given client for rdma transfer. A session
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) consists of multiple paths, each representing a separate physical link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) between client and server. Those are used for load balancing and failover.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) Each path consists of as many connections (QPs) as there are cpus on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) the client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) When processing an incoming write or read request, rtrs client uses memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) chunks reserved for him on the server side. Their number, size and addresses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) need to be exchanged between client and server during the connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) establishment phase. Apart from the memory related information client needs to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) inform the server about the session name and identify each path and connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) individually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) On an established session client sends to server write or read messages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) Server uses immediate field to tell the client which request is being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) acknowledged and for errno. Client uses immediate field to tell the server
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) which of the memory chunks has been accessed and at which offset the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) can be found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) Module parameter always_invalidate is introduced for the security problem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) discussed in LPC RDMA MC 2019. When always_invalidate=Y, on the server side we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) invalidate each rdma buffer before we hand it over to RNBD server and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) then pass it to the block layer. A new rkey is generated and registered for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) buffer after it returns back from the block layer and RNBD server.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) The new rkey is sent back to the client along with the IO result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) The procedure is the default behaviour of the driver. This invalidation and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) registration on each IO causes performance drop of up to 20%. A user of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) driver may choose to load the modules with this mechanism switched off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) (always_invalidate=N), if he understands and can take the risk of a malicious
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) client being able to corrupt memory of a server it is connected to. This might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) be a reasonable option in a scenario where all the clients and all the servers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) are located within a secure datacenter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) Connection establishment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) ------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 1. Client starts establishing connections belonging to a path of a session one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) by one via attaching RTRS_MSG_CON_REQ messages to the rdma_connect requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) Those include uuid of the session and uuid of the path to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) established. They are used by the server to find a persisting session/path or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) to create a new one when necessary. The message also contains the protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) version and magic for compatibility, total number of connections per session
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) (as many as cpus on the client), the id of the current connection and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) the reconnect counter, which is used to resolve the situations where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) client is trying to reconnect a path, while server is still destroying the old
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 2. Server accepts the connection requests one by one and attaches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) RTRS_MSG_CONN_RSP messages to the rdma_accept. Apart from magic and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) protocol version, the messages include error code, queue depth supported by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) the server (number of memory chunks which are going to be allocated for that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) session) and the maximum size of one io, RTRS_MSG_NEW_RKEY_F flags is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) when always_invalidate=Y.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 3. After all connections of a path are established client sends to server the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) RTRS_MSG_INFO_REQ message, containing the name of the session. This message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) requests the address information from the server.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 4. Server replies to the session info request message with RTRS_MSG_INFO_RSP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) which contains the addresses and keys of the RDMA buffers allocated for that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) session.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 5. Session becomes connected after all paths to be established are connected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) (i.e. steps 1-4 finished for all paths requested for a session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 6. Server and client exchange periodically heartbeat messages (empty rdma
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) messages with an immediate field) which are used to detect a crash on remote
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) side or network outage in an absence of IO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 7. On any RDMA related error or in the case of a heartbeat timeout, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) corresponding path is disconnected, all the inflight IO are failed over to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) healthy path, if any, and the reconnect mechanism is triggered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) CLT                                     SRV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) *for each connection belonging to a path and for each path:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) RTRS_MSG_CON_REQ  ------------------->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)                    <------------------- RTRS_MSG_CON_RSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) *after all connections are established:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) RTRS_MSG_INFO_REQ ------------------->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)                    <------------------- RTRS_MSG_INFO_RSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *heartbeat is started from both sides:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)                    -------------------> [RTRS_HB_MSG_IMM]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) [RTRS_HB_MSG_ACK] <-------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) [RTRS_HB_MSG_IMM] <-------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)                    -------------------> [RTRS_HB_MSG_ACK]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) IO path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) -------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * Write (always_invalidate=N) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 1. When processing a write request client selects one of the memory chunks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) on the server side and rdma writes there the user data, user header and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) RTRS_MSG_RDMA_WRITE message. Apart from the type (write), the message only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) contains size of the user header. The client tells the server which chunk has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) been accessed and at what offset the RTRS_MSG_RDMA_WRITE can be found by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) using the IMM field.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 2. When confirming a write request server sends an "empty" rdma message with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) an immediate field. The 32 bit field is used to specify the outstanding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) inflight IO and for the error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) CLT                                                          SRV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) usr_data + usr_hdr + rtrs_msg_rdma_write -----------------> [RTRS_IO_REQ_IMM]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) [RTRS_IO_RSP_IMM]                        <----------------- (id + errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * Write (always_invalidate=Y) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 1. When processing a write request client selects one of the memory chunks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) on the server side and rdma writes there the user data, user header and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) RTRS_MSG_RDMA_WRITE message. Apart from the type (write), the message only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) contains size of the user header. The client tells the server which chunk has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) been accessed and at what offset the RTRS_MSG_RDMA_WRITE can be found by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) using the IMM field, Server invalidate rkey associated to the memory chunks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) first, when it finishes, pass the IO to RNBD server module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 2. When confirming a write request server sends an "empty" rdma message with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) an immediate field. The 32 bit field is used to specify the outstanding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) inflight IO and for the error code. The new rkey is sent back using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) SEND_WITH_IMM WR, client When it recived new rkey message, it validates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) the message and finished IO after update rkey for the rbuffer, then post
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) back the recv buffer for later use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) CLT                                                          SRV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) usr_data + usr_hdr + rtrs_msg_rdma_write -----------------> [RTRS_IO_REQ_IMM]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) [RTRS_MSG_RKEY_RSP]                     <----------------- (RTRS_MSG_RKEY_RSP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) [RTRS_IO_RSP_IMM]                        <----------------- (id + errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * Read (always_invalidate=N)*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 1. When processing a read request client selects one of the memory chunks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) on the server side and rdma writes there the user header and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) RTRS_MSG_RDMA_READ message. This message contains the type (read), size of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) the user header, flags (specifying if memory invalidation is necessary) and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) list of addresses along with keys for the data to be read into.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 2. When confirming a read request server transfers the requested data first,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) attaches an invalidation message if requested and finally an "empty" rdma
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) message with an immediate field. The 32 bit field is used to specify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) outstanding inflight IO and the error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) CLT                                           SRV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) usr_hdr + rtrs_msg_rdma_read --------------> [RTRS_IO_REQ_IMM]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) [RTRS_IO_RSP_IMM]            <-------------- usr_data + (id + errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) or in case client requested invalidation:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) [RTRS_IO_RSP_IMM_W_INV]      <-------------- usr_data + (INV) + (id + errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * Read (always_invalidate=Y)*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 1. When processing a read request client selects one of the memory chunks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) on the server side and rdma writes there the user header and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) RTRS_MSG_RDMA_READ message. This message contains the type (read), size of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) the user header, flags (specifying if memory invalidation is necessary) and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) list of addresses along with keys for the data to be read into.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) Server invalidate rkey associated to the memory chunks first, when it finishes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) passes the IO to RNBD server module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 2. When confirming a read request server transfers the requested data first,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) attaches an invalidation message if requested and finally an "empty" rdma
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) message with an immediate field. The 32 bit field is used to specify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) outstanding inflight IO and the error code. The new rkey is sent back using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) SEND_WITH_IMM WR, client When it recived new rkey message, it validates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) the message and finished IO after update rkey for the rbuffer, then post
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) back the recv buffer for later use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) CLT                                           SRV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) usr_hdr + rtrs_msg_rdma_read --------------> [RTRS_IO_REQ_IMM]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) [RTRS_IO_RSP_IMM]            <-------------- usr_data + (id + errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) [RTRS_MSG_RKEY_RSP]	     <----------------- (RTRS_MSG_RKEY_RSP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) or in case client requested invalidation:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) [RTRS_IO_RSP_IMM_W_INV]      <-------------- usr_data + (INV) + (id + errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) =========================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) Contributors List(in alphabetical order)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) =========================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) Danil Kipnis <danil.kipnis@profitbricks.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) Fabian Holler <mail@fholler.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) Jack Wang <jinpu.wang@profitbricks.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) Kleber Souza <kleber.souza@profitbricks.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) Lutz Pogrell <lutz.pogrell@cloud.ionos.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) Milind Dumbare <Milind.dumbare@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) Roman Penyaev <roman.penyaev@profitbricks.com>