summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-07-24 17:41:13 -0700
committerKent Overstreet <kmo@daterainc.com>2013-11-10 21:56:08 -0800
commitcc23196631fbcd1bc3eafedbb712413fdbf946a3 (patch)
tree92f606edf7dc4b83ec5d1438f6e33b28e12af7bc
parent2c1953e201a05ddfb1ea53f23d81a492c6513028 (diff)
bcache: Clean up cache_lookup_fn
There was some looping in submit_partial_cache_hit() and submit_partial_cache_hit() that isn't needed anymore - originally, we wouldn't necessarily process the full hit or miss all at once because when splitting the bio, we took into account the restrictions of the device we were sending it to. But, device bio size restrictions are now handled elsewhere, with a wrapper around generic_make_request() - so that looping has been unnecessary for awhile now and we can now do quite a bit of cleanup. And if we trim the key we're reading from to match the subset we're actually reading, we don't have to explicitly calculate bi_sector anymore. Neat. Signed-off-by: Kent Overstreet <kmo@daterainc.com>
-rw-r--r--drivers/md/bcache/request.c108
1 files changed, 46 insertions, 62 deletions
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 854743e85e76..de3fc76ffcfc 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -663,86 +663,70 @@ static void bch_cache_read_endio(struct bio *bio, int error)
bch_bbio_endio(s->op.c, bio, error, "reading from cache");
}
-static int submit_partial_cache_miss(struct btree *b, struct search *s,
- struct bkey *k)
-{
- struct bio *bio = &s->bio.bio;
- int ret = MAP_CONTINUE;
-
- do {
- unsigned sectors = INT_MAX;
-
- if (KEY_INODE(k) == s->op.inode) {
- if (KEY_START(k) <= bio->bi_sector)
- break;
-
- sectors = min_t(uint64_t, sectors,
- KEY_START(k) - bio->bi_sector);
- }
-
- ret = s->d->cache_miss(b, s, bio, sectors);
- } while (ret == MAP_CONTINUE);
-
- return ret;
-}
-
/*
* Read from a single key, handling the initial cache miss if the key starts in
* the middle of the bio
*/
-static int submit_partial_cache_hit(struct btree_op *op, struct btree *b,
- struct bkey *k)
+static int cache_lookup_fn(struct btree_op *op, struct btree *b, struct bkey *k)
{
struct search *s = container_of(op, struct search, op);
- struct bio *bio = &s->bio.bio;
+ struct bio *n, *bio = &s->bio.bio;
+ struct bkey *bio_key;
unsigned ptr;
- struct bio *n;
- int ret = submit_partial_cache_miss(b, s, k);
- if (ret != MAP_CONTINUE || !KEY_SIZE(k))
- return ret;
+ if (bkey_cmp(k, &KEY(op->inode, bio->bi_sector, 0)) <= 0)
+ return MAP_CONTINUE;
+
+ if (KEY_INODE(k) != s->op.inode ||
+ KEY_START(k) > bio->bi_sector) {
+ unsigned bio_sectors = bio_sectors(bio);
+ unsigned sectors = KEY_INODE(k) == s->op.inode
+ ? min_t(uint64_t, INT_MAX,
+ KEY_START(k) - bio->bi_sector)
+ : INT_MAX;
+
+ int ret = s->d->cache_miss(b, s, bio, sectors);
+ if (ret != MAP_CONTINUE)
+ return ret;
+
+ /* if this was a complete miss we shouldn't get here */
+ BUG_ON(bio_sectors <= sectors);
+ }
+
+ if (!KEY_SIZE(k))
+ return MAP_CONTINUE;
/* XXX: figure out best pointer - for multiple cache devices */
ptr = 0;
PTR_BUCKET(b->c, k, ptr)->prio = INITIAL_PRIO;
- while (ret == MAP_CONTINUE &&
- KEY_INODE(k) == op->inode &&
- bio->bi_sector < KEY_OFFSET(k)) {
- struct bkey *bio_key;
- sector_t sector = PTR_OFFSET(k, ptr) +
- (bio->bi_sector - KEY_START(k));
- unsigned sectors = min_t(uint64_t, INT_MAX,
- KEY_OFFSET(k) - bio->bi_sector);
-
- n = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split);
- if (n == bio)
- ret = MAP_DONE;
-
- bio_key = &container_of(n, struct bbio, bio)->key;
+ n = bch_bio_split(bio, min_t(uint64_t, INT_MAX,
+ KEY_OFFSET(k) - bio->bi_sector),
+ GFP_NOIO, s->d->bio_split);
- /*
- * The bucket we're reading from might be reused while our bio
- * is in flight, and we could then end up reading the wrong
- * data.
- *
- * We guard against this by checking (in cache_read_endio()) if
- * the pointer is stale again; if so, we treat it as an error
- * and reread from the backing device (but we don't pass that
- * error up anywhere).
- */
+ bio_key = &container_of(n, struct bbio, bio)->key;
+ bch_bkey_copy_single_ptr(bio_key, k, ptr);
- bch_bkey_copy_single_ptr(bio_key, k, ptr);
- SET_PTR_OFFSET(bio_key, 0, sector);
+ bch_cut_front(&KEY(s->op.inode, n->bi_sector, 0), bio_key);
+ bch_cut_back(&KEY(s->op.inode, bio_end_sector(n), 0), bio_key);
- n->bi_end_io = bch_cache_read_endio;
- n->bi_private = &s->cl;
+ n->bi_end_io = bch_cache_read_endio;
+ n->bi_private = &s->cl;
- __bch_submit_bbio(n, b->c);
- }
+ /*
+ * The bucket we're reading from might be reused while our bio
+ * is in flight, and we could then end up reading the wrong
+ * data.
+ *
+ * We guard against this by checking (in cache_read_endio()) if
+ * the pointer is stale again; if so, we treat it as an error
+ * and reread from the backing device (but we don't pass that
+ * error up anywhere).
+ */
- return ret;
+ __bch_submit_bbio(n, b->c);
+ return n == bio ? MAP_DONE : MAP_CONTINUE;
}
static void cache_lookup(struct closure *cl)
@@ -753,7 +737,7 @@ static void cache_lookup(struct closure *cl)
int ret = bch_btree_map_keys(op, op->c,
&KEY(op->inode, bio->bi_sector, 0),
- submit_partial_cache_hit, 1);
+ cache_lookup_fn, MAP_END_KEY);
if (ret == -EAGAIN)
continue_at(cl, cache_lookup, bcache_wq);