summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSlava Pestov <sp@daterainc.com>2014-07-11 12:17:41 -0700
committerJiri Slaby <jslaby@suse.cz>2014-10-31 12:14:36 +0100
commit57c68d49b58d2c6c942dbc89d2c4fec2041e0e9e (patch)
treede8869629acb8e1177324fb7643066bbb3bf7df7 /drivers
parent2c30554fdfb22f41d66d6c5f4114147bc60a5fd9 (diff)
bcache: fix crash with incomplete cache set
commit bf0c55c986540483c34ca640f2eef4c3314388b1 upstream. Change-Id: I6abde52afe917633480caaf4e2518f42a816d886 Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/bcache/bcache.h4
-rw-r--r--drivers/md/bcache/super.c4
2 files changed, 8 insertions, 0 deletions
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 0f12382aa35d..7552207a479b 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -663,9 +663,13 @@ struct gc_stat {
* CACHE_SET_STOPPING always gets set first when we're closing down a cache set;
* we'll continue to run normally for awhile with CACHE_SET_STOPPING set (i.e.
* flushing dirty data).
+ *
+ * CACHE_SET_RUNNING means all cache devices have been registered and journal
+ * replay is complete.
*/
#define CACHE_SET_UNREGISTERING 0
#define CACHE_SET_STOPPING 1
+#define CACHE_SET_RUNNING 2
struct cache_set {
struct closure cl;
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 3a2ccf9b624b..f5004c5c4b96 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1235,6 +1235,9 @@ int bch_flash_dev_create(struct cache_set *c, uint64_t size)
if (test_bit(CACHE_SET_STOPPING, &c->flags))
return -EINTR;
+ if (!test_bit(CACHE_SET_RUNNING, &c->flags))
+ return -EPERM;
+
u = uuid_find_empty(c);
if (!u) {
pr_err("Can't create volume, no room for UUID");
@@ -1640,6 +1643,7 @@ static void run_cache_set(struct cache_set *c)
flash_devs_run(c);
+ set_bit(CACHE_SET_RUNNING, &c->flags);
return;
err_unlock_gc:
closure_set_stopped(&c->gc.cl);