上一篇介绍了ceph存储在上两层的消息逻辑,这一篇主要介绍一下读写操作在底两层的流程。下图是上一篇消息流程的一个总结。
上
在ceph中,读写操作由于分布式存储的原因,故走了不同流程。
对于读操作而言:
1.客户端直接计算出存储数据所属于的主osd,直接给主osd上发送消息。
2.主osd收到消息后,可以调用Filestore直接读取处在底层文件系统中的主pg里面的内容然后返回给客户端。具体调用函数在ReplicatedPG::do_osd_ops中实现。
读操作代码流程如图:
如我们之前说的,当确定读操作为主osd的消息时(CEPH_MSG_OSD_OP类型),会调用到ReplicatePG::do_osd_op函数,该函数对类型做进一步判断,当发现为读类型(CEPH_OSD_OP_READ)时,会调用FileStore中的函数对磁盘上数据进行读。
int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
{
……
switch (op.op) {
……
case CEPH_OSD_OP_READ:
++ctx->num_read;
{
// read into a buffer
bufferlist bl;
int r = osd->store->read(coll, soid, op.extent.offset, op.extent.length, bl);
// 调用FileStore::read从底层文件系统读取
……
}
case CEPH_OSD_OP_WRITE:
++ctx->num_write;
{
……//写操作只是做准备工作,并不实际的写
}
……
}
}
FileStore::read函数是底层具体的实现,会通过调用系统函数如::open,::pread,::close等函数来完成具体的操作。
int FileStore::read(
coll_t cid,
const ghobject_t& oid,
uint64_t offset,
size_t len,
bufferlist& bl,
bool allow_eio)
{
……
int r = lfn_open(cid, oid, false, &fd);
……
got = safe_pread(**fd, bptr.c_str(), len, offset);
//FileStore::safe_pread中调用了::pread
……
lfn_close(fd);
……
}