diff options
author | Kent Overstreet <kmo@daterainc.com> | 2013-08-17 05:13:15 -0400 |
---|---|---|
committer | Kent Overstreet <kmo@daterainc.com> | 2013-11-11 00:55:55 -0500 |
commit | 2d679fc75678551485df62274edaed452becd16d (patch) | |
tree | 5ac694ced25578b0b54893f69d74bbcaa65b0b67 | |
parent | 77c320eb46e216c17aee5c943949229ccfed6904 (diff) |
bcache: Stripe size isn't necessarily a power of two
Originally I got this right... except that the divides didn't use
do_div(), which broke 32 bit kernels. When I went to fix that, I forgot
that the raid stripe size usually isn't a power of two... doh
Signed-off-by: Kent Overstreet <kmo@daterainc.com>
-rw-r--r-- | drivers/md/bcache/bcache.h | 2 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 7 | ||||
-rw-r--r-- | drivers/md/bcache/sysfs.c | 2 | ||||
-rw-r--r-- | drivers/md/bcache/writeback.c | 33 | ||||
-rw-r--r-- | drivers/md/bcache/writeback.h | 8 |
5 files changed, 27 insertions, 25 deletions
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 578615604be5..6e836f22f276 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h | |||
@@ -437,7 +437,7 @@ struct bcache_device { | |||
437 | int flush_done; | 437 | int flush_done; |
438 | 438 | ||
439 | uint64_t nr_stripes; | 439 | uint64_t nr_stripes; |
440 | unsigned stripe_size_bits; | 440 | unsigned stripe_size; |
441 | atomic_t *stripe_sectors_dirty; | 441 | atomic_t *stripe_sectors_dirty; |
442 | 442 | ||
443 | unsigned long sectors_dirty_last; | 443 | unsigned long sectors_dirty_last; |
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 74f2e902d876..d3169c0652f8 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c | |||
@@ -761,11 +761,10 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size, | |||
761 | struct request_queue *q; | 761 | struct request_queue *q; |
762 | size_t n; | 762 | size_t n; |
763 | 763 | ||
764 | if (!d->stripe_size_bits) | 764 | if (!d->stripe_size) |
765 | d->stripe_size_bits = 31; | 765 | d->stripe_size = 1 << 31; |
766 | 766 | ||
767 | d->nr_stripes = round_up(sectors, 1 << d->stripe_size_bits) >> | 767 | d->nr_stripes = DIV_ROUND_UP_ULL(sectors, d->stripe_size); |
768 | d->stripe_size_bits; | ||
769 | 768 | ||
770 | if (!d->nr_stripes || d->nr_stripes > SIZE_MAX / sizeof(atomic_t)) | 769 | if (!d->nr_stripes || d->nr_stripes > SIZE_MAX / sizeof(atomic_t)) |
771 | return -ENOMEM; | 770 | return -ENOMEM; |
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c index 4211d82179fc..b3a66f17231d 100644 --- a/drivers/md/bcache/sysfs.c +++ b/drivers/md/bcache/sysfs.c | |||
@@ -157,7 +157,7 @@ SHOW(__bch_cached_dev) | |||
157 | sysfs_hprint(dirty_data, | 157 | sysfs_hprint(dirty_data, |
158 | bcache_dev_sectors_dirty(&dc->disk) << 9); | 158 | bcache_dev_sectors_dirty(&dc->disk) << 9); |
159 | 159 | ||
160 | sysfs_hprint(stripe_size, (1 << dc->disk.stripe_size_bits) << 9); | 160 | sysfs_hprint(stripe_size, dc->disk.stripe_size << 9); |
161 | var_printf(partial_stripes_expensive, "%u"); | 161 | var_printf(partial_stripes_expensive, "%u"); |
162 | 162 | ||
163 | var_printf(sequential_merge, "%i"); | 163 | var_printf(sequential_merge, "%i"); |
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index ba3ee48320f2..b842fbfbf1db 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c | |||
@@ -114,25 +114,25 @@ static bool dirty_pred(struct keybuf *buf, struct bkey *k) | |||
114 | 114 | ||
115 | static bool dirty_full_stripe_pred(struct keybuf *buf, struct bkey *k) | 115 | static bool dirty_full_stripe_pred(struct keybuf *buf, struct bkey *k) |
116 | { | 116 | { |
117 | uint64_t stripe; | 117 | uint64_t stripe = KEY_START(k); |
118 | unsigned nr_sectors = KEY_SIZE(k); | 118 | unsigned nr_sectors = KEY_SIZE(k); |
119 | struct cached_dev *dc = container_of(buf, struct cached_dev, | 119 | struct cached_dev *dc = container_of(buf, struct cached_dev, |
120 | writeback_keys); | 120 | writeback_keys); |
121 | unsigned stripe_size = 1 << dc->disk.stripe_size_bits; | ||
122 | 121 | ||
123 | if (!KEY_DIRTY(k)) | 122 | if (!KEY_DIRTY(k)) |
124 | return false; | 123 | return false; |
125 | 124 | ||
126 | stripe = KEY_START(k) >> dc->disk.stripe_size_bits; | 125 | do_div(stripe, dc->disk.stripe_size); |
127 | while (1) { | ||
128 | if (atomic_read(dc->disk.stripe_sectors_dirty + stripe) != | ||
129 | stripe_size) | ||
130 | return false; | ||
131 | 126 | ||
132 | if (nr_sectors <= stripe_size) | 127 | while (1) { |
128 | if (atomic_read(dc->disk.stripe_sectors_dirty + stripe) == | ||
129 | dc->disk.stripe_size) | ||
133 | return true; | 130 | return true; |
134 | 131 | ||
135 | nr_sectors -= stripe_size; | 132 | if (nr_sectors <= dc->disk.stripe_size) |
133 | return false; | ||
134 | |||
135 | nr_sectors -= dc->disk.stripe_size; | ||
136 | stripe++; | 136 | stripe++; |
137 | } | 137 | } |
138 | } | 138 | } |
@@ -186,11 +186,12 @@ static void refill_dirty(struct closure *cl) | |||
186 | 186 | ||
187 | for (i = 0; i < dc->disk.nr_stripes; i++) | 187 | for (i = 0; i < dc->disk.nr_stripes; i++) |
188 | if (atomic_read(dc->disk.stripe_sectors_dirty + i) == | 188 | if (atomic_read(dc->disk.stripe_sectors_dirty + i) == |
189 | 1 << dc->disk.stripe_size_bits) | 189 | dc->disk.stripe_size) |
190 | goto full_stripes; | 190 | goto full_stripes; |
191 | 191 | ||
192 | goto normal_refill; | 192 | goto normal_refill; |
193 | full_stripes: | 193 | full_stripes: |
194 | searched_from_start = false; /* not searching entire btree */ | ||
194 | bch_refill_keybuf(dc->disk.c, buf, &end, | 195 | bch_refill_keybuf(dc->disk.c, buf, &end, |
195 | dirty_full_stripe_pred); | 196 | dirty_full_stripe_pred); |
196 | } else { | 197 | } else { |
@@ -252,19 +253,19 @@ void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode, | |||
252 | uint64_t offset, int nr_sectors) | 253 | uint64_t offset, int nr_sectors) |
253 | { | 254 | { |
254 | struct bcache_device *d = c->devices[inode]; | 255 | struct bcache_device *d = c->devices[inode]; |
255 | unsigned stripe_size, stripe_offset; | 256 | unsigned stripe_offset; |
256 | uint64_t stripe; | 257 | uint64_t stripe = offset; |
257 | 258 | ||
258 | if (!d) | 259 | if (!d) |
259 | return; | 260 | return; |
260 | 261 | ||
261 | stripe_size = 1 << d->stripe_size_bits; | 262 | do_div(stripe, d->stripe_size); |
262 | stripe = offset >> d->stripe_size_bits; | 263 | |
263 | stripe_offset = offset & (stripe_size - 1); | 264 | stripe_offset = offset & (d->stripe_size - 1); |
264 | 265 | ||
265 | while (nr_sectors) { | 266 | while (nr_sectors) { |
266 | int s = min_t(unsigned, abs(nr_sectors), | 267 | int s = min_t(unsigned, abs(nr_sectors), |
267 | stripe_size - stripe_offset); | 268 | d->stripe_size - stripe_offset); |
268 | 269 | ||
269 | if (nr_sectors < 0) | 270 | if (nr_sectors < 0) |
270 | s = -s; | 271 | s = -s; |
diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h index c91f61bb95b6..34961888b5a9 100644 --- a/drivers/md/bcache/writeback.h +++ b/drivers/md/bcache/writeback.h | |||
@@ -18,16 +18,18 @@ static inline bool bcache_dev_stripe_dirty(struct bcache_device *d, | |||
18 | uint64_t offset, | 18 | uint64_t offset, |
19 | unsigned nr_sectors) | 19 | unsigned nr_sectors) |
20 | { | 20 | { |
21 | uint64_t stripe = offset >> d->stripe_size_bits; | 21 | uint64_t stripe = offset; |
22 | |||
23 | do_div(stripe, d->stripe_size); | ||
22 | 24 | ||
23 | while (1) { | 25 | while (1) { |
24 | if (atomic_read(d->stripe_sectors_dirty + stripe)) | 26 | if (atomic_read(d->stripe_sectors_dirty + stripe)) |
25 | return true; | 27 | return true; |
26 | 28 | ||
27 | if (nr_sectors <= 1 << d->stripe_size_bits) | 29 | if (nr_sectors <= d->stripe_size) |
28 | return false; | 30 | return false; |
29 | 31 | ||
30 | nr_sectors -= 1 << d->stripe_size_bits; | 32 | nr_sectors -= d->stripe_size; |
31 | stripe++; | 33 | stripe++; |
32 | } | 34 | } |
33 | } | 35 | } |