Hi Sage, We could have: struct crush_choose_arg { __u32 bucket_id; __u32 num_items; __u32 *ids; // override the bucket items for placement __u32 num_positions; __u32 *weights; // size is num_positions*num_items }; struct crush_choose_arg_map { struct crush_choose_arg *args; __u32 size; }; and void crush_init_workspace(const struct crush_map *m, struct crush_choose_arg_map *arg_map, void *v) { ... if (m->buckets[b]->id == arg_map[b]->bucket_id) w->work[b]->arg = arg_map[b]; ... } with struct crush_work_bucket { __u32 perm_x; /* @x for which *perm is defined */ __u32 perm_n; /* num elements of *perm that are permuted/defined */ __u32 *perm; /* Permutation of the bucket's items */ struct crush_choose_arg *arg; }; There would be no need to change the code path since crush_bucket_choose already is given the crush_work_bucket. And crush_init_workspace already has logic that is algorithm dependent. And all the sanity checks could be done in crush_init_workspace so that the choose function only does what's absolutely necessary. What do you think ? Cheers -- Loïc Dachary, Artisan Logiciel Libre -- To unsubscribe from this list: send the line "unsubscribe ceph-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html