summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-07-24 17:41:13 -0700
committerKent Overstreet <kmo@daterainc.com>2013-10-03 15:20:23 -0700
commit437a89b5d0bfbd5ae883e37c269982adf95de1e6 (patch)
tree61842bbd527113171d1c31421eaf73dc7536ceb4
parent045ea94f58c63b7209bd46742e9ac17f0d249cdd (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 7299c9f356b9..8b2fb169c6ac 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);