ceph/src/crush/crush.h 源代码解析
crush算法相关的数据结构有 crush_bucket 结构、crush_map 结构和 crush_rule 结构。
(1) crush_bucket
结构 crush_bucket 用于保存 bucket 相关的信息
struct crush_bucket {
__s32 id; /*bucket的id,一般为负值*/
__u16 type; /* 类型,如果是0,就是OSD设备 */
__u8 alg; /* bucket的选择算法*/
__u8 hash; /* bucket的hash函数*/
__u32 weight; /* bucket的权重*/
__u32 size; /* bucket下的item的数量*/
__s32 *items; /*子bucket在crush_bucket结构buckets数组的下标,这里特别要注意的是,其子item的crush_bucket结构体都统一保存在crush map结构中的buckets数组中,这里只保存其在数组中的下标*/
/*以下是随机排序选择算法的一些cache的参数 */
__u32 perm_x; /* 要选择的x*/
__u32 perm_n; /* 排列的总的元素*/
__u32 *perm; /*排列组合的结果*/
};
(2)crush_map
结构 crush_map 定义了静态的所有 Cluster Map 的 bucket。bucket 为动态申请的二维数组,保存了所有的 bucket 结构。
struct crush_map {
struct crush_bucket **buckets; /*动态二维数组,保存所有的bucket结构*/
struct crush_rule **rules; /*保存所有的Crush_rule */
__s32 max_buckets;
__u32 max_rules;
__s32 max_devices;
/* 在重新下降之前选择本地重试 */
__u32 choose_local_tries;
/*在重新下降之前选择使用后备排列的本地尝试*/
__u32 choose_local_fallback_tries;
/* 在放弃之前选择尝试*/
__u32 choose_total_tries;
/* 尝试选择内部下降一次为firstn模式; 拒绝重试外部下降。 请注意,这不适用于碰撞:在这种情况下,我们将按照惯例重试。 */
__u32 chooseleaf_descend_once;
/*如果非零,则将r馈入selectleaf,右移(r-1)位。 值为1最适合新群集。 对于想要限制重新排列的传统集群,值为3或4将使映射与先前的映射相比更好一些。*/
__u8 chooseleaf_vary_r;
/* 如果为true,则会使chooseleaf首先返回稳定的结果(如果没有本地重试),以便在某些设备出现故障时数据迁移将是最佳的。 */
__u8 chooseleaf_stable;
#ifndef __KERNEL__
/*.straw_calc的版本0(原始)有各种缺陷。 版本1修复了其中的一些。 */
__u8 straw_calc_version;
/*允许的桶algs是一个位掩码,这里的位位置是CRUSH_BUCKET_ *。 请注意,这些是*位*而不是CRUSH_BUCKET_ *值,所以我们需要或在一起(1 << CRUSH_BUCKET_WHATEVER)。 第0位不用于最小化混淆(桶类型值从1开始)。*/
__u32 allowed_bucket_algs;
__u32 *choose_tries;
#endif
};
(3)crush_rule
struct crush_rule {
__u32 len; /*steps的数组的长度*/
struct crush_rule_mask mask; /*ruleset相关的配置参数*/
struct crush_rule_step steps[0]; /*操作步*/
};
struct crush_rule_mask {
__u8 ruleset; /*ruleset的编号*/
__u8 type; /*类型*/
__u8 min_size; /*最小size*/
__u8 max_size; /*最大size*/
};
struct crush_rule_step {
__u32 op; /*step操作步的操作码*/
__s32 arg1; /*如果是take,参数就是选择的bucket的id号;如果是select,就是选择的数量*/
__s32 arg2; /*如果是select,是选择的类型*/
};