Chinaunix首页 | 论坛 | 博客
  • 博客访问: 434908
  • 博文数量: 122
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 688
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-04 12:30
文章分类

全部博文(122)

文章存档

2017年(5)

2016年(4)

2015年(56)

2014年(41)

2013年(16)

我的朋友

分类: 其他平台

2015-02-02 20:17:46

原文地址:代码阅读 ceph kernel 作者:rachine2

mds, meta data server
mds client 在内核fs层面实现, 最终还是需要通过net与mdsc通信
fs层面接收mdsc发来的命令, 并在fs层面完成具体操作
osd, object storage daemon
osd client 在内核net层面实现
mon, monitor daemon




include/linux/ceph/ceph_frag.h
frag, 高8位 "bits" + 低24位 "value"


fs/ceph/
caps.c
ceph_check_caps(), 检查caps, 公共函数

dir.c
ceph_dir_fops
ceph_dir_iops

file.c, 访问具体文件
struct file_operations ceph_file_fops

ceph_sync_write(), 与osd通信, 写入
ceph_osdc_new_request()
ceph_osdc_start_request()
ceph_osdc_wait_request()



inode.c, 使用rbtree 维护inode对应的一个或多个mds
ceph_file_iops, file inode 入口
通过和mdsc进行通信, 获取attr, xattr设置

ceph_setxattr() =>
int dirty = __ceph_mark_dirty_caps() 检查dirty cap并标记
__mark_inode_dirty(inode, dirty) 标识inode需要回写到磁盘

frag相关函数, 使用md5来为inode进行索引, 红黑树查找

__ceph_do_pending_vmtruncate() ????

ioctl.h,
ioctl.c,
ceph_ioctl(), 主入口
get/set layout, file/inode 在当前/远端上的layout,
参考struct ceph_ioctl_layout



ceph_choose_frag()
=> 调用__ceph_find_frag(),
frag->split_by == 0, 即frag没有child, 返回当前frag,
frag->split_by > 0,
ceph_frag_make_child(), 搜索child,
ceph_frag_contains_value(), 只比较value部分, 返回匹配的child

__ceph_find_frag(), rbtree搜索frag
从ci->i_fragtree.rb_node



locks.c, 与POSIX兼容锁实现, 见flock(2)和fcntl(2)
(struct file_lock)->fl_flags & FL_POSIX
(struct file_lock)->fl_flags & FL_FLOCK

ceph_lock(), fcntl lock
ceph_flock(), flock
=> ceph_lock_message()

ceph_lock_message(), mdsc构造并发现req, 告知lock 变动



mds_client.c
ceph_mdsc_do_request(), 构造并命令net ceph发送mds相关req
在同目录下多个文件中使用,
CEPH_MDS_OP_***
__register_request(),
wait_for_completion_killable()
ceph_invalidate_dir_request()


__register_request(), =>
__insert_request() 将request按红黑树搜索, 插入mdsc->request_tree.rb_node

__do_request()
__choose_mds()
__ceph_lookup_mds_session()
complete_request()

__ceph_lookup_mds_session(mds_client, int mds),
用session保护连接的唯一性 ???

complete_request(mds_client, request)
执行回调和complete_all()

__choose_mds(),
根据inode获取mds, 否则返回随机mds
ceph_mdsmap_get_state(), state >= CEPH_MDS_STATE_ACTIVE, 得到的mds才有意义

register_session()
ceph_con_open(), net/ceph/messenger.c


mdsmap.c, 导入mds map



snap.c
什么是snap?
snap是如何实现的?
ceph的snap实现有什么问题?
内核中的snap纯粹实现split ?

snap基于inode,
每个snap属于一个realm, snap像目录结构一样, 包含某个目录下的子目录,
类似改名之类变动dir的操作, 会改变realm的parent指向,
导致一个realm snap包含其parent的snap,

struct ceph_snap_realm, fs/ceph/super.h

flush_snaps(),
对mdsc->snap_flush_list的所有成员, 调用
__ceph_flush_snaps(), caps.c,
将snap相关的cap和inode信息提交到mds


ceph_update_snap_trace(), 连接snap的历史操作, 提交到mds,
所有对于snap的操作都要记录
struct ceph_mds_reply_info_parsed.snapblob

