关于ceph 客户端的flatten操作

发布于 2021-12-01 10:21:29 字数 382 浏览 825 评论 4

@一只小江 你好,想跟你请教个问题:

看了你关于客户端流程的分析,收益很大,谢谢你的分享。

我想请教你关于在客户端的rbd flatten操作的相关事宜,在rbd flatten操作的时候,会将重合数据重新写入新的image,我加日志后,发现其会以4M的块向相应的oid写数据。但这些数据从哪里来,一直没有追踪到,通过自已添加的log看,大致判断可能是读出来的,但依旧不能确定。且自己对读流程不是很清晰,不明白读到数据后的回调机制。

麻烦您能帮我解惑,不吝赐教!谢谢您。


如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

爱的故事 2021-12-01 15:02:59

引用来自“百草权舆”的评论

@一只小江 

你好,谢谢你在百忙之中能回帮复我的问题。

关于flatten操作,根据你的给的启示,我对其具体的流程又做了具体的调查和分析,如你所说,其通过状态转换来实现具体的功能,设计相当的精妙。

但还有一些小的细节需要和你探讨,望不吝赐教。

1flatten操作可以分为三次操作,写-读-写, 第一次写只是空数据,未有相关的动作,只是进入了初始状态,在写动作的异步回调函数中(should_complete)状态转变,且发送读请求,读请求的完成回调后,收集读到的数据置于,然后发起第三次写请求,将相应的数据 写到osd。

第三次的写请求,由谁发起的呢?或者说是谁的回调呢?

最后,真心谢谢你的上次回答。

清风夜微凉 2021-12-01 14:56:59

@一只小江 

你好,谢谢你在百忙之中能回帮复我的问题。

关于flatten操作,根据你的给的启示,我对其具体的流程又做了具体的调查和分析,如你所说,其通过状态转换来实现具体的功能,设计相当的精妙。

但还有一些小的细节需要和你探讨,望不吝赐教。

1flatten操作可以分为三次操作,写-读-写, 第一次写只是空数据,未有相关的动作,只是进入了初始状态,在写动作的异步回调函数中(should_complete)状态转变,且发送读请求,读请求的完成回调后,收集读到的数据置于,然后发起第三次写请求,将相应的数据 写到osd。

第三次的写请求,由谁发起的呢?或者说是谁的回调呢?

最后,真心谢谢你的上次回答。

夜司空 2021-12-01 14:43:21

感谢你的回复。 还有一个小问题需要请教。 关于flatten的操作,我们知道,第一次是一个空的写请求,第二次是一个读请求,第三次将第二次的读请求获取的数据发送一个写请求。 但我们从代码可以看到,第二次读请求是获取所有ovelap数据,但第三部分只是针对某一个objectid的写请求,这两个部分难道 不应该是读一个具体的overlap中object id的数据,再将其写到新的objectid中吗?

叹沉浮 2021-12-01 13:11:41

这部分代码当初确实看过,但是现在也想不起来那么详细的细节了。

1. 首先需要说明一下child_image的写入原理。原始parent_image经过快照snap。然后在根据snap创建clone。这里clone后的child_image是没有真正的将parent_image数据拷贝到child_image中(一开始时,一丁点数据都没拷贝)。直到child_image要写入数据时,假如写child_image的object_x中的一部分数据data_new(data_new的数据小于等于4M),则会先从parent_image读出object_x的数据data_old(data_old包含了object的大小,默认是4M)。这时把data_new覆盖到data_old上形成最新的data,再将这个data写入child_image中。

2.flatten的操作的原理同child_image的写入原理是一样。flatten操作会将parent与child重合的object统计出来set_object,然后向child_image的set_object中的每一个object发送一个写请求,这个写请求的size为0 data_new(0M),对于child_image的写入原理上面说了,这时出先从parent中读取对应的object的数据data_old(4M),然后再合并data_new与data_old,合并仍然是4M的data。再将这个data写入到child_image。

原理就是上述讲的内容,具体的代码可参考AioWrite req。

调用关系,最重要的生成一个

do_flatten()
flatten_with_progress()
librbd::flatten()
async_flatten()
AsyncFlattenRequest::send()
throttle->start_ops()
start_next_op()
AsyncFlattenObjectContext ::send()
AioWrite *req = new AioWrite()
req->send()

req有一个继承的类叫做AbstractWrite,这个类里边定义很重要的回调函数should_complete(),这个就是child_image写入操作的各个阶段,根据不同阶段会有不同的处理,这里包括了读取parent_image数据,合并数据date_new 与 data_old,合并后的数据写入child_image的各个阶段。
AioWrite ---> AbstractWrite 
AbstractWrite::should_complete()

flatten这部分代码写的很妙,值得去细细看,然后学会这些程序设计的思想。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文