mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
77c320eb46
commit
2d679fc756
|
@ -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,
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue