summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2015-01-19 19:13:31 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-07-26 00:24:52 -0800
commit6822af3b4852f1b07a1e26c25ad72a904e129753 (patch)
tree145ec1b9ae876ba931b533213192306bd29bf77c
parent1cd50128de0be46d91741f44a6e7e57b33146666 (diff)
bcache: Verify that there aren't multiple pointers to the same device
-rw-r--r--drivers/md/bcache/extents.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/md/bcache/extents.c b/drivers/md/bcache/extents.c
index 39060d2e03ca..8f2e5d596541 100644
--- a/drivers/md/bcache/extents.c
+++ b/drivers/md/bcache/extents.c
@@ -291,17 +291,23 @@ static void bch_ptr_swab(const struct bkey_format *f, struct bkey_packed *k)
d[i] = swab64(d[i]);
}
-static const char *extent_ptr_invalid(const struct cache_member_rcu *mi,
+static const char *extent_ptr_invalid(struct bkey_s_c_extent e,
+ const struct cache_member_rcu *mi,
const struct bch_extent_ptr *ptr,
unsigned size_ondisk)
{
+ const struct bch_extent_ptr *ptr2;
const struct cache_member_cpu *m = mi->m + ptr->dev;
if (ptr->dev > mi->nr_in_set || !m->valid)
return "pointer to invalid device";
+ extent_for_each_ptr(e, ptr2)
+ if (ptr != ptr2 && ptr->dev == ptr2->dev)
+ return "multiple pointers to same device";
+
if (ptr->offset + size_ondisk > m->bucket_size * m->nbuckets)
- return "offset past end of device";
+ return "offset past end of device";
if (ptr->offset < m->bucket_size * m->first_bucket)
return "offset before first bucket";
@@ -386,7 +392,7 @@ static const char *bch_btree_ptr_invalid(const struct cache_set *c,
mi = cache_member_info_get(c);
extent_for_each_ptr_crc(e, ptr, crc) {
- reason = extent_ptr_invalid(mi, ptr,
+ reason = extent_ptr_invalid(e, mi, ptr,
c->sb.btree_node_size);
if (reason) {
@@ -1390,7 +1396,8 @@ static const char *bch_extent_invalid(const struct cache_set *c,
goto invalid;
break;
case BCH_EXTENT_ENTRY_ptr:
- reason = extent_ptr_invalid(mi, &entry->ptr, size_ondisk);
+ reason = extent_ptr_invalid(e, mi,
+ &entry->ptr, size_ondisk);
if (reason)
goto invalid;
break;