]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
bcache: Fix a journal replay bug
authorKent Overstreet <kmo@daterainc.com>
Fri, 11 Apr 2014 00:58:49 +0000 (17:58 -0700)
committerKent Overstreet <kmo@daterainc.com>
Mon, 4 Aug 2014 22:23:02 +0000 (15:23 -0700)
journal replay wansn't validating pointers with bch_extent_invalid() before
derefing, fixed

Signed-off-by: Kent Overstreet <kmo@daterainc.com>
drivers/md/bcache/extents.c
drivers/md/bcache/extents.h
drivers/md/bcache/journal.c

index 3a0de4cf9771031e9d4707fc49f356aee48b50e7..243de0bf15cdbf359965dff55cac4762b804362f 100644 (file)
@@ -474,9 +474,8 @@ static bool bch_extent_insert_fixup(struct btree_keys *b,
        return false;
 }
 
-static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
+bool __bch_extent_invalid(struct cache_set *c, const struct bkey *k)
 {
-       struct btree *b = container_of(bk, struct btree, keys);
        char buf[80];
 
        if (!KEY_SIZE(k))
@@ -485,16 +484,22 @@ static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
        if (KEY_SIZE(k) > KEY_OFFSET(k))
                goto bad;
 
-       if (__ptr_invalid(b->c, k))
+       if (__ptr_invalid(c, k))
                goto bad;
 
        return false;
 bad:
        bch_extent_to_text(buf, sizeof(buf), k);
-       cache_bug(b->c, "spotted extent %s: %s", buf, bch_ptr_status(b->c, k));
+       cache_bug(c, "spotted extent %s: %s", buf, bch_ptr_status(c, k));
        return true;
 }
 
+static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
+{
+       struct btree *b = container_of(bk, struct btree, keys);
+       return __bch_extent_invalid(b->c, k);
+}
+
 static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k,
                                     unsigned ptr)
 {
index e4e23409782d1957baacc8022e525d65aba7f094..e2ed54054e7a9106b50d0d2a3f6eb7967ce4e494 100644 (file)
@@ -9,5 +9,6 @@ struct cache_set;
 
 void bch_extent_to_text(char *, size_t, const struct bkey *);
 bool __bch_btree_ptr_invalid(struct cache_set *, const struct bkey *);
+bool __bch_extent_invalid(struct cache_set *, const struct bkey *);
 
 #endif /* _BCACHE_EXTENTS_H */
index 59e82021b5bb320d9c03606e35e0d5347417f1ff..363b88131f011ceea51bc6b1ebfe542e777347cd 100644 (file)
@@ -7,6 +7,7 @@
 #include "bcache.h"
 #include "btree.h"
 #include "debug.h"
+#include "extents.h"
 
 #include <trace/events/bcache.h>
 
@@ -291,15 +292,16 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list)
 
                for (k = i->j.start;
                     k < bset_bkey_last(&i->j);
-                    k = bkey_next(k)) {
-                       unsigned j;
+                    k = bkey_next(k))
+                       if (!__bch_extent_invalid(c, k)) {
+                               unsigned j;
 
-                       for (j = 0; j < KEY_PTRS(k); j++)
-                               if (ptr_available(c, k, j))
-                                       atomic_inc(&PTR_BUCKET(c, k, j)->pin);
+                               for (j = 0; j < KEY_PTRS(k); j++)
+                                       if (ptr_available(c, k, j))
+                                               atomic_inc(&PTR_BUCKET(c, k, j)->pin);
 
-                       bch_initial_mark_key(c, 0, k);
-               }
+                               bch_initial_mark_key(c, 0, k);
+                       }
        }
 }