summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/md/bcache/alloc.c3
-rw-r--r--drivers/md/bcache/journal.c3
-rw-r--r--drivers/md/bcache/movinggc.c3
-rw-r--r--drivers/md/bcache/super.c41
4 files changed, 37 insertions, 13 deletions
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
index 7ced8ebc2611..ece8f5a1aadd 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -1423,6 +1423,9 @@ const char *bch_cache_allocator_start(struct cache *ca)
}
spin_unlock(&ca->freelist_lock);
+ if (cache_set_init_fault("alloc_start"))
+ return "dynamic fault";
+
if (!fifo_full(&ca->free[RESERVE_PRIO]))
return "couldn't find enough available buckets to write prios";
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 8dce022a2b57..ff903dc15ff6 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -604,6 +604,9 @@ int bch_cache_journal_alloc(struct cache *ca)
if (CACHE_TIER(&ca->mi) != 0)
return 0;
+ if (dynamic_fault("bcache:add:journal_alloc"))
+ return -ENOMEM;
+
/* clamp journal size to 512MB (in sectors) */
ret = bch_set_nr_journal_buckets(ca,
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 6af4c392581f..b8a248160324 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -323,6 +323,9 @@ int bch_moving_gc_thread_start(struct cache *ca)
if (ret)
return ret;
+ if (cache_set_init_fault("moving_gc_start"))
+ return -ENOMEM;
+
t = kthread_create(bch_moving_gc_thread, ca, "bch_copygc_read");
if (IS_ERR(t))
return PTR_ERR(t);
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index e1124224653a..6ee7ebc87706 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -299,7 +299,9 @@ static int __bch_super_realloc(struct bcache_superblock *sb, unsigned order)
if (!new_sb)
return -ENOMEM;
- bio = bio_kmalloc(GFP_KERNEL, 1 << order);
+ bio = (dynamic_fault("bcache:add:super_realloc")
+ ? NULL
+ : bio_kmalloc(GFP_KERNEL, 1 << order));
if (!bio) {
free_pages((unsigned long) new_sb, order);
return -ENOMEM;
@@ -1599,6 +1601,10 @@ static void bch_cache_free_work(struct work_struct *work)
pr_notice("%s removed", bdevname(ca->disk_sb.bdev, buf));
free_super(&ca->disk_sb);
+
+ if (ca->kobj.state_in_sysfs)
+ kobject_del(&ca->kobj);
+
kobject_put(&ca->kobj);
}
@@ -1870,16 +1876,19 @@ static const char *cache_alloc(struct bcache_superblock *sb,
size_t heap_size;
char buf[12];
unsigned i;
- const char *err;
+ const char *err = "cannot allocate memory";
struct cache *ca;
+ if (cache_set_init_fault("cache_alloc"))
+ return err;
+
ca = kzalloc(sizeof(*ca), GFP_KERNEL);
if (!ca)
- return "cannot allocate memory";
+ return err;
if (percpu_ref_init(&ca->ref, bch_cache_percpu_ref_release)) {
kfree(ca);
- return "cannot allocate memory";
+ return err;
}
kobject_init(&ca->kobj, &bch_cache_ktype);
@@ -1991,6 +2000,9 @@ static const char *cache_alloc(struct bcache_superblock *sb,
kobject_get(&c->kobj);
ca->set = c;
+ kobject_get(&ca->kobj);
+ rcu_assign_pointer(c->cache[ca->sb.nr_this_dev], ca);
+
bch_moving_init_cache(ca);
bch_tiering_init_cache(ca);
@@ -2004,9 +2016,6 @@ static const char *cache_alloc(struct bcache_superblock *sb,
sysfs_create_link(&c->kobj, &ca->kobj, buf))
goto err;
- kobject_get(&ca->kobj);
- rcu_assign_pointer(c->cache[ca->sb.nr_this_dev], ca);
-
if (ca->sb.seq > c->sb.seq)
cache_sb_to_cache_set(c, ca->disk_sb.sb);
@@ -2085,6 +2094,10 @@ int bch_cache_set_add_cache(struct cache_set *c, const char *path)
mutex_lock(&bch_register_lock);
down_read(&c->gc_lock);
+
+ if (dynamic_fault("bcache:add:no_slot"))
+ goto no_slot;
+
if (test_bit(CACHE_SET_GC_FAILURE, &c->flags))
goto no_slot;
@@ -2115,13 +2128,15 @@ have_slot:
sb.sb->u64s = u64s;
old_mi = c->members;
- new_mi = kzalloc(sizeof(struct cache_member_rcu) +
- sizeof(struct cache_member) * nr_in_set,
- GFP_KERNEL);
+ new_mi = (dynamic_fault("bcache:add:member_info_realloc")
+ ? NULL
+ : kzalloc(sizeof(struct cache_member_rcu) +
+ sizeof(struct cache_member) * nr_in_set,
+ GFP_KERNEL));
if (!new_mi) {
err = "cannot allocate memory";
ret = -ENOMEM;
- goto err_put;
+ goto err_unlock;
}
new_mi->nr_in_set = nr_in_set;
@@ -2140,7 +2155,7 @@ have_slot:
err = cache_alloc(&sb, c, &ca);
if (err)
- goto err;
+ goto err_unlock;
bcache_write_super(c);
@@ -2158,7 +2173,7 @@ have_slot:
mutex_unlock(&bch_register_lock);
return 0;
err_put:
- kobject_put(&ca->kobj);
+ bch_cache_stop(ca);
err_unlock:
mutex_unlock(&bch_register_lock);
err: