aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/crush
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2009-11-07 23:18:22 -0500
committerSage Weil <sage@newdream.net>2009-11-07 23:18:22 -0500
commitfb690390e305ea51e1883b105c7d3c52d7100ba5 (patch)
treec099a71133225b1d22bba976e93dc6ab92a08986 /fs/ceph/crush
parent1654dd0cf5ee1827322aca156af7d96d757201c7 (diff)
ceph: make CRUSH hash function a bucket property
Make the integer hash function a property of the bucket it is used on. This allows us to gracefully add support for new hash functions without starting from scatch. Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/crush')
-rw-r--r--fs/ceph/crush/crush.h3
-rw-r--r--fs/ceph/crush/hash.c73
-rw-r--r--fs/ceph/crush/hash.h19
-rw-r--r--fs/ceph/crush/mapper.c16
4 files changed, 91 insertions, 20 deletions
diff --git a/fs/ceph/crush/crush.h b/fs/ceph/crush/crush.h
index 92c6b3c3a57..dcd7e752370 100644
--- a/fs/ceph/crush/crush.h
+++ b/fs/ceph/crush/crush.h
@@ -102,7 +102,8 @@ extern const char *crush_bucket_alg_name(int alg);
102struct crush_bucket { 102struct crush_bucket {
103 __s32 id; /* this'll be negative */ 103 __s32 id; /* this'll be negative */
104 __u16 type; /* non-zero; type=0 is reserved for devices */ 104 __u16 type; /* non-zero; type=0 is reserved for devices */
105 __u16 alg; /* one of CRUSH_BUCKET_* */ 105 __u8 alg; /* one of CRUSH_BUCKET_* */
106 __u8 hash; /* which hash function to use, CRUSH_HASH_* */
106 __u32 weight; /* 16-bit fixed point */ 107 __u32 weight; /* 16-bit fixed point */
107 __u32 size; /* num items */ 108 __u32 size; /* num items */
108 __s32 *items; 109 __s32 *items;
diff --git a/fs/ceph/crush/hash.c b/fs/ceph/crush/hash.c
index b438c5d2781..5873aed694b 100644
--- a/fs/ceph/crush/hash.c
+++ b/fs/ceph/crush/hash.c
@@ -1,5 +1,6 @@
1 1
2#include <linux/types.h> 2#include <linux/types.h>
3#include "hash.h"
3 4
4/* 5/*
5 * Robert Jenkins' function for mixing 32-bit values 6 * Robert Jenkins' function for mixing 32-bit values
@@ -20,7 +21,7 @@
20 21
21#define crush_hash_seed 1315423911 22#define crush_hash_seed 1315423911
22 23
23__u32 crush_hash32(__u32 a) 24static __u32 crush_hash32_rjenkins1(__u32 a)
24{ 25{
25 __u32 hash = crush_hash_seed ^ a; 26 __u32 hash = crush_hash_seed ^ a;
26 __u32 b = a; 27 __u32 b = a;
@@ -31,7 +32,7 @@ __u32 crush_hash32(__u32 a)
31 return hash; 32 return hash;
32} 33}
33 34
34__u32 crush_hash32_2(__u32 a, __u32 b) 35static __u32 crush_hash32_rjenkins1_2(__u32 a, __u32 b)
35{ 36{
36 __u32 hash = crush_hash_seed ^ a ^ b; 37 __u32 hash = crush_hash_seed ^ a ^ b;
37 __u32 x = 231232; 38 __u32 x = 231232;
@@ -42,7 +43,7 @@ __u32 crush_hash32_2(__u32 a, __u32 b)
42 return hash; 43 return hash;
43} 44}
44 45
45__u32 crush_hash32_3(__u32 a, __u32 b, __u32 c) 46static __u32 crush_hash32_rjenkins1_3(__u32 a, __u32 b, __u32 c)
46{ 47{
47 __u32 hash = crush_hash_seed ^ a ^ b ^ c; 48 __u32 hash = crush_hash_seed ^ a ^ b ^ c;
48 __u32 x = 231232; 49 __u32 x = 231232;
@@ -55,7 +56,7 @@ __u32 crush_hash32_3(__u32 a, __u32 b, __u32 c)
55 return hash; 56 return hash;
56} 57}
57 58
58__u32 crush_hash32_4(__u32 a, __u32 b, __u32 c, __u32 d) 59static __u32 crush_hash32_rjenkins1_4(__u32 a, __u32 b, __u32 c, __u32 d)
59{ 60{
60 __u32 hash = crush_hash_seed ^ a ^ b ^ c ^ d; 61 __u32 hash = crush_hash_seed ^ a ^ b ^ c ^ d;
61 __u32 x = 231232; 62 __u32 x = 231232;
@@ -69,7 +70,8 @@ __u32 crush_hash32_4(__u32 a, __u32 b, __u32 c, __u32 d)
69 return hash; 70 return hash;
70} 71}
71 72
72__u32 crush_hash32_5(__u32 a, __u32 b, __u32 c, __u32 d, __u32 e) 73static __u32 crush_hash32_rjenkins1_5(__u32 a, __u32 b, __u32 c, __u32 d,
74 __u32 e)
73{ 75{
74 __u32 hash = crush_hash_seed ^ a ^ b ^ c ^ d ^ e; 76 __u32 hash = crush_hash_seed ^ a ^ b ^ c ^ d ^ e;
75 __u32 x = 231232; 77 __u32 x = 231232;
@@ -84,3 +86,64 @@ __u32 crush_hash32_5(__u32 a, __u32 b, __u32 c, __u32 d, __u32 e)
84 crush_hashmix(y, e, hash); 86 crush_hashmix(y, e, hash);
85 return hash; 87 return hash;
86} 88}
89
90
91__u32 crush_hash32(int type, __u32 a)
92{
93 switch (type) {
94 case CRUSH_HASH_RJENKINS1:
95 return crush_hash32_rjenkins1(a);
96 default:
97 return 0;
98 }
99}
100
101__u32 crush_hash32_2(int type, __u32 a, __u32 b)
102{
103 switch (type) {
104 case CRUSH_HASH_RJENKINS1:
105 return crush_hash32_rjenkins1_2(a, b);
106 default:
107 return 0;
108 }
109}
110
111__u32 crush_hash32_3(int type, __u32 a, __u32 b, __u32 c)
112{
113 switch (type) {
114 case CRUSH_HASH_RJENKINS1:
115 return crush_hash32_rjenkins1_3(a, b, c);
116 default:
117 return 0;
118 }
119}
120
121__u32 crush_hash32_4(int type, __u32 a, __u32 b, __u32 c, __u32 d)
122{
123 switch (type) {
124 case CRUSH_HASH_RJENKINS1:
125 return crush_hash32_rjenkins1_4(a, b, c, d);
126 default:
127 return 0;
128 }
129}
130
131__u32 crush_hash32_5(int type, __u32 a, __u32 b, __u32 c, __u32 d, __u32 e)
132{
133 switch (type) {
134 case CRUSH_HASH_RJENKINS1:
135 return crush_hash32_rjenkins1_5(a, b, c, d, e);
136 default:
137 return 0;
138 }
139}
140
141const char *crush_hash_name(int type)
142{
143 switch (type) {
144 case CRUSH_HASH_RJENKINS1:
145 return "rjenkins1";
146 default:
147 return "unknown";
148 }
149}
diff --git a/fs/ceph/crush/hash.h b/fs/ceph/crush/hash.h
index 9ce89f85dc7..ff48e110e4b 100644
--- a/fs/ceph/crush/hash.h
+++ b/fs/ceph/crush/hash.h
@@ -1,12 +1,17 @@
1#ifndef _CRUSH_HASH_H 1#ifndef _CRUSH_HASH_H
2#define _CRUSH_HASH_H 2#define _CRUSH_HASH_H
3 3
4extern __u32 crush_hash32(__u32 a); 4#define CRUSH_HASH_RJENKINS1 0
5extern __u32 crush_hash32_2(__u32 a, __u32 b); 5
6extern __u32 crush_hash32_3(__u32 a, __u32 b, __u32 c); 6#define CRUSH_HASH_DEFAULT CRUSH_HASH_RJENKINS1
7extern __u32 crush_hash32_4(__u32 a, __u32 b, __u32 c, 7
8 __u32 d); 8extern const char *crush_hash_name(int type);
9extern __u32 crush_hash32_5(__u32 a, __u32 b, __u32 c, 9
10 __u32 d, __u32 e); 10extern __u32 crush_hash32(int type, __u32 a);
11extern __u32 crush_hash32_2(int type, __u32 a, __u32 b);
12extern __u32 crush_hash32_3(int type, __u32 a, __u32 b, __u32 c);
13extern __u32 crush_hash32_4(int type, __u32 a, __u32 b, __u32 c, __u32 d);
14extern __u32 crush_hash32_5(int type, __u32 a, __u32 b, __u32 c, __u32 d,
15 __u32 e);
11 16
12#endif 17#endif
diff --git a/fs/ceph/crush/mapper.c b/fs/ceph/crush/mapper.c
index 54f3f402af6..2523d448445 100644
--- a/fs/ceph/crush/mapper.c
+++ b/fs/ceph/crush/mapper.c
@@ -78,7 +78,7 @@ static int bucket_perm_choose(struct crush_bucket *bucket,
78 78
79 /* optimize common r=0 case */ 79 /* optimize common r=0 case */
80 if (pr == 0) { 80 if (pr == 0) {
81 s = crush_hash32_3(x, bucket->id, 0) % 81 s = crush_hash32_3(bucket->hash, x, bucket->id, 0) %
82 bucket->size; 82 bucket->size;
83 bucket->perm[0] = s; 83 bucket->perm[0] = s;
84 bucket->perm_n = 0xffff; /* magic value, see below */ 84 bucket->perm_n = 0xffff; /* magic value, see below */
@@ -103,7 +103,7 @@ static int bucket_perm_choose(struct crush_bucket *bucket,
103 unsigned p = bucket->perm_n; 103 unsigned p = bucket->perm_n;
104 /* no point in swapping the final entry */ 104 /* no point in swapping the final entry */
105 if (p < bucket->size - 1) { 105 if (p < bucket->size - 1) {
106 i = crush_hash32_3(x, bucket->id, p) % 106 i = crush_hash32_3(bucket->hash, x, bucket->id, p) %
107 (bucket->size - p); 107 (bucket->size - p);
108 if (i) { 108 if (i) {
109 unsigned t = bucket->perm[p + i]; 109 unsigned t = bucket->perm[p + i];
@@ -138,8 +138,8 @@ static int bucket_list_choose(struct crush_bucket_list *bucket,
138 int i; 138 int i;
139 139
140 for (i = bucket->h.size-1; i >= 0; i--) { 140 for (i = bucket->h.size-1; i >= 0; i--) {
141 __u64 w = crush_hash32_4(x, bucket->h.items[i], r, 141 __u64 w = crush_hash32_4(bucket->h.hash,x, bucket->h.items[i],
142 bucket->h.id); 142 r, bucket->h.id);
143 w &= 0xffff; 143 w &= 0xffff;
144 dprintk("list_choose i=%d x=%d r=%d item %d weight %x " 144 dprintk("list_choose i=%d x=%d r=%d item %d weight %x "
145 "sw %x rand %llx", 145 "sw %x rand %llx",
@@ -198,7 +198,8 @@ static int bucket_tree_choose(struct crush_bucket_tree *bucket,
198 while (!terminal(n)) { 198 while (!terminal(n)) {
199 /* pick point in [0, w) */ 199 /* pick point in [0, w) */
200 w = bucket->node_weights[n]; 200 w = bucket->node_weights[n];
201 t = (__u64)crush_hash32_4(x, n, r, bucket->h.id) * (__u64)w; 201 t = (__u64)crush_hash32_4(bucket->h.hash, x, n, r,
202 bucket->h.id) * (__u64)w;
202 t = t >> 32; 203 t = t >> 32;
203 204
204 /* descend to the left or right? */ 205 /* descend to the left or right? */
@@ -224,7 +225,7 @@ static int bucket_straw_choose(struct crush_bucket_straw *bucket,
224 __u64 draw; 225 __u64 draw;
225 226
226 for (i = 0; i < bucket->h.size; i++) { 227 for (i = 0; i < bucket->h.size; i++) {
227 draw = crush_hash32_3(x, bucket->h.items[i], r); 228 draw = crush_hash32_3(bucket->h.hash, x, bucket->h.items[i], r);
228 draw &= 0xffff; 229 draw &= 0xffff;
229 draw *= bucket->straws[i]; 230 draw *= bucket->straws[i];
230 if (i == 0 || draw > high_draw) { 231 if (i == 0 || draw > high_draw) {
@@ -267,7 +268,8 @@ static int is_out(struct crush_map *map, __u32 *weight, int item, int x)
267 return 0; 268 return 0;
268 if (weight[item] == 0) 269 if (weight[item] == 0)
269 return 1; 270 return 1;
270 if ((crush_hash32_2(x, item) & 0xffff) < weight[item]) 271 if ((crush_hash32_2(CRUSH_HASH_RJENKINS1, x, item) & 0xffff)
272 < weight[item])
271 return 0; 273 return 0;
272 return 1; 274 return 1;
273} 275}