summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2015-02-11 14:20:12 -0800
committerKent Overstreet <kmo@daterainc.com>2015-02-12 23:44:11 -0800
commitd49160a317281562f2c64f4c46455e222feb1e70 (patch)
tree7e0cf762ef026a29e643b335e00bc63b91dea945
parentb354cf6ccab5f9934e88b8c2f91b47e2152f84b2 (diff)
downloadlinux-bcache-bcache-dev-february.tar.zst
bcache: Validate bkey formatbcache-dev-february
Change-Id: Ie30284518f55388925da92e7e0c4e13e77f54a90
-rw-r--r--drivers/md/bcache/bkey.c20
-rw-r--r--drivers/md/bcache/bkey.h1
-rw-r--r--drivers/md/bcache/btree.c4
3 files changed, 25 insertions, 0 deletions
diff --git a/drivers/md/bcache/bkey.c b/drivers/md/bcache/bkey.c
index ab3a034f407a..b60a2481f92e 100644
--- a/drivers/md/bcache/bkey.c
+++ b/drivers/md/bcache/bkey.c
@@ -296,6 +296,26 @@ struct bkey_format bch_bkey_format_done(struct bkey_format_state *s)
return ret;
}
+const char *bch_bkey_format_validate(struct bkey_format *f)
+{
+ unsigned i, bits = KEY_PACKED_BITS_START;
+
+ if (f->nr_fields != BKEY_NR_FIELDS)
+ return "invalid format: incorrect number of fields";
+
+ for (i = 0; i < f->nr_fields; i++) {
+ if (f->bits_per_field[i] > 64)
+ return "invalid format: field too large";
+
+ bits += f->bits_per_field[i];
+ }
+
+ if (f->key_u64s != DIV_ROUND_UP(bits, 64))
+ return "invalid format: incorrect key_u64s";
+
+ return NULL;
+}
+
/* Most significant differing bit */
unsigned bkey_greatest_differing_bit(const struct bkey_format *format,
const struct bkey_packed *l_k,
diff --git a/drivers/md/bcache/bkey.h b/drivers/md/bcache/bkey.h
index 666920d080f6..6ab9203b2fb0 100644
--- a/drivers/md/bcache/bkey.h
+++ b/drivers/md/bcache/bkey.h
@@ -57,6 +57,7 @@ void bch_bkey_format_init(struct bkey_format_state *);
void bch_bkey_format_add_key(struct bkey_format_state *, struct bkey *);
void bch_bkey_format_add_pos(struct bkey_format_state *, struct bpos);
struct bkey_format bch_bkey_format_done(struct bkey_format_state *);
+const char *bch_bkey_format_validate(struct bkey_format *);
unsigned bkey_greatest_differing_bit(const struct bkey_format *,
const struct bkey_packed *,
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index c4f9851b8b78..1ca4629ee08e 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -348,6 +348,10 @@ void bch_btree_node_read_done(struct btree *b, struct cache *ca,
if (BSET_BTREE_LEVEL(i) != b->level)
goto err;
+ err = bch_bkey_format_validate(&b->data->format);
+ if (err)
+ goto err;
+
b->keys.format = b->data->format;
b->keys.set->data = &b->data->keys;