Commit 2d679fc7 authored by Kent Overstreet's avatar Kent Overstreet

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: default avatarKent Overstreet <kmo@daterainc.com>
parent 77c320eb
...@@ -437,7 +437,7 @@ struct bcache_device { ...@@ -437,7 +437,7 @@ struct bcache_device {
int flush_done; int flush_done;
uint64_t nr_stripes; uint64_t nr_stripes;
unsigned stripe_size_bits; unsigned stripe_size;
atomic_t *stripe_sectors_dirty; atomic_t *stripe_sectors_dirty;
unsigned long sectors_dirty_last; unsigned long sectors_dirty_last;
......
...@@ -761,11 +761,10 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size, ...@@ -761,11 +761,10 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
struct request_queue *q; struct request_queue *q;
size_t n; size_t n;
if (!d->stripe_size_bits) if (!d->stripe_size)
d->stripe_size_bits = 31; d->stripe_size = 1 << 31;
d->nr_stripes = round_up(sectors, 1 << d->stripe_size_bits) >> d->nr_stripes = DIV_ROUND_UP_ULL(sectors, d->stripe_size);
d->stripe_size_bits;
if (!d->nr_stripes || d->nr_stripes > SIZE_MAX / sizeof(atomic_t)) if (!d->nr_stripes || d->nr_stripes > SIZE_MAX / sizeof(atomic_t))
return -ENOMEM; return -ENOMEM;
......
...@@ -157,7 +157,7 @@ SHOW(__bch_cached_dev) ...@@ -157,7 +157,7 @@ SHOW(__bch_cached_dev)
sysfs_hprint(dirty_data, sysfs_hprint(dirty_data,
bcache_dev_sectors_dirty(&dc->disk) << 9); bcache_dev_sectors_dirty(&dc->disk) << 9);
sysfs_hprint(stripe_size, (1 << dc->disk.stripe_size_bits) << 9); sysfs_hprint(stripe_size, dc->disk.stripe_size << 9);
var_printf(partial_stripes_expensive, "%u"); var_printf(partial_stripes_expensive, "%u");
var_printf(sequential_merge, "%i"); var_printf(sequential_merge, "%i");
......
...@@ -114,25 +114,25 @@ static bool dirty_pred(struct keybuf *buf, struct bkey *k) ...@@ -114,25 +114,25 @@ static bool dirty_pred(struct keybuf *buf, struct bkey *k)
static bool dirty_full_stripe_pred(struct keybuf *buf, struct bkey *k) static bool dirty_full_stripe_pred(struct keybuf *buf, struct bkey *k)
{ {
uint64_t stripe; uint64_t stripe = KEY_START(k);
unsigned nr_sectors = KEY_SIZE(k); unsigned nr_sectors = KEY_SIZE(k);
struct cached_dev *dc = container_of(buf, struct cached_dev, struct cached_dev *dc = container_of(buf, struct cached_dev,
writeback_keys); writeback_keys);
unsigned stripe_size = 1 << dc->disk.stripe_size_bits;
if (!KEY_DIRTY(k)) if (!KEY_DIRTY(k))
return false; return false;
stripe = KEY_START(k) >> dc->disk.stripe_size_bits; do_div(stripe, dc->disk.stripe_size);
while (1) {
if (atomic_read(dc->disk.stripe_sectors_dirty + stripe) !=
stripe_size)
return false;
if (nr_sectors <= stripe_size) while (1) {
if (atomic_read(dc->disk.stripe_sectors_dirty + stripe) ==
dc->disk.stripe_size)
return true; return true;
nr_sectors -= stripe_size; if (nr_sectors <= dc->disk.stripe_size)
return false;
nr_sectors -= dc->disk.stripe_size;
stripe++; stripe++;
} }
} }
...@@ -186,11 +186,12 @@ static void refill_dirty(struct closure *cl) ...@@ -186,11 +186,12 @@ static void refill_dirty(struct closure *cl)
for (i = 0; i < dc->disk.nr_stripes; i++) for (i = 0; i < dc->disk.nr_stripes; i++)
if (atomic_read(dc->disk.stripe_sectors_dirty + i) == if (atomic_read(dc->disk.stripe_sectors_dirty + i) ==
1 << dc->disk.stripe_size_bits) dc->disk.stripe_size)
goto full_stripes; goto full_stripes;
goto normal_refill; goto normal_refill;
full_stripes: full_stripes:
searched_from_start = false; /* not searching entire btree */
bch_refill_keybuf(dc->disk.c, buf, &end, bch_refill_keybuf(dc->disk.c, buf, &end,
dirty_full_stripe_pred); dirty_full_stripe_pred);
} else { } else {
...@@ -252,19 +253,19 @@ void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode, ...@@ -252,19 +253,19 @@ void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
uint64_t offset, int nr_sectors) uint64_t offset, int nr_sectors)
{ {
struct bcache_device *d = c->devices[inode]; struct bcache_device *d = c->devices[inode];
unsigned stripe_size, stripe_offset; unsigned stripe_offset;
uint64_t stripe; uint64_t stripe = offset;
if (!d) if (!d)
return; return;
stripe_size = 1 << d->stripe_size_bits; do_div(stripe, d->stripe_size);
stripe = offset >> d->stripe_size_bits;
stripe_offset = offset & (stripe_size - 1); stripe_offset = offset & (d->stripe_size - 1);
while (nr_sectors) { while (nr_sectors) {
int s = min_t(unsigned, abs(nr_sectors), int s = min_t(unsigned, abs(nr_sectors),
stripe_size - stripe_offset); d->stripe_size - stripe_offset);
if (nr_sectors < 0) if (nr_sectors < 0)
s = -s; s = -s;
......
...@@ -18,16 +18,18 @@ static inline bool bcache_dev_stripe_dirty(struct bcache_device *d, ...@@ -18,16 +18,18 @@ static inline bool bcache_dev_stripe_dirty(struct bcache_device *d,
uint64_t offset, uint64_t offset,
unsigned nr_sectors) unsigned nr_sectors)
{ {
uint64_t stripe = offset >> d->stripe_size_bits; uint64_t stripe = offset;
do_div(stripe, d->stripe_size);
while (1) { while (1) {
if (atomic_read(d->stripe_sectors_dirty + stripe)) if (atomic_read(d->stripe_sectors_dirty + stripe))
return true; return true;
if (nr_sectors <= 1 << d->stripe_size_bits) if (nr_sectors <= d->stripe_size)
return false; return false;
nr_sectors -= 1 << d->stripe_size_bits; nr_sectors -= d->stripe_size;
stripe++; stripe++;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment