Ceph OSD 如何处理读取消息?(Firefly 及更高版本)
当一个 OSD 处理一个操作时,它会被 排队到 PG,会被 添加到 op_wq 工作队列(或者如果 PG 的 queue_op 方法发现它必须等待 OSDMap),则会被 异步地从队列中移除。 移除队列的操作由 ReplicatedPG::do_request 方法处理,该方法 调用 do_op 方法,因为它是 CEPH_MSG_OSD_OP。一个 OpContext 被分配并且被 执行。
2014-02-24 09:28:34.571489 7fc18006f700 10 osd.4 pg_epoch: 26 pg[3.7s0( v 26'1 (0'0,26'1] local-les=26 n=1 ec=25 les/c 26/26 25/25/25) [4,6,9] r=0 lpr=25 crt=0’0 lcod 0’0 mlcod 0’0 active+clean] execute_ctx 0x7fc16c08a3b0
一个 事务(要么是一个用于 复制后端的 RPGTransaction,要么是一个用于 纠删码后端的 ECTransaction)从 PGBackend 获取。事务被附加到一个 OpContext(该 OpContext 由 do_op 分配)。请注意,在下面的日志行中,虽然显示了 do_op,但它 来自 execute_ctx 方法。
2014-02-24 09:28:34.571563 7fc18006f700 10 osd.4 pg_epoch: 26 pg[3.7s0( v 26'1 (0'0,26'1] local-les=26 n=1 ec=25 les/c 26/26 25/25/25) [4,6,9] r=0 lpr=25 crt=0’0 lcod 0’0 mlcod 0’0 active+clean] do_op 847441d7/SOMETHING/head//3 [read 0~4194304] ov 26’1
execute_ctx 方法 调用 prepare_transaction,后者 调用 do_osd_ops,后者 准备 CEPH_OSD_OP_READ。
2014-02-24 09:28:34.571663 7fc18006f700 10 osd.4 pg_epoch: 26 pg[3.7s0( v 26'1 (0'0,26'1] local-les=26 n=1 ec=25 les/c 26/26 25/25/25) [4,6,9] r=0 lpr=25 crt=0’0 lcod 0’0 mlcod 0’0 active+clean] async_read noted for 847441d7/SOMETHING/head//3
execute_ctx 方法在 prepare_transaction 返回时继续,并 创建 MOSDOpReply 对象。然后它 调用 start_async_reads,后者 在后端上调用 objects_read_async(即 ReplicatedBackend::objects_read_async 或 ECBackend::objects_read_async)。当读取完成时(此处不探讨此代码路径),它调用 OnReadComplete::finish 方法(因为 OnReadComplete 对象作为 objects_read_async 的参数提供),后者调用 ReplicatedPG::OpContext::finish_read,每次读取完成时(即,如果从纠删码池读取,则为每个块),后者调用 ReplicatedPG::complete_read_ctx(如果没有待处理的读取),后者 将回复发送给客户端。