diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2015-08-21 00:32:20 -0800 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2016-10-07 09:21:25 -0800 |
commit | ad6d9b7d545817af82f635659ca720377caab230 (patch) | |
tree | 5af37c3c1a75c88273151172d5b803b53d40874c | |
parent | c429d08d9667437f9cbb711c1072b6ea40a96053 (diff) |
bcache: don't overrun buffer in bch_data_insert()
Need to drop old stale pointers before adding new ones
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | drivers/md/bcache/extents.c | 43 | ||||
-rw-r--r-- | drivers/md/bcache/extents.h | 1 | ||||
-rw-r--r-- | drivers/md/bcache/request.c | 5 |
3 files changed, 29 insertions, 20 deletions
diff --git a/drivers/md/bcache/extents.c b/drivers/md/bcache/extents.c index 0ad774f66193..43b855d42fe9 100644 --- a/drivers/md/bcache/extents.c +++ b/drivers/md/bcache/extents.c @@ -102,14 +102,6 @@ static bool should_drop_ptr(struct cache_set *c, const struct bkey *k, ptr_stale(c, ca, k, ptr); } -static unsigned PTR_TIER(struct cache_set *c, const struct bkey *k, - unsigned ptr) -{ - unsigned dev = PTR_DEV(k, ptr); - - return dev < c->sb.nr_in_set ? CACHE_TIER(&c->members[dev]) : UINT_MAX; -} - unsigned bch_extent_nr_ptrs_after_normalize(struct cache_set *c, const struct bkey *k) { @@ -127,16 +119,9 @@ unsigned bch_extent_nr_ptrs_after_normalize(struct cache_set *c, return ret; } -bool bch_extent_normalize(struct cache_set *c, struct bkey *k) +void bch_extent_drop_stale(struct cache_set *c, struct bkey *k) { unsigned i = 0; - bool swapped; - - if (!KEY_SIZE(k)) { - bch_set_extent_ptrs(k, 0); - SET_KEY_DELETED(k, true); - return true; - } rcu_read_lock(); @@ -149,6 +134,30 @@ bool bch_extent_normalize(struct cache_set *c, struct bkey *k) } else i++; + rcu_read_unlock(); +} + +static unsigned PTR_TIER(struct cache_set *c, const struct bkey *k, + unsigned ptr) +{ + unsigned dev = PTR_DEV(k, ptr); + + return dev < c->sb.nr_in_set ? CACHE_TIER(&c->members[dev]) : UINT_MAX; +} + +bool bch_extent_normalize(struct cache_set *c, struct bkey *k) +{ + unsigned i; + bool swapped; + + if (!KEY_SIZE(k)) { + bch_set_extent_ptrs(k, 0); + SET_KEY_DELETED(k, true); + return true; + } + + bch_extent_drop_stale(c, k); + /* Bubble sort pointers by tier, lowest (fastest) tier first */ do { swapped = false; @@ -160,8 +169,6 @@ bool bch_extent_normalize(struct cache_set *c, struct bkey *k) } } while (swapped); - rcu_read_unlock(); - if (!bch_extent_ptrs(k)) SET_KEY_DELETED(k, true); diff --git a/drivers/md/bcache/extents.h b/drivers/md/bcache/extents.h index 0912064a4e07..e4bb64accc6b 100644 --- a/drivers/md/bcache/extents.h +++ b/drivers/md/bcache/extents.h @@ -25,6 +25,7 @@ struct cache *bch_extent_pick_ptr(struct cache_set *, const struct bkey *, unsigned bch_extent_nr_ptrs_after_normalize(struct cache_set *, const struct bkey *); +void bch_extent_drop_stale(struct cache_set *, struct bkey *); bool bch_extent_normalize(struct cache_set *, struct bkey *); static inline unsigned bch_extent_ptrs(const struct bkey *k) diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index f05a73dfdcbd..08f82223c0ef 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -318,11 +318,12 @@ static void bch_data_insert_start(struct closure *cl) (KEY_CSUM(&op->insert_key) ? 1 : 0))) continue_at(cl, bch_data_insert_keys, op->c->wq); - memset(ptrs_to_write, 0, sizeof(ptrs_to_write)); - k = op->insert_keys.top; bkey_copy(k, &op->insert_key); + bch_extent_drop_stale(op->c, k); + memset(ptrs_to_write, 0, sizeof(ptrs_to_write)); + b = op->moving_gc ? bch_gc_alloc_sectors(op->c, k, ptrs_to_write, cl) : bch_alloc_sectors(op->c, k, op->write_point, op->tier, |