aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/crush/crush.c
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2009-10-06 14:31:11 -0400
committerSage Weil <sage@newdream.net>2009-10-06 14:31:11 -0400
commit5ecc0a0f8128b1876e8614638deaed49cc8b174c (patch)
tree6b1511b0e3ec2a349a24faebc375548b14ee137a /fs/ceph/crush/crush.c
parentf24e9980eb860d8600cbe5ef3d2fd9295320d229 (diff)
ceph: CRUSH mapping algorithm
CRUSH is a pseudorandom data distribution function designed to map inputs onto a dynamic hierarchy of devices, while minimizing the extent to which inputs are remapped when the devices are added or removed. It includes some features that are specifically useful for storage, most notably the ability to map each input onto a set of N devices that are separated across administrator-defined failure domains. CRUSH is used to distribute data across the cluster of Ceph storage nodes. More information about CRUSH can be found in this paper: http://www.ssrc.ucsc.edu/Papers/weil-sc06.pdf Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/crush/crush.c')
-rw-r--r--fs/ceph/crush/crush.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/fs/ceph/crush/crush.c b/fs/ceph/crush/crush.c
new file mode 100644
index 000000000000..13755cdc4fb3
--- /dev/null
+++ b/fs/ceph/crush/crush.c
@@ -0,0 +1,140 @@
1
2#ifdef __KERNEL__
3# include <linux/slab.h>
4#else
5# include <stdlib.h>
6# include <assert.h>
7# define kfree(x) do { if (x) free(x); } while (0)
8# define BUG_ON(x) assert(!(x))
9#endif
10
11#include "crush.h"
12
13/**
14 * crush_get_bucket_item_weight - Get weight of an item in given bucket
15 * @b: bucket pointer
16 * @p: item index in bucket
17 */
18int crush_get_bucket_item_weight(struct crush_bucket *b, int p)
19{
20 if (p >= b->size)
21 return 0;
22
23 switch (b->alg) {
24 case CRUSH_BUCKET_UNIFORM:
25 return ((struct crush_bucket_uniform *)b)->item_weight;
26 case CRUSH_BUCKET_LIST:
27 return ((struct crush_bucket_list *)b)->item_weights[p];
28 case CRUSH_BUCKET_TREE:
29 if (p & 1)
30 return ((struct crush_bucket_tree *)b)->node_weights[p];
31 return 0;
32 case CRUSH_BUCKET_STRAW:
33 return ((struct crush_bucket_straw *)b)->item_weights[p];
34 }
35 return 0;
36}
37
38/**
39 * crush_calc_parents - Calculate parent vectors for the given crush map.
40 * @map: crush_map pointer
41 */
42void crush_calc_parents(struct crush_map *map)
43{
44 int i, b, c;
45
46 for (b = 0; b < map->max_buckets; b++) {
47 if (map->buckets[b] == NULL)
48 continue;
49 for (i = 0; i < map->buckets[b]->size; i++) {
50 c = map->buckets[b]->items[i];
51 BUG_ON(c >= map->max_devices ||
52 c < -map->max_buckets);
53 if (c >= 0)
54 map->device_parents[c] = map->buckets[b]->id;
55 else
56 map->bucket_parents[-1-c] = map->buckets[b]->id;
57 }
58 }
59}
60
61void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b)
62{
63 kfree(b->h.perm);
64 kfree(b->h.items);
65 kfree(b);
66}
67
68void crush_destroy_bucket_list(struct crush_bucket_list *b)
69{
70 kfree(b->item_weights);
71 kfree(b->sum_weights);
72 kfree(b->h.perm);
73 kfree(b->h.items);
74 kfree(b);
75}
76
77void crush_destroy_bucket_tree(struct crush_bucket_tree *b)
78{
79 kfree(b->node_weights);
80 kfree(b);
81}
82
83void crush_destroy_bucket_straw(struct crush_bucket_straw *b)
84{
85 kfree(b->straws);
86 kfree(b->item_weights);
87 kfree(b->h.perm);
88 kfree(b->h.items);
89 kfree(b);
90}
91
92void crush_destroy_bucket(struct crush_bucket *b)
93{
94 switch (b->alg) {
95 case CRUSH_BUCKET_UNIFORM:
96 crush_destroy_bucket_uniform((struct crush_bucket_uniform *)b);
97 break;
98 case CRUSH_BUCKET_LIST:
99 crush_destroy_bucket_list((struct crush_bucket_list *)b);
100 break;
101 case CRUSH_BUCKET_TREE:
102 crush_destroy_bucket_tree((struct crush_bucket_tree *)b);
103 break;
104 case CRUSH_BUCKET_STRAW:
105 crush_destroy_bucket_straw((struct crush_bucket_straw *)b);
106 break;
107 }
108}
109
110/**
111 * crush_destroy - Destroy a crush_map
112 * @map: crush_map pointer
113 */
114void crush_destroy(struct crush_map *map)
115{
116 int b;
117
118 /* buckets */
119 if (map->buckets) {
120 for (b = 0; b < map->max_buckets; b++) {
121 if (map->buckets[b] == NULL)
122 continue;
123 crush_destroy_bucket(map->buckets[b]);
124 }
125 kfree(map->buckets);
126 }
127
128 /* rules */
129 if (map->rules) {
130 for (b = 0; b < map->max_rules; b++)
131 kfree(map->rules[b]);
132 kfree(map->rules);
133 }
134
135 kfree(map->bucket_parents);
136 kfree(map->device_parents);
137 kfree(map);
138}
139
140