summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-04-25 22:41:55 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2017-01-18 21:39:20 -0900
commit0a744dc46e969f531bc62abee28e670dd85a1eec (patch)
treebc8be278527f083cfab49a02aecb71efed508e61
parenta3b76d5b38af09034e07dbd036d034b850d959ec (diff)
bcache: fix promotion locking bug
promote path uses @k for replace key, but it pointed into unlocked btree node
-rw-r--r--drivers/md/bcache/fs-io.c7
-rw-r--r--drivers/md/bcache/io.c6
-rw-r--r--drivers/md/bcache/request.c6
3 files changed, 13 insertions, 6 deletions
diff --git a/drivers/md/bcache/fs-io.c b/drivers/md/bcache/fs-io.c
index add3db305fa9..fd1c751c2e57 100644
--- a/drivers/md/bcache/fs-io.c
+++ b/drivers/md/bcache/fs-io.c
@@ -642,17 +642,20 @@ static void bchfs_read(struct cache_set *c, struct bch_read_bio *rbio, u64 inode
for_each_btree_key_with_holes(&iter, c, BTREE_ID_EXTENTS,
POS(inode, bio->bi_iter.bi_sector), k) {
+ BKEY_PADDED(k) tmp;
struct extent_pick_ptr pick;
unsigned bytes, sectors;
bool is_last;
+ bkey_reassemble(&tmp.k, k);
+ bch_btree_iter_unlock(&iter);
+ k = bkey_i_to_s_c(&tmp.k);
+
if (!bkey_extent_is_allocation(k.k) ||
bkey_extent_is_compressed(c, k))
bch_mark_pages_unalloc(bio);
bch_extent_pick_ptr(c, k, &pick);
- bch_btree_iter_unlock(&iter);
-
if (IS_ERR(pick.ca)) {
bcache_io_error(c, bio, "no device to read from");
bio_endio(bio);
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index 06da65f2fbb3..3f30cbcb0492 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -1885,18 +1885,20 @@ static void bch_read_iter(struct cache_set *c, struct bch_read_bio *rbio,
for_each_btree_key_with_holes(&iter, c, BTREE_ID_EXTENTS,
POS(inode, bvec_iter.bi_sector), k) {
+ BKEY_PADDED(k) tmp;
struct extent_pick_ptr pick;
unsigned bytes, sectors;
bool is_last;
- bch_extent_pick_ptr(c, k, &pick);
-
/*
* Unlock the iterator while the btree node's lock is still in
* cache, before doing the IO:
*/
+ bkey_reassemble(&tmp.k, k);
+ k = bkey_i_to_s_c(&tmp.k);
bch_btree_iter_unlock(&iter);
+ bch_extent_pick_ptr(c, k, &pick);
if (IS_ERR(pick.ca)) {
bcache_io_error(c, bio, "no device to read from");
bio_endio(bio);
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 5ad20f2d87dc..97a2ba16fb1f 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -402,17 +402,19 @@ static void cached_dev_read(struct cached_dev *dc, struct search *s)
for_each_btree_key_with_holes(&iter, s->iop.c, BTREE_ID_EXTENTS,
POS(s->inode, bio->bi_iter.bi_sector), k) {
+ BKEY_PADDED(k) tmp;
struct extent_pick_ptr pick;
unsigned sectors, bytes;
bool is_last;
retry:
-
+ bkey_reassemble(&tmp.k, k);
+ bch_btree_iter_unlock(&iter);
+ k = bkey_i_to_s_c(&tmp.k);
bch_extent_pick_ptr(s->iop.c, k, &pick);
if (IS_ERR(pick.ca)) {
bcache_io_error(s->iop.c, bio,
"no device to read from");
- bch_btree_iter_unlock(&iter);
goto out;
}