Upgrade to 4.4.50-rt62
[kvmfornfv.git] / kernel / drivers / md / bcache / super.c
index 8d0ead9..3d5c0ba 100644 (file)
@@ -1015,8 +1015,12 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c)
         */
        atomic_set(&dc->count, 1);
 
-       if (bch_cached_dev_writeback_start(dc))
+       /* Block writeback thread, but spawn it */
+       down_write(&dc->writeback_lock);
+       if (bch_cached_dev_writeback_start(dc)) {
+               up_write(&dc->writeback_lock);
                return -ENOMEM;
+       }
 
        if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
                bch_sectors_dirty_init(dc);
@@ -1028,6 +1032,9 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c)
        bch_cached_dev_run(dc);
        bcache_device_link(&dc->disk, c, "bdev");
 
+       /* Allow the writeback thread to proceed */
+       up_write(&dc->writeback_lock);
+
        pr_info("Caching %s as %s on set %pU",
                bdevname(dc->bdev, buf), dc->disk.disk->disk_name,
                dc->disk.c->sb.set_uuid);
@@ -1366,6 +1373,9 @@ static void cache_set_flush(struct closure *cl)
        struct btree *b;
        unsigned i;
 
+       if (!c)
+               closure_return(cl);
+
        bch_cache_accounting_destroy(&c->accounting);
 
        kobject_put(&c->internal);
@@ -1808,7 +1818,7 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca)
        free = roundup_pow_of_two(ca->sb.nbuckets) >> 10;
 
        if (!init_fifo(&ca->free[RESERVE_BTREE], 8, GFP_KERNEL) ||
-           !init_fifo(&ca->free[RESERVE_PRIO], prio_buckets(ca), GFP_KERNEL) ||
+           !init_fifo_exact(&ca->free[RESERVE_PRIO], prio_buckets(ca), GFP_KERNEL) ||
            !init_fifo(&ca->free[RESERVE_MOVINGGC], free, GFP_KERNEL) ||
            !init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL) ||
            !init_fifo(&ca->free_inc,   free << 2, GFP_KERNEL) ||
@@ -1828,11 +1838,12 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca)
        return 0;
 }
 
-static void register_cache(struct cache_sb *sb, struct page *sb_page,
+static int register_cache(struct cache_sb *sb, struct page *sb_page,
                                struct block_device *bdev, struct cache *ca)
 {
        char name[BDEVNAME_SIZE];
-       const char *err = "cannot allocate memory";
+       const char *err = NULL;
+       int ret = 0;
 
        memcpy(&ca->sb, sb, sizeof(struct cache_sb));
        ca->bdev = bdev;
@@ -1847,27 +1858,35 @@ static void register_cache(struct cache_sb *sb, struct page *sb_page,
        if (blk_queue_discard(bdev_get_queue(ca->bdev)))
                ca->discard = CACHE_DISCARD(&ca->sb);
 
-       if (cache_alloc(sb, ca) != 0)
+       ret = cache_alloc(sb, ca);
+       if (ret != 0)
                goto err;
 
-       err = "error creating kobject";
-       if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache"))
-               goto err;
+       if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) {
+               err = "error calling kobject_add";
+               ret = -ENOMEM;
+               goto out;
+       }
 
        mutex_lock(&bch_register_lock);
        err = register_cache_set(ca);
        mutex_unlock(&bch_register_lock);
 
-       if (err)
-               goto err;
+       if (err) {
+               ret = -ENODEV;
+               goto out;
+       }
 
        pr_info("registered cache device %s", bdevname(bdev, name));
+
 out:
        kobject_put(&ca->kobj);
-       return;
+
 err:
-       pr_notice("error opening %s: %s", bdevname(bdev, name), err);
-       goto out;
+       if (err)
+               pr_notice("error opening %s: %s", bdevname(bdev, name), err);
+
+       return ret;
 }
 
 /* Global interfaces/init */
@@ -1965,7 +1984,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
                if (!ca)
                        goto err_close;
 
-               register_cache(sb, sb_page, bdev, ca);
+               if (register_cache(sb, sb_page, bdev, ca) != 0)
+                       goto err_close;
        }
 out:
        if (sb_page)