ri 新参数导入的realm
realm, 与ri同inode, 系统现有的
if (le64_to_cpu(ri->seq) > realm->seq) {
seq: version ??? 后续操作 ???
即ri要合并到realm

build_snap_context()
合并realm->num_prior_parent_snaps + realm->num_snaps,
保存在realm->cached_context
参考file.c, ceph_sync_write(),
ceph_osdc_new_request(..., ci->i_snap_realm->cached_context, ...)

rebuild_snap_realms(), 对realm和realm->children, 执行build_snap_context()


ceph_queue_cap_snap(),
当snap建立后, 所有对目标inode的写入操作都会预先合并到snap,
capsnap->ci 指向(struct ceph_inode_info *ci)
如果建立snap时, inode正在写入, capsnap->writing = 1,
如果写入完成, 即建立cap_snap, __ceph_finish_cap_snap()


ceph_handle_snap(), 主入口, 在mds_client.c, dispatch()中调用
对CEPH_SNAP_OP_SPLIT 操作, 需要分割现有realm, 或新建,
参数 u64 split从输入参数中转换获取,
使用split_inos[] => vino => inode => ceph_inode,
丢弃oldrealm = ci->i_snap_realm,
直接使用新建/查找到的现有realm






super.h,
struct ceph_inode_frag,
int split_by; 什么意思 ???, 在fill_inode() 中写入


super.c,
mount() =>
ceph_mount() =>
create_fs_client(), ceph_mdsc_init(), ceph_real_mount() =>
open_root_dentry() =>
ceph_mdsc_create_request(), CEPH_MDS_OP_GETATTR
ceph_mdsc_do_request(), 构造mdsc, 获取远端mds client上保存的attr
即本地负责mount, 并在本地构造根目录"/", 但对应的具体信息由mds保存,
所以在构造根目录之前, 需要首先访问mds

create_fs_client(),
struct ceph_fs_client,
fsc->wb_wq, "ceph-writeback"
fsc->pg_inv_wq, "ceph-pg-invalid"
fsc->trunc_wq, "ceph-trunc"

ceph_mdsc_init(fsc)
mdsc->fsc = fsc;
fsc->mdsc = mdsc;
fsc与mdsc需要相互对应


net/ceph/ 网络接口, 有EXPORT_SYMBOL
messenger.c
queue_con() 主要队列入口, 调用系统work执行ceph_connection->work


net/ceph/crush, crush核心算法接口

mapper.c, uniform, list, 等bucket
不同算法下的不同实现

bucket_uniform_choose()

crush_bucket_choose() =>
bucket_XXX_choose(), 如 uniform, list, tree, straw

bucket_tree_choose(), 不是数组实现的二叉树
以cursh_bucket_tree.num_nodes作为root, 使用hash生成的随机树?

bucket_straw_choose() =>
纯粹的随机数 ???
straw, 稻草


crush_do_rule(), 计算rule与其他参数对应的map,
CRUSH_RULE_CHOOSE_INDEP:
调用crush_choose() => list/tree/straw/...
注意参数, o+osize, ugly code

crush_choose(), 搜索leaf, 核心搜索函数


osd_client.c
ceph_connection_operations osd_con_ops 入口, 输入参数 ceph_msg

ceph_osdc_handle_map(), 导入osd_map

handle_reply(), 回应


ceph_osdc_readpages(), 从page获取osd_client
ceph_osdc_new_request()
ceph_osdc_start_request()

struct ceph_connection_operations osd_con_ops 接口
引用计数和认证

osdmap.c

crush_decode(), 解析crush_map, 导入bucket, rules

osdmap_apply_incremental()
从memory data导入osdmap

ceph_calc_object_layout(),
__lookup_pg_pool(), 红黑树搜索 poolid,
ceph_object_layout, 计算出ol的成员pgid (pool group id)和stripe_unit并返回


ceph_calc_pg_primary()
=> calc_pg_raw()

calc_pg_raw(), 从osdmap导入pool group
osdmap->pg_pools, pool 红黑树root
crush_find_rule(), 定位rule
__lookup_pg_mapping(osdmap->pg_temp),
crush_do_rule()


messenger.c 内部通讯接口,
fs/ceph/mds_client.c, __do_request() =>
ceph_con_send() 发送req, 被mds/osd/mon共同调用的公共接口

con_work() 初始化时调用, 线程
=>
try_read() 接收req, 接收并直接解析TCP报文
try_write()

ceph_con_init(), 见
ceph_con_init(monc->client->msgr, monc->con), mon_client.c
ceph_con_init(osdc->client->msgr, monc->o_con), osd_client.c
=> con_work()

read_partial(), 从指定的connection上获取指定长度的data,
调用 ceph_tcp_recvmsg()

try_read(),
con->state 维护状态机, (只建立conn时用?)
CONNECTING,
process_banner(), 确认对端IP, port
process_connect(), 由con->in_reply.tag 作出回应
con->in_tag, message exchange protocol,
include/linux/ceph/msgr.h, CEPH_MSGR_TAG_* 宏

try_write(),
con->sock == NULL, 建立新连接
ceph_tcp_connect(), 在内核中维护tcp con, 很麻烦
write_partial_kvec(),
struct kvec, 维护用户态下内存
include/linux/ceph/messenger.h, struct ceph_connection->out_kvec[8],
/* sending header/footer data */
write_partial_msg_pages(),
con->out_msg, 作为payload传输

完成全部写操作, con->state设成WRITE_PENDING


prepare_write_connect(), 根据con->peer_name.type,
获得protocol: MON/OSD/MDS
banner, auth等等



mon_clinet.c, monitor




pagevec.c, page vector 页表数组

ceph_get_direct_page_vector(),
(struct page) * num + user_pages

调用get_user_pages()




阅读(2020) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